From 74a592e5867a375f1705654c1112d7c9ac784ddf Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Fri, 6 Sep 2024 14:32:28 -0400 Subject: [PATCH 001/224] feat: Add ownerCollateral support into Token.ts & TokenStandard.ts (#4446) ### Description Adds CollateralFiat to token mapping which will output the correct `standard` to the warp deploy artifact. ### Backward compatibility Yes ### Testing Manual --- .changeset/eighty-candles-press.md | 5 +++++ typescript/sdk/src/token/Token.test.ts | 9 +++++++++ typescript/sdk/src/token/Token.ts | 4 ++++ typescript/sdk/src/token/TokenStandard.ts | 5 ++++- 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 .changeset/eighty-candles-press.md diff --git a/.changeset/eighty-candles-press.md b/.changeset/eighty-candles-press.md new file mode 100644 index 000000000..5f397e18a --- /dev/null +++ b/.changeset/eighty-candles-press.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Adds OwnerCollateral to token mapping which will output the correct standard to the warp deploy artifact. diff --git a/typescript/sdk/src/token/Token.test.ts b/typescript/sdk/src/token/Token.test.ts index 4085bf137..8fe6ec332 100644 --- a/typescript/sdk/src/token/Token.test.ts +++ b/typescript/sdk/src/token/Token.test.ts @@ -47,6 +47,15 @@ const STANDARD_TO_TOKEN: Record = { symbol: 'USDC', name: 'USDC', }, + [TokenStandard.EvmHypOwnerCollateral]: { + chainName: TestChainName.test3, + standard: TokenStandard.EvmHypOwnerCollateral, + addressOrDenom: '0x31b5234A896FbC4b3e2F7237592D054716762131', + collateralAddressOrDenom: '0x64544969ed7ebf5f083679233325356ebe738930', + decimals: 18, + symbol: 'USDC', + name: 'USDC', + }, [TokenStandard.EvmHypCollateralFiat]: { chainName: TestChainName.test3, standard: TokenStandard.EvmHypCollateralFiat, diff --git a/typescript/sdk/src/token/Token.ts b/typescript/sdk/src/token/Token.ts index cf9d5e65d..1f24d6b5e 100644 --- a/typescript/sdk/src/token/Token.ts +++ b/typescript/sdk/src/token/Token.ts @@ -215,6 +215,10 @@ export class Token implements IToken { return new EvmHypCollateralAdapter(chainName, multiProvider, { token: addressOrDenom, }); + } else if (standard === TokenStandard.EvmHypOwnerCollateral) { + return new EvmHypCollateralAdapter(chainName, multiProvider, { + token: addressOrDenom, + }); } else if (standard === TokenStandard.EvmHypSynthetic) { return new EvmHypSyntheticAdapter(chainName, multiProvider, { token: addressOrDenom, diff --git a/typescript/sdk/src/token/TokenStandard.ts b/typescript/sdk/src/token/TokenStandard.ts index 2605b9b3c..002501d32 100644 --- a/typescript/sdk/src/token/TokenStandard.ts +++ b/typescript/sdk/src/token/TokenStandard.ts @@ -14,6 +14,7 @@ export enum TokenStandard { EvmNative = 'EvmNative', EvmHypNative = 'EvmHypNative', EvmHypCollateral = 'EvmHypCollateral', + EvmHypOwnerCollateral = 'EvmHypOwnerCollateral', EvmHypCollateralFiat = 'EvmHypCollateralFiat', EvmHypSynthetic = 'EvmHypSynthetic', EvmHypXERC20 = 'EvmHypXERC20', @@ -50,6 +51,7 @@ export const TOKEN_STANDARD_TO_PROTOCOL: Record = { EvmNative: ProtocolType.Ethereum, EvmHypNative: ProtocolType.Ethereum, EvmHypCollateral: ProtocolType.Ethereum, + EvmHypOwnerCollateral: ProtocolType.Ethereum, EvmHypCollateralFiat: ProtocolType.Ethereum, EvmHypSynthetic: ProtocolType.Ethereum, EvmHypXERC20: ProtocolType.Ethereum, @@ -111,6 +113,7 @@ export const TOKEN_HYP_STANDARDS = [ TokenStandard.EvmHypNative, TokenStandard.EvmHypCollateral, TokenStandard.EvmHypCollateralFiat, + TokenStandard.EvmHypOwnerCollateral, TokenStandard.EvmHypSynthetic, TokenStandard.EvmHypXERC20, TokenStandard.EvmHypXERC20Lockbox, @@ -144,7 +147,7 @@ export const TOKEN_TYPE_TO_STANDARD: Record = { [TokenType.collateralFiat]: TokenStandard.EvmHypCollateralFiat, [TokenType.XERC20]: TokenStandard.EvmHypXERC20, [TokenType.XERC20Lockbox]: TokenStandard.EvmHypXERC20Lockbox, - [TokenType.collateralVault]: TokenStandard.EvmHypCollateral, + [TokenType.collateralVault]: TokenStandard.EvmHypOwnerCollateral, [TokenType.collateralUri]: TokenStandard.EvmHypCollateral, [TokenType.fastCollateral]: TokenStandard.EvmHypCollateral, [TokenType.synthetic]: TokenStandard.EvmHypSynthetic, From 88d4c397019d39ed868d890471e55517a0a707af Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:29:24 +0100 Subject: [PATCH 002/224] fix: temporarily disable dry-run in cli-advanced-e2e (#4458) fix: temporarily disable dry-run in cli-advanced-e2e - until we fix the problem with our call to `resetFork` after a dry-run deployment - our CI uses the latest nightly foundry releases, and this recent PR https://github.com/foundry-rs/foundry/pull/8768 has broken the fork reset. Ironically, this PR actually is a bugfix for something that was broken that we relied on. Examples of failures: - https://github.com/hyperlane-xyz/hyperlane-monorepo/actions/runs/10772795435/job/29873480020?pr=4441#step:12:133 - https://github.com/hyperlane-xyz/hyperlane-monorepo/actions/runs/10751285630/job/29818541086?pr=4448 Note that the `pi_with_core_chain` tests don't fail because they do not do a dry run --- typescript/cli/ci-advanced-test.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/typescript/cli/ci-advanced-test.sh b/typescript/cli/ci-advanced-test.sh index eaf9cfabf..bc250cd5e 100755 --- a/typescript/cli/ci-advanced-test.sh +++ b/typescript/cli/ci-advanced-test.sh @@ -25,10 +25,10 @@ _main() { DEPLOYER=$(cast rpc eth_accounts | jq -r '.[0]'); - run_hyperlane_deploy_core_dry_run; - run_hyperlane_deploy_warp_dry_run; - - reset_anvil; + # TODO: fix `resetFork` after a dry-run. Related: https://github.com/foundry-rs/foundry/pull/8768 + # run_hyperlane_deploy_core_dry_run; + # run_hyperlane_deploy_warp_dry_run; + # reset_anvil; run_hyperlane_deploy_core; run_hyperlane_deploy_warp; From 03d2595121ec0af8f41126076a08d5224b14282c Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Mon, 9 Sep 2024 17:52:40 +0100 Subject: [PATCH 003/224] chore: update mainnet3 key funder deployment (#4461) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/infra/config/environments/mainnet3/funding.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index fbb7555c4..2ac22ab64 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '72d498f-20240828-092240', + tag: '74a592e-20240906-191211', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron From d4204c6f0ad46b01e8c6c010d72eae794de72c8f Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:07:48 +0100 Subject: [PATCH 004/224] chore: revert to using a 10 min relayer `CONFIRM_DELAY` (#4452) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/agents/relayer/src/msg/pending_message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/agents/relayer/src/msg/pending_message.rs b/rust/agents/relayer/src/msg/pending_message.rs index 02ca48e13..a65fde909 100644 --- a/rust/agents/relayer/src/msg/pending_message.rs +++ b/rust/agents/relayer/src/msg/pending_message.rs @@ -28,7 +28,7 @@ pub const CONFIRM_DELAY: Duration = if cfg!(any(test, feature = "test-utils")) { Duration::from_secs(5) } else { // Wait 1 min after submitting the message before confirming in normal/production mode - Duration::from_secs(60) + Duration::from_secs(60 * 10) }; /// The message context contains the links needed to submit a message. Each From a75e84af4def06dd11a3da40841812a78679f5d2 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:08:12 +0100 Subject: [PATCH 005/224] chore: rm leftover printlines (#4448) ### Description Noticed these when I was debugging the scroll delivery issues ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../src/rpc_clients/trait_builder.rs | 2 -- .../infra/config/environments/mainnet3/agent.ts | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/rust/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs b/rust/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs index 440e46368..67bad0893 100644 --- a/rust/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs +++ b/rust/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs @@ -213,13 +213,11 @@ pub trait BuildableWithProvider { M: Middleware + 'static, { Ok(if let Some(signer) = signer { - println!("Building provider with signer"); let signing_provider = wrap_with_signer(provider, signer) .await .map_err(ChainCommunicationError::from_other)?; self.build_with_provider(signing_provider, conn, locator) } else { - println!("Building provider without signer"); self.build_with_provider(provider, conn, locator) } .await) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 556d928bf..7e69f486d 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -372,7 +372,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '1cb1916-20240902-171411', + tag: '74a592e-20240906-191210', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -381,7 +381,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: '1cb1916-20240902-171411', + tag: '74a592e-20240906-191210', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -391,7 +391,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '707db4a-20240828-164024', + tag: '74a592e-20240906-191210', }, resources: scraperResources, }, @@ -406,7 +406,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '78b596e-20240813-123401', + tag: '74a592e-20240906-191210', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. @@ -418,7 +418,7 @@ const releaseCandidate: RootAgentConfig = { validators: { docker: { repo, - tag: '0d12ff3-20240620-173353', + tag: '74a592e-20240906-191210', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.ReleaseCandidate), @@ -439,7 +439,7 @@ const neutron: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '707db4a-20240828-164024', + tag: '74a592e-20240906-191210', }, gasPaymentEnforcement: [ { From a19e882fd3d14c5e84f10abe9d1feb0a33a9e64b Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:13:03 +0100 Subject: [PATCH 006/224] feat: improve Router enrollment with Checker/Governor (#4441) feat: improve Router enrollment with Checker/Governor - aggregate violations into a single RouterViolation with the diff in router enrollments - reduces number of txs to do the enrollment - now supports ICA router enrollment of chains that we haven't enrolled - previously we would only iterate over the set of routers already onchain, and no attention was paid to new domains example call for `ica`: ![image](https://github.com/user-attachments/assets/5557d2f4-41e5-45ee-b318-e4cf8d510069) example call for `haas`: ![image](https://github.com/user-attachments/assets/fec0e41b-e0ef-43a0-a17c-3f77c0756f8a) --- .changeset/chatty-plums-invite.md | 5 +++ .../infra/src/govern/HyperlaneAppGovernor.ts | 11 ++--- .../infra/src/govern/ProxiedRouterGovernor.ts | 23 ++++++++--- .../middleware/account/InterchainAccount.ts | 6 +++ .../sdk/src/router/HyperlaneRouterChecker.ts | 40 +++++++++++++++---- typescript/sdk/src/router/RouterApps.ts | 4 +- typescript/sdk/src/router/types.ts | 10 +++-- 7 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 .changeset/chatty-plums-invite.md diff --git a/.changeset/chatty-plums-invite.md b/.changeset/chatty-plums-invite.md new file mode 100644 index 000000000..e610e8836 --- /dev/null +++ b/.changeset/chatty-plums-invite.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Improve Router Checker/Governor tooling to support enrolling multiple routers for missing domains diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index 64e4d0655..c6ca3d87f 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -111,11 +111,12 @@ export abstract class HyperlaneAppGovernor< console.log( `> ${calls.length} calls will be submitted via ${SubmissionType[submissionType]}`, ); - calls.map((c) => - console.log( - `> > ${c.description} (to: ${c.to} data: ${c.data}) value: ${c.value}`, - ), - ); + calls.map((c) => { + console.log(`> > ${c.description}`); + console.log(`> > > to: ${c.to}`); + console.log(`> > > data: ${c.data}`); + console.log(`> > > value: ${c.value}`); + }); if (!requestConfirmation) return true; const { value: confirmed } = await prompts({ diff --git a/typescript/infra/src/govern/ProxiedRouterGovernor.ts b/typescript/infra/src/govern/ProxiedRouterGovernor.ts index 6a5dfe655..304f20761 100644 --- a/typescript/infra/src/govern/ProxiedRouterGovernor.ts +++ b/typescript/infra/src/govern/ProxiedRouterGovernor.ts @@ -12,6 +12,7 @@ import { RouterViolationType, ViolationType, } from '@hyperlane-xyz/sdk'; +import { stringifyObject } from '@hyperlane-xyz/utils'; import { HyperlaneAppGovernor } from './HyperlaneAppGovernor.js'; @@ -54,19 +55,29 @@ export class ProxiedRouterGovernor< } protected handleEnrolledRouterViolation(violation: RouterViolation) { - const remoteDomain = this.checker.multiProvider.getDomainId( - violation.remoteChain, - ); + const expectedDomains: number[] = []; + const expectedAddresses: string[] = []; + + for (const [remoteChain, routerDiff] of Object.entries( + violation.routerDiff, + )) { + const remoteDomain = this.checker.multiProvider.getDomainId(remoteChain); + expectedDomains.push(remoteDomain); + expectedAddresses.push(routerDiff.expected); + } + return { chain: violation.chain, call: { to: violation.contract.address, data: violation.contract.interface.encodeFunctionData( - 'enrollRemoteRouter', - [remoteDomain, violation.expected], + 'enrollRemoteRouters', + [expectedDomains, expectedAddresses], ), value: BigNumber.from(0), - description: `Enroll router for remote chain ${violation.remoteChain} (${remoteDomain}) ${violation.expected} in ${violation.contract.address}`, + description: `Updating routers in ${violation.contract.address} for ${ + expectedDomains.length + } remote chains:\n${stringifyObject(violation.routerDiff, 'yaml')}`, }, }; } diff --git a/typescript/sdk/src/middleware/account/InterchainAccount.ts b/typescript/sdk/src/middleware/account/InterchainAccount.ts index 67ec07754..273efb587 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccount.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccount.ts @@ -31,6 +31,12 @@ export class InterchainAccount extends RouterApp { super(contractsMap, multiProvider); } + override async remoteChains(chainName: string): Promise { + return Object.keys(this.contractsMap).filter( + (chain) => chain !== chainName, + ); + } + router( contracts: HyperlaneContracts, ): InterchainAccountRouter { diff --git a/typescript/sdk/src/router/HyperlaneRouterChecker.ts b/typescript/sdk/src/router/HyperlaneRouterChecker.ts index 492b3f655..2dde30791 100644 --- a/typescript/sdk/src/router/HyperlaneRouterChecker.ts +++ b/typescript/sdk/src/router/HyperlaneRouterChecker.ts @@ -1,6 +1,12 @@ import { ethers } from 'ethers'; -import { addressToBytes32, assert, eqAddress } from '@hyperlane-xyz/utils'; +import { + AddressBytes32, + addressToBytes32, + assert, + eqAddress, + rootLogger, +} from '@hyperlane-xyz/utils'; import { HyperlaneFactories } from '../contracts/types.js'; import { HyperlaneAppChecker } from '../deploy/HyperlaneAppChecker.js'; @@ -29,6 +35,7 @@ export class HyperlaneRouterChecker< app: App, configMap: ChainMap, readonly ismFactory?: HyperlaneIsmFactory, + readonly logger = rootLogger.child({ module: 'HyperlaneRouterChecker' }), ) { super(multiProvider, app, configMap); } @@ -120,24 +127,43 @@ export class HyperlaneRouterChecker< async checkEnrolledRouters(chain: ChainName): Promise { const router = this.app.router(this.app.getContracts(chain)); const remoteChains = await this.app.remoteChains(chain); + const currentRouters: ChainMap = {}; + const expectedRouters: ChainMap = {}; + const routerDiff: ChainMap<{ + actual: AddressBytes32; + expected: AddressBytes32; + }> = {}; + await Promise.all( remoteChains.map(async (remoteChain) => { const remoteRouterAddress = this.app.routerAddress(remoteChain); const remoteDomainId = this.multiProvider.getDomainId(remoteChain); const actualRouter = await router.routers(remoteDomainId); const expectedRouter = addressToBytes32(remoteRouterAddress); + + currentRouters[remoteChain] = actualRouter; + expectedRouters[remoteChain] = expectedRouter; + if (actualRouter !== expectedRouter) { - const violation: RouterViolation = { - chain, - remoteChain, - type: RouterViolationType.EnrolledRouter, - contract: router, + routerDiff[remoteChain] = { actual: actualRouter, expected: expectedRouter, }; - this.addViolation(violation); } }), ); + + if (Object.keys(routerDiff).length > 0) { + const violation: RouterViolation = { + chain, + type: RouterViolationType.EnrolledRouter, + contract: router, + actual: currentRouters, + expected: expectedRouters, + routerDiff, + description: `Routers for some domains are missing or not enrolled correctly`, + }; + this.addViolation(violation); + } } } diff --git a/typescript/sdk/src/router/RouterApps.ts b/typescript/sdk/src/router/RouterApps.ts index 5251a93f2..306eec65a 100644 --- a/typescript/sdk/src/router/RouterApps.ts +++ b/typescript/sdk/src/router/RouterApps.ts @@ -45,14 +45,14 @@ export abstract class RouterApp< // check onchain for remote enrollments override async remoteChains(chainName: string): Promise { const router = this.router(this.contractsMap[chainName]); - const domainIds = (await router.domains()).map((domain) => { + const onchainRemoteChainNames = (await router.domains()).map((domain) => { const chainName = this.multiProvider.tryGetChainName(domain); if (chainName === null) { throw new Error(`Chain name not found for domain: ${domain}`); } return chainName; }); - return domainIds; + return onchainRemoteChainNames; } getSecurityModules(): Promise> { diff --git a/typescript/sdk/src/router/types.ts b/typescript/sdk/src/router/types.ts index 8fdf7c98b..2b0c81de5 100644 --- a/typescript/sdk/src/router/types.ts +++ b/typescript/sdk/src/router/types.ts @@ -6,11 +6,12 @@ import { Router, TimelockController__factory, } from '@hyperlane-xyz/core'; -import { Address } from '@hyperlane-xyz/utils'; +import { Address, AddressBytes32 } from '@hyperlane-xyz/utils'; import { HyperlaneFactories } from '../contracts/types.js'; import { UpgradeConfig } from '../deploy/proxy.js'; import { CheckerViolation } from '../deploy/types.js'; +import { ChainMap } from '../types.js'; import { GasRouterConfigSchema, @@ -56,10 +57,11 @@ export enum RouterViolationType { export interface RouterViolation extends CheckerViolation { type: RouterViolationType.EnrolledRouter; - remoteChain: string; contract: Router; - actual: string; - expected: string; + routerDiff: ChainMap<{ + actual: AddressBytes32; + expected: AddressBytes32; + }>; description?: string; } From b94a74534d231b10c24a33964bd5bf42dc534ac2 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:38:29 +0100 Subject: [PATCH 007/224] chore: tidy up cli-advanced-e2e workflow (#4460) chore: tidy up cli-advanced-e2e workflow - we don't run agents in the cli-advanced-e2e test anymore since our push for the updated CLI v4 - until we add agents back (https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4070) or migrate these tests entirely (https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4417), we should simplify the test - stop the agent prebuild to save precious cache space + ci cost - reduces ci cost by switching simple ts tests to a standard github runner --- .github/workflows/test.yml | 81 +--------------------- typescript/cli/ci-advanced-test.sh | 104 ----------------------------- 2 files changed, 2 insertions(+), 183 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6305e22df..8210e95cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -282,59 +282,10 @@ jobs: echo "All e2e-matrix jobs have completed." # You can add additional commands here to report the result as needed - prebuild-cli-e2e: - runs-on: larger-runner - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main' || github.base_ref == 'cli-2.0') || github.event_name == 'merge_group' - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - submodules: recursive - - - name: setup rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - - - name: rust cache - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v1-${{ runner.os }}-rust-cache" - shared-key: "cli-e2e" - workspaces: | - ./rust - - - name: Free disk space - run: | - # Based on https://github.com/actions/runner-images/issues/2840#issuecomment-790492173 - sudo rm -rf /usr/share/dotnet - sudo rm -rf /opt/ghc - sudo rm -rf "/usr/local/share/boost" - sudo rm -rf "$AGENT_TOOLSDIRECTORY" - - - name: Install mold linker - uses: rui314/setup-mold@v1 - with: - mold-version: 2.0.0 - make-default: true - - - name: Build validator - run: cargo build --bin validator --features test-utils - working-directory: ./rust - env: - RUST_BACKTRACE: 'full' - - - name: Build relayer - run: cargo build --bin relayer --features test-utils - working-directory: ./rust - env: - RUST_BACKTRACE: 'full' - cli-advanced-e2e: - runs-on: larger-runner + runs-on: ubuntu-latest if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main' || github.base_ref == 'cli-2.0') || github.event_name == 'merge_group' - needs: [yarn-build, prebuild-cli-e2e] + needs: [yarn-build] strategy: matrix: include: @@ -354,34 +305,6 @@ jobs: - name: foundry-install uses: foundry-rs/foundry-toolchain@v1 - - name: setup rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - - - name: rust cache - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "v1-${{ runner.os }}-rust-cache" - shared-key: "cli-e2e" - workspaces: | - ./rust - - - name: Free disk space - run: | - # Based on https://github.com/actions/runner-images/issues/2840#issuecomment-790492173 - sudo rm -rf /usr/share/dotnet - sudo rm -rf /opt/ghc - sudo rm -rf "/usr/local/share/boost" - sudo rm -rf "$AGENT_TOOLSDIRECTORY" - - - name: Install mold linker - uses: rui314/setup-mold@v1 - with: - mold-version: 2.0.0 - make-default: true - - name: yarn-cache uses: actions/cache@v4 with: diff --git a/typescript/cli/ci-advanced-test.sh b/typescript/cli/ci-advanced-test.sh index bc250cd5e..5fd16676f 100755 --- a/typescript/cli/ci-advanced-test.sh +++ b/typescript/cli/ci-advanced-test.sh @@ -34,12 +34,6 @@ _main() { run_hyperlane_deploy_warp; run_hyperlane_send_message; - # cd ./rust; - - # run_validator; - # run_relayer; - # run_hyperlane_status; - kill_anvil; echo "Done"; @@ -260,104 +254,6 @@ run_hyperlane_send_message() { echo "Message 2 ID: $MESSAGE2_ID" } -run_validator() { - echo -e "\nPre-building validator with cargo" - cargo build --bin validator --features test-utils - - # set some default agent env vars, used by both validators and relayer - export HYP_CHAINS_${CHAIN1_CAPS}_BLOCKS_REORGPERIOD=0 - export HYP_CHAINS_${CHAIN1_CAPS}_CUSTOMRPCURLS="http://127.0.0.1:${CHAIN1_PORT}" - export HYP_CHAINS_${CHAIN2_CAPS}_BLOCKS_REORGPERIOD=0 - export HYP_CHAINS_${CHAIN2_CAPS}_CUSTOMRPCURLS="http://127.0.0.1:${CHAIN2_PORT}" - - VALIDATOR_PORT=9091 - - for CHAIN in ${CHAIN1} ${CHAIN2} - do - # don't need the second validator for pi<>core test - if [ "$CHAIN" == "$CHAIN2" ] && [ "$TEST_TYPE" == "$TEST_TYPE_PI_CORE" ]; then - echo "Skipping validator for $CHAIN2 due to $TEST_TYPE_PI_CORE test type" - continue - fi - - VALIDATOR_PORT=$((VALIDATOR_PORT+1)) - echo "Running validator on $CHAIN on port $VALIDATOR_PORT" - export CONFIG_FILES=/tmp/agent-config.json - export HYP_ORIGINCHAINNAME=${CHAIN} - export HYP_VALIDATOR_INTERVAL=1 - export HYP_VALIDATOR_TYPE=hexKey - export HYP_VALIDATOR_KEY=0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 - export HYP_CHECKPOINTSYNCER_TYPE=localStorage - export HYP_CHECKPOINTSYNCER_PATH=/tmp/${CHAIN}/validator - export HYP_TRACING_LEVEL=debug - export HYP_TRACING_FMT=compact - export HYP_METRICSPORT=$VALIDATOR_PORT - - cargo run --bin validator > /tmp/${CHAIN}/validator-logs.txt & - done - - echo "Validator running, sleeping to let it sync" - # This needs to be long to allow time for the cargo build to finish - sleep 20 - echo "Done sleeping" - - for CHAIN in ${CHAIN1} ${CHAIN2} - do - # only have one validator announce in pi<>core test - if [ "$CHAIN" == "$CHAIN2" ] && [ "$TEST_TYPE" == "$TEST_TYPE_PI_CORE" ]; then - echo "Skipping validator for $CHAIN2 due to $TEST_TYPE_PI_CORE test type" - continue - fi - - echo "Validator Announcement for ${CHAIN}:" - cat /tmp/${CHAIN}/validator/announcement.json - done -} - -run_relayer() { - echo -e "\nPre-building relayer with cargo" - cargo build --bin relayer --features test-utils - - echo "Running relayer" - export CONFIG_FILES=/tmp/agent-config.json - export HYP_RELAYCHAINS=${CHAIN1},${CHAIN2} - export HYP_ALLOWLOCALCHECKPOINTSYNCERS=true - export HYP_DB=/tmp/relayer - export HYP_GASPAYMENTENFORCEMENT='[{"type":"none"}]' - export HYP_CHAINS_${CHAIN1_CAPS}_SIGNER_TYPE=hexKey - export HYP_CHAINS_${CHAIN1_CAPS}_SIGNER_KEY=0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 - export HYP_CHAINS_${CHAIN2_CAPS}_SIGNER_TYPE=hexKey - export HYP_CHAINS_${CHAIN2_CAPS}_SIGNER_KEY=0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 - export HYP_METRICSPORT=9090 - - cargo run --bin relayer > /tmp/relayer/relayer-logs.txt & - - # This needs to be long to allow time for the cargo build to finish - echo "Waiting for relayer..." - sleep 20 - echo "Done running relayer, checking message delivery statuses" -} - -run_hyperlane_status() { - for i in "1 $MESSAGE1_ID" "2 $MESSAGE2_ID" - do - set -- $i - echo "Checking delivery status of $1: $2" - yarn workspace @hyperlane-xyz/cli run hyperlane status \ - --id $2 \ - --destination ${CHAIN2} \ - --registry $REGISTRY_PATH \ - --overrides " " \ - | tee /tmp/message-status-$1 - if ! grep -q "$2 was delivered" /tmp/message-status-$1; then - echo "ERROR: Message $1 was not delivered" - exit 1 - else - echo "Message $1 was delivered!" - fi - done -} - update_deployer_balance() { OLD_BALANCE=$(cast balance $DEPLOYER --rpc-url http://127.0.0.1:${CHAIN1_PORT}); } From 518a1bef91a025c5a2c580134aa5fdb48fdd5667 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:13:16 +0100 Subject: [PATCH 008/224] fix: add 10% gas bump to initialize call in EvmModuleDeployer (#4470) fix: add 10% gas bump to initialize call in EvmModuleDeployer --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/curvy-ligers-drive.md | 5 +++++ typescript/sdk/src/deploy/EvmModuleDeployer.ts | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .changeset/curvy-ligers-drive.md diff --git a/.changeset/curvy-ligers-drive.md b/.changeset/curvy-ligers-drive.md new file mode 100644 index 000000000..45778d7c2 --- /dev/null +++ b/.changeset/curvy-ligers-drive.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +add 10% gas bump to initialize call in EvmModuleDeployer diff --git a/typescript/sdk/src/deploy/EvmModuleDeployer.ts b/typescript/sdk/src/deploy/EvmModuleDeployer.ts index f1b5a2313..2d742c9ea 100644 --- a/typescript/sdk/src/deploy/EvmModuleDeployer.ts +++ b/typescript/sdk/src/deploy/EvmModuleDeployer.ts @@ -69,8 +69,18 @@ export class EvmModuleDeployer { if (initializeArgs) { this.logger.debug(`Initialize ${contractName} on ${chain}`); + // Estimate gas for the initialize transaction + const estimatedGas = await contract.estimateGas.initialize( + ...initializeArgs, + ); + + // deploy with 10% buffer on gas limit const overrides = this.multiProvider.getTransactionOverrides(chain); - const initTx = await contract.initialize(...initializeArgs, overrides); + const initTx = await contract.initialize(...initializeArgs, { + gasLimit: estimatedGas.add(estimatedGas.div(10)), + ...overrides, + }); + await this.multiProvider.handleTx(chain, initTx); } From a46fe434a4864ec6ce6e466d265400c422451eb9 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Wed, 11 Sep 2024 10:09:38 -0400 Subject: [PATCH 009/224] feat: machine readable registry utils (#4444) ### Description - **Add --contract option to registry addresses cmd** - **Add registry rpc cmd** ### Backward compatibility Yes ### Testing Manual --- .changeset/pink-paws-fry.md | 5 +++ typescript/cli/src/commands/registry.ts | 52 ++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 .changeset/pink-paws-fry.md diff --git a/.changeset/pink-paws-fry.md b/.changeset/pink-paws-fry.md new file mode 100644 index 000000000..a4a48f737 --- /dev/null +++ b/.changeset/pink-paws-fry.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +Add hyperlane registry rpc and addresses --contract utils diff --git a/typescript/cli/src/commands/registry.ts b/typescript/cli/src/commands/registry.ts index 46f96ada0..933024de5 100644 --- a/typescript/cli/src/commands/registry.ts +++ b/typescript/cli/src/commands/registry.ts @@ -20,6 +20,7 @@ export const registryCommand: CommandModule = { builder: (yargs) => yargs .command(addressesCommand) + .command(rpcCommand) .command(createAgentConfigCommand) .command(initCommand) .command(listCommand) @@ -71,8 +72,12 @@ const listCommand: CommandModuleWithContext<{ type: ChainType }> = { /** * Addresses command */ -const addressesCommand: CommandModuleWithContext<{ name: string }> = { +const addressesCommand: CommandModuleWithContext<{ + name: string; + contract: string; +}> = { command: 'addresses', + aliases: ['address', 'addy'], describe: 'Display the addresses of core Hyperlane contracts', builder: { name: { @@ -80,10 +85,21 @@ const addressesCommand: CommandModuleWithContext<{ name: string }> = { description: 'Chain to display addresses for', alias: 'chain', }, + contract: { + type: 'string', + description: 'Specific contract name to print addresses for', + implies: 'name', + }, }, - handler: async ({ name, context }) => { + handler: async ({ name, context, contract }) => { if (name) { const result = await context.registry.getChainAddresses(name); + if (contract && result?.[contract.toLowerCase()]) { + // log only contract address for machine readability + log(result[contract]); + return; + } + logBlue('Hyperlane contract addresses for:', name); logGray('---------------------------------'); log(JSON.stringify(result, null, 2)); @@ -96,6 +112,38 @@ const addressesCommand: CommandModuleWithContext<{ name: string }> = { }, }; +const rpcCommand: CommandModuleWithContext<{ + name: string; + index: number; +}> = { + command: 'rpc', + describe: 'Display the public rpc of a Hyperlane chain', + builder: { + name: { + type: 'string', + description: 'Chain to display addresses for', + alias: 'chain', + demandOption: true, + }, + index: { + type: 'number', + description: 'Index of the rpc to display', + default: 0, + demandOption: false, + }, + }, + handler: async ({ name, context, index }) => { + const result = await context.registry.getChainMetadata(name); + const rpcUrl = result?.rpcUrls[index]?.http; + if (!rpcUrl) { + errorRed(`❌ No rpc found for chain ${name}`); + process.exit(1); + } + + log(rpcUrl); + }, +}; + /** * agent-config command */ From 2e6176f675593d36a2c415445d72c01bf2f84c87 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:00:13 +0100 Subject: [PATCH 010/224] feat: deploy to everclear mainnet (#4471) feat: deploy to everclear mainnet - registry PR https://github.com/hyperlane-xyz/hyperlane-registry/pull/187 --- .changeset/tender-moles-mate.md | 5 + .registryrc | 2 +- rust/config/mainnet_config.json | 64 ++++++++++ .../config/environments/mainnet3/agent.ts | 13 +- .../mainnet3/aw-validators/hyperlane.json | 3 + .../mainnet3/core/verification.json | 76 +++++++++++ .../config/environments/mainnet3/funding.ts | 3 +- .../environments/mainnet3/gasPrices.json | 8 +- .../mainnet3/ism/verification.json | 86 +++++++++++++ .../middleware/accounts/verification.json | 21 ++++ .../mainnet3/supportedChainNames.ts | 1 + .../environments/mainnet3/tokenPrices.json | 119 +++++++++--------- .../environments/mainnet3/validators.ts | 12 ++ typescript/infra/src/funding/key-funder.ts | 4 +- typescript/sdk/src/consts/multisigIsm.ts | 5 + 15 files changed, 352 insertions(+), 70 deletions(-) create mode 100644 .changeset/tender-moles-mate.md diff --git a/.changeset/tender-moles-mate.md b/.changeset/tender-moles-mate.md new file mode 100644 index 000000000..09b5e628e --- /dev/null +++ b/.changeset/tender-moles-mate.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Deploy to everclear mainnet diff --git a/.registryrc b/.registryrc index a7b8f56df..074ebc6b1 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -1d43e33fc84f486d0edf20a9e573f914e53fe94c +7512eac66d258d6cd8e8f417665b8e2ef81ab353 diff --git a/rust/config/mainnet_config.json b/rust/config/mainnet_config.json index ce6c300c1..89255a41a 100644 --- a/rust/config/mainnet_config.json +++ b/rust/config/mainnet_config.json @@ -3928,6 +3928,70 @@ "interchainAccountIsm": "0xA0a44cB8Bc0f7EDe788b0Cd29524A5b14fED7b45", "interchainAccountRouter": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a", "timelockController": "0x0000000000000000000000000000000000000000" + }, + "everclear": { + "blockExplorers": [ + { + "apiUrl": "https://everclear.cloud.blockscout.com/api", + "family": "blockscout", + "name": "Everclear Explorer", + "url": "https://everclear.cloud.blockscout.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 0 + }, + "chainId": 25327, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Everclear", + "domainId": 25327, + "gasCurrencyCoinGeckoId": "ethereum", + "index": { + "from": 37 + }, + "name": "everclear", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.everclear.raas.gelato.cloud" + } + ], + "technicalStack": "arbitrumnitro", + "aggregationHook": "0x14F6CA3B04f077AF26922B7957B89b32F8C842a9", + "domainRoutingIsm": "0xDEed16fe4b1c9b2a93483EDFf34C77A9b57D31Ff", + "domainRoutingIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "fallbackRoutingHook": "0x3C2b535a49c6827DF0b8e94467e6922c99E3c092", + "interchainAccountIsm": "0xcd9D3744512F07AE844c40E27912092d7c503565", + "interchainAccountRouter": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8", + "interchainGasPaymaster": "0xb58257cc81E47EC72fD38aE16297048de23163b4", + "interchainSecurityModule": "0x47F57D08d01544Ed082152B73807A9D39305Fac6", + "mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", + "merkleTreeHook": "0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1", + "pausableHook": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", + "pausableIsm": "0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0", + "protocolFee": "0xC49aF4965264FA7BB6424CE37aA06773ad177224", + "proxyAdmin": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "staticAggregationHookFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticAggregationIsm": "0x47F57D08d01544Ed082152B73807A9D39305Fac6", + "staticAggregationIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticMerkleRootMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticMessageIdMultisigIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMessageIdWeightedMultisigIsmFactory": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "storageGasOracle": "0xf8344D85a1429708e0BE6724218E938087e596DF", + "testRecipient": "0xF15D70941dE2Bf95A23d6488eBCbedE0a444137f", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xC88bAD76EC7acD9fd3b9Bb264f7f5C18097c5710" } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 7e69f486d..77a29775d 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -73,6 +73,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< eclipsemainnet: true, endurance: true, ethereum: true, + everclear: true, flare: true, fraxtal: true, fusemainnet: true, @@ -134,6 +135,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< eclipsemainnet: true, endurance: true, ethereum: true, + everclear: true, flare: true, fraxtal: true, fusemainnet: true, @@ -197,6 +199,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< eclipsemainnet: false, endurance: true, ethereum: true, + everclear: true, flare: true, fraxtal: true, fusemainnet: true, @@ -372,7 +375,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '74a592e-20240906-191210', + tag: 'd71dd4e-20240910-140936', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -381,7 +384,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: '74a592e-20240906-191210', + tag: 'd71dd4e-20240910-140936', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -391,7 +394,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '74a592e-20240906-191210', + tag: 'd71dd4e-20240910-140936', }, resources: scraperResources, }, @@ -406,7 +409,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '74a592e-20240906-191210', + tag: 'd71dd4e-20240910-140936', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. @@ -418,7 +421,7 @@ const releaseCandidate: RootAgentConfig = { validators: { docker: { repo, - tag: '74a592e-20240906-191210', + tag: 'd71dd4e-20240910-140936', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.ReleaseCandidate), diff --git a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json index fd6ae33c9..885ec4112 100644 --- a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json @@ -80,6 +80,9 @@ "0x749d6e7ad949e522c92181dc77f7bbc1c5d71506" ] }, + "everclear": { + "validators": ["0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837"] + }, "flare": { "validators": ["0xb65e52be342dba3ab2c088ceeb4290c744809134"] }, diff --git a/typescript/infra/config/environments/mainnet3/core/verification.json b/typescript/infra/config/environments/mainnet3/core/verification.json index 1999c9706..9d589b726 100644 --- a/typescript/infra/config/environments/mainnet3/core/verification.json +++ b/typescript/infra/config/environments/mainnet3/core/verification.json @@ -3447,5 +3447,81 @@ "constructorArguments": "000000000000000000000000000000000000000000000000000000000000006d", "isProxy": false } + ], + "everclear": [ + { + "name": "ProxyAdmin", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000062ef", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa70000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7" + }, + { + "name": "PausableIsm", + "address": "0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x3C2b535a49c6827DF0b8e94467e6922c99E3c092", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000cc3d1659d50461d27a2f025ddb2c9b06b584b7e1", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xf8344D85a1429708e0BE6724218E938087e596DF", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x8a28b3ec380cfdFF904a5D0bA615d53A4b19dc91", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xb58257cc81E47EC72fD38aE16297048de23163b4", + "constructorArguments": "0000000000000000000000008a28b3ec380cfdff904a5d0ba615d53a4b19dc910000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x8a28b3ec380cfdFF904a5D0bA615d53A4b19dc91" + }, + { + "name": "ProtocolFee", + "address": "0xC49aF4965264FA7BB6424CE37aA06773ad177224", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xC88bAD76EC7acD9fd3b9Bb264f7f5C18097c5710", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index 2ac22ab64..223f32d1a 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '74a592e-20240906-191211', + tag: 'd71dd4e-20240910-140936', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron @@ -44,6 +44,7 @@ export const keyFunderConfig: KeyFunderConfig< dogechain: '100', endurance: '20', ethereum: '0.5', + everclear: '0.05', flare: '500', fraxtal: '0.2', fusemainnet: '20', diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 0c78455c7..76ed0334d 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -72,7 +72,11 @@ "decimals": 9 }, "ethereum": { - "amount": "2", + "amount": "6.654595701", + "decimals": 9 + }, + "everclear": { + "amount": "0.1", "decimals": 9 }, "flare": { @@ -188,7 +192,7 @@ "decimals": 9 }, "sei": { - "amount": "100.0", + "amount": "120.0", "decimals": 9 }, "shibarium": { diff --git a/typescript/infra/config/environments/mainnet3/ism/verification.json b/typescript/infra/config/environments/mainnet3/ism/verification.json index 52d18b2c3..00d025f90 100644 --- a/typescript/infra/config/environments/mainnet3/ism/verification.json +++ b/typescript/infra/config/environments/mainnet3/ism/verification.json @@ -4852,5 +4852,91 @@ "constructorArguments": "", "isProxy": false } + ], + "everclear": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xDFF18Bf286c9cDd0fC653a28616460Cf7443F8EF", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json index 2eee67272..e82d33e68 100644 --- a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json @@ -1138,5 +1138,26 @@ "isProxy": true, "expectedimplementation": "0xF1854214392864c628A16930E73B699f7a51b3EE" } + ], + "everclear": [ + { + "name": "InterchainAccountIsm", + "address": "0xcd9D3744512F07AE844c40E27912092d7c503565", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x58556AaeB2e3829d52EE5E711D44735412efA43B", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8", + "constructorArguments": "00000000000000000000000058556aaeb2e3829d52ee5e711d44735412efa43b0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd9d3744512f07ae844c40e27912092d7c503565000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x58556AaeB2e3829d52EE5E711D44735412efA43B" + } ] } diff --git a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts index 454703f59..c477fe4c5 100644 --- a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts +++ b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts @@ -20,6 +20,7 @@ export const mainnet3SupportedChainNames = [ 'eclipsemainnet', 'endurance', 'ethereum', + 'everclear', 'flare', 'fraxtal', 'fusemainnet', diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index 4b29e06a6..d0ef62336 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -1,61 +1,62 @@ { - "ancient8": "2620.58", - "arbitrum": "2620.58", - "astar": "0.074541", - "astarzkevm": "2620.58", - "avalanche": "25.76", - "base": "2620.58", - "bitlayer": "62418", - "blast": "2620.58", - "bob": "2620.58", - "bsc": "551.73", - "celo": "0.481911", - "cheesechain": "0.00204939", - "coredao": "1.091", - "cyber": "2620.58", - "degenchain": "0.00398489", - "dogechain": "0.104488", - "eclipsemainnet": "2620.58", - "endurance": "2.34", - "ethereum": "2620.58", - "flare": "0.01529346", - "fraxtal": "2619.2", - "fusemainnet": "0.03214191", - "gnosis": "1.001", - "inevm": "20.44", - "injective": "20.44", - "kroma": "2620.58", - "linea": "2620.58", - "lisk": "2620.58", - "lukso": "2.54", - "mantapacific": "2620.58", - "mantle": "0.60943", - "merlin": "62351", - "metis": "35.7", - "mint": "2620.58", - "mode": "2620.58", - "molten": "0.498892", - "moonbeam": "0.169444", - "neutron": "0.404548", - "optimism": "2620.58", - "osmosis": "0.435141", - "polygon": "0.49875", - "polygonzkevm": "2620.58", - "proofofplay": "2620.58", - "real": "2620.58", - "redstone": "2620.58", - "sanko": "49.41", - "scroll": "2620.58", - "sei": "0.325976", - "shibarium": "0.418598", - "solanamainnet": "154.32", - "taiko": "2620.58", - "tangle": "0.999894", - "viction": "0.380653", - "worldchain": "2620.58", - "xai": "0.209969", - "xlayer": "37.74", - "zetachain": "0.528535", - "zircuit": "2620.58", - "zoramainnet": "2620.58" + "ancient8": "2342.46", + "arbitrum": "2342.46", + "astar": "0.054438", + "astarzkevm": "2342.46", + "avalanche": "23.83", + "base": "2342.46", + "bitlayer": "56880", + "blast": "2342.46", + "bob": "2342.46", + "bsc": "519.43", + "celo": "0.444294", + "cheesechain": "0.00249894", + "coredao": "0.942068", + "cyber": "2342.46", + "degenchain": "0.00324668", + "dogechain": "0.102724", + "eclipsemainnet": "2342.46", + "endurance": "2.14", + "ethereum": "2342.46", + "everclear": "2342.46", + "flare": "0.01473859", + "fraxtal": "2335.15", + "fusemainnet": "0.02525184", + "gnosis": "0.990366", + "inevm": "17.79", + "injective": "17.79", + "kroma": "2342.46", + "linea": "2342.46", + "lisk": "2342.46", + "lukso": "2.1", + "mantapacific": "2342.46", + "mantle": "0.563082", + "merlin": "56884", + "metis": "29.99", + "mint": "2342.46", + "mode": "2342.46", + "molten": "0.663236", + "moonbeam": "0.159678", + "neutron": "0.359547", + "optimism": "2342.46", + "osmosis": "0.39708", + "polygon": "0.384058", + "polygonzkevm": "2342.46", + "proofofplay": "2342.46", + "real": "2342.46", + "redstone": "2342.46", + "sanko": "39.51", + "scroll": "2342.46", + "sei": "0.290644", + "shibarium": "0.398366", + "solanamainnet": "133.81", + "taiko": "2342.46", + "tangle": "0.999864", + "viction": "0.438134", + "worldchain": "2342.46", + "xai": "0.183944", + "xlayer": "37.86", + "zetachain": "0.465693", + "zircuit": "2342.46", + "zoramainnet": "2342.46" } diff --git a/typescript/infra/config/environments/mainnet3/validators.ts b/typescript/infra/config/environments/mainnet3/validators.ts index a214d883e..b0be3a142 100644 --- a/typescript/infra/config/environments/mainnet3/validators.ts +++ b/typescript/infra/config/environments/mainnet3/validators.ts @@ -872,5 +872,17 @@ export const validatorChainConfig = ( 'shibarium', ), }, + everclear: { + interval: 5, + reorgPeriod: getReorgPeriod('everclear'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837'], + [Contexts.ReleaseCandidate]: [''], + [Contexts.Neutron]: [], + }, + 'everclear', + ), + }, }; }; diff --git a/typescript/infra/src/funding/key-funder.ts b/typescript/infra/src/funding/key-funder.ts index 8ecbea981..ad63128ec 100644 --- a/typescript/infra/src/funding/key-funder.ts +++ b/typescript/infra/src/funding/key-funder.ts @@ -6,8 +6,8 @@ import { getEnvironmentConfig } from '../../scripts/core-utils.js'; import { AgentContextConfig } from '../config/agent/agent.js'; import { DeployEnvironment, EnvironmentConfig } from '../config/environment.js'; import { KeyFunderConfig } from '../config/funding.js'; -import { HelmCommand, HelmManager, helmifyValues } from '../utils/helm.js'; -import { execCmd, getInfraPath } from '../utils/utils.js'; +import { HelmManager } from '../utils/helm.js'; +import { getInfraPath } from '../utils/utils.js'; export class KeyFunderHelmManager extends HelmManager { readonly helmReleaseName: string = 'key-funder'; diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index a519f08d8..9a2f49fa3 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -212,6 +212,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + everclear: { + threshold: 1, + validators: ['0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837'], + }, + flare: { threshold: 1, validators: ['0xb65e52be342dba3ab2c088ceeb4290c744809134'], From 952e2df759434b761c079805f5c21f9a9f592f24 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:29:34 +0100 Subject: [PATCH 011/224] chore: streamline evm module/deployer test setup (#4475) chore: streamline module test setup - move reusable setup into `before` - keep necessary per-test setup in `beforeEach` - shaves off several minutes from `yarn test:ci` time - [~15m](https://github.com/hyperlane-xyz/hyperlane-monorepo/actions/runs/10797378870/job/29948649484) -> [~6m](https://github.com/hyperlane-xyz/hyperlane-monorepo/actions/runs/10802337166/job/29964269588?pr=4475) --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .../src/hook/EvmHookModule.hardhat-test.ts | 2 +- .../sdk/src/ism/EvmIsmModule.hardhat-test.ts | 8 +++- .../ism/HyperlaneIsmFactory.hardhat-test.ts | 42 ++++++++++++------- .../EvmERC20WarpRouteReader.hardhat-test.ts | 8 +++- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts b/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts index 82abd5b44..f1dedc91d 100644 --- a/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts +++ b/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts @@ -180,7 +180,7 @@ describe('EvmHookModule', async () => { let factoryContracts: HyperlaneContracts; let exampleRoutingConfig: DomainRoutingHookConfig | FallbackRoutingHookConfig; - beforeEach(async () => { + before(async () => { [signer, funder] = await hre.ethers.getSigners(); multiProvider = MultiProvider.createTestMultiProvider({ signer }); diff --git a/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts b/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts index 3c079d138..a8deb6c24 100644 --- a/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts +++ b/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts @@ -98,7 +98,7 @@ describe('EvmIsmModule', async () => { let factoryAddresses: HyperlaneAddresses; let factoryContracts: HyperlaneContracts; - beforeEach(async () => { + before(async () => { const [signer, funder] = await hre.ethers.getSigners(); fundingAccount = funder; multiProvider = MultiProvider.createTestMultiProvider({ signer }); @@ -125,6 +125,12 @@ describe('EvmIsmModule', async () => { mailboxAddress = ( await new TestCoreDeployer(multiProvider, legacyIsmFactory).deployApp() ).getContracts(chain).mailbox.address; + }); + + beforeEach(async () => { + // Reset the MultiProvider for each test + const [signer] = await hre.ethers.getSigners(); + multiProvider = MultiProvider.createTestMultiProvider({ signer }); // example routing config exampleRoutingConfig = { diff --git a/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts b/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts index 017d539f7..5e7b004a0 100644 --- a/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts +++ b/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts @@ -6,9 +6,10 @@ import { DomainRoutingIsm, TrustedRelayerIsm } from '@hyperlane-xyz/core'; import { Address, randomElement, randomInt } from '@hyperlane-xyz/utils'; import { TestChainName, testChains } from '../consts/testChains.js'; -import { TestCoreApp } from '../core/TestCoreApp.js'; +import { HyperlaneContractsMap } from '../contracts/types.js'; import { TestCoreDeployer } from '../core/TestCoreDeployer.js'; import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js'; +import { ProxyFactoryFactories } from '../deploy/contracts.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { randomAddress } from '../test/testUtils.js'; @@ -132,29 +133,42 @@ export const randomIsmConfig = ( }; describe('HyperlaneIsmFactory', async () => { + let ismFactoryDeployer: HyperlaneProxyFactoryDeployer; let ismFactory: HyperlaneIsmFactory; - let coreApp: TestCoreApp; let multiProvider: MultiProvider; - let ismFactoryDeployer: HyperlaneProxyFactoryDeployer; let exampleRoutingConfig: RoutingIsmConfig; - let mailboxAddress: Address, newMailboxAddress: Address; + let mailboxAddress: Address; + let newMailboxAddress: Address; + let contractsMap: HyperlaneContractsMap = {}; + const chain = TestChainName.test1; - beforeEach(async () => { + before(async () => { const [signer] = await hre.ethers.getSigners(); multiProvider = MultiProvider.createTestMultiProvider({ signer }); + ismFactoryDeployer = new HyperlaneProxyFactoryDeployer(multiProvider); - ismFactory = new HyperlaneIsmFactory( - await ismFactoryDeployer.deploy(multiProvider.mapKnownChains(() => ({}))), - multiProvider, + contractsMap = await ismFactoryDeployer.deploy( + multiProvider.mapKnownChains(() => ({})), ); - let coreDeployer = new TestCoreDeployer(multiProvider, ismFactory); - coreApp = await coreDeployer.deployApp(); - mailboxAddress = coreApp.getContracts(chain).mailbox.address; + ismFactory = new HyperlaneIsmFactory(contractsMap, multiProvider); + + mailboxAddress = ( + await new TestCoreDeployer(multiProvider, ismFactory).deployApp() + ).getContracts(chain).mailbox.address; - coreDeployer = new TestCoreDeployer(multiProvider, ismFactory); - coreApp = await coreDeployer.deployApp(); - newMailboxAddress = coreApp.getContracts(chain).mailbox.address; + newMailboxAddress = ( + await new TestCoreDeployer(multiProvider, ismFactory).deployApp() + ).getContracts(chain).mailbox.address; + }); + + beforeEach(async () => { + const [signer] = await hre.ethers.getSigners(); + multiProvider = MultiProvider.createTestMultiProvider({ signer }); + + ismFactoryDeployer = new HyperlaneProxyFactoryDeployer(multiProvider); + ismFactory = new HyperlaneIsmFactory(contractsMap, multiProvider); + ismFactory.setDeployer(new TestCoreDeployer(multiProvider, ismFactory)); exampleRoutingConfig = { type: IsmType.ROUTING, diff --git a/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts b/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts index d5f7a6ee1..f086f3b83 100644 --- a/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts +++ b/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts @@ -49,7 +49,7 @@ describe('ERC20WarpRouterReader', async () => { let mailbox: Mailbox; let evmERC20WarpRouteReader: EvmERC20WarpRouteReader; let vault: ERC4626; - beforeEach(async () => { + before(async () => { [signer] = await hre.ethers.getSigners(); multiProvider = MultiProvider.createTestMultiProvider({ signer }); const ismFactoryDeployer = new HyperlaneProxyFactoryDeployer(multiProvider); @@ -77,6 +77,12 @@ describe('ERC20WarpRouterReader', async () => { vault = await vaultFactory.deploy(token.address, TOKEN_NAME, TOKEN_NAME); }); + beforeEach(async () => { + // Reset the MultiProvider and create a new deployer for each test + multiProvider = MultiProvider.createTestMultiProvider({ signer }); + deployer = new HypERC20Deployer(multiProvider); + }); + it('should derive a token type from contract', async () => { const typesToDerive = [ TokenType.collateral, From b91e0f446a0192492360b78280d14385bba87033 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:26:59 +0100 Subject: [PATCH 012/224] feat: remove extraneous caching (#4469) feat: remove yarn build cache - saves 600MB of cache space PER COMMIT - doesn't impact overall per-commit CI time - better CI time in the general case due to fewer cache evictions on the e2e matrix job - [with caching](https://github.com/hyperlane-xyz/hyperlane-monorepo/actions/runs/10797745470) vs [no caching](https://github.com/hyperlane-xyz/hyperlane-monorepo/actions/runs/10797213927?pr=4469) drive-by: disable docker caching for agent build - currently cache has no impact on build time of the agent image - rerunning builds for a commit or pushing empty commits should in theory lead to quicker builds with layer caching, but the main problem is that the `RUN` step of building the agents is not cached by the docker action - only RUNs with bind mounts get a checksum computed [(reference)](https://docs.docker.com/build/cache/invalidation/#general-rules) - disabling docker build caching could help save a bunch of cache space - best way to 4x speed here is moving this job to a buildjet 8vcpu runner (read [here](https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4445) for more info) drive-by: TLC - update to latest docker build action - provides a nice build summary and can generate artifacts that help break down where build time is spent - update check-env before build, given the current deprecation annotations - https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ - coverage step doesn't need to wait for `yarn-test` anymore --- .../actions/yarn-build-with-cache/action.yml | 23 +++ .github/workflows/monorepo-docker.yml | 4 +- .github/workflows/rust-docker.yml | 6 +- .github/workflows/test.yml | 138 +++--------------- 4 files changed, 51 insertions(+), 120 deletions(-) create mode 100644 .github/actions/yarn-build-with-cache/action.yml diff --git a/.github/actions/yarn-build-with-cache/action.yml b/.github/actions/yarn-build-with-cache/action.yml new file mode 100644 index 000000000..11fc4bd20 --- /dev/null +++ b/.github/actions/yarn-build-with-cache/action.yml @@ -0,0 +1,23 @@ +name: 'Yarn Build with Cache' +description: 'Run yarn build using yarn cache' + +inputs: + ref: + description: 'The Git ref to checkout' + required: true + +runs: + using: "composite" + steps: + - name: Cache + uses: actions/cache@v4 + with: + path: | + **/node_modules + .yarn + key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} + fail-on-cache-miss: true + + - name: Build + shell: bash + run: yarn build diff --git a/.github/workflows/monorepo-docker.yml b/.github/workflows/monorepo-docker.yml index 27690bede..e697aae22 100644 --- a/.github/workflows/monorepo-docker.yml +++ b/.github/workflows/monorepo-docker.yml @@ -29,7 +29,7 @@ jobs: GCLOUD_SERVICE_KEY: ${{ secrets.GCLOUD_SERVICE_KEY }} if: "${{ env.GCLOUD_SERVICE_KEY != '' }}" # runs if GCLOUD_SERVICE_KEY is defined, so we set the output to true - run: echo "::set-output name=defined::true" + run: echo "defined=true" >> $GITHUB_OUTPUT build-and-push-to-gcr: runs-on: ubuntu-latest @@ -77,7 +77,7 @@ jobs: echo "REGISTRY_VERSION=$REGISTRY_VERSION" >> $GITHUB_ENV - name: Build and push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: ./ file: ./Dockerfile diff --git a/.github/workflows/rust-docker.yml b/.github/workflows/rust-docker.yml index bc70a1f86..adf37434e 100644 --- a/.github/workflows/rust-docker.yml +++ b/.github/workflows/rust-docker.yml @@ -24,7 +24,7 @@ jobs: GCLOUD_SERVICE_KEY: ${{ secrets.GCLOUD_SERVICE_KEY }} if: "${{ env.GCLOUD_SERVICE_KEY != '' }}" # runs if GCLOUD_SERVICE_KEY is defined, so we set the output to true - run: echo "::set-output name=defined::true" + run: echo "defined=true" >> $GITHUB_OUTPUT build-and-push-to-gcr: runs-on: ubuntu-latest @@ -63,12 +63,10 @@ jobs: username: _json_key password: ${{ secrets.GCLOUD_SERVICE_KEY }} - name: Build and push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . file: ./rust/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8210e95cf..83ea16b65 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,35 +54,6 @@ jobs: exit 1 fi - yarn-build: - runs-on: ubuntu-latest - needs: [yarn-install] - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - submodules: recursive - fetch-depth: 0 - - - name: yarn-cache - uses: actions/cache@v4 - with: - path: | - **/node_modules - .yarn - key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} - - - name: build-cache - uses: actions/cache@v4 - with: - path: | - ./* - !./rust - key: ${{ github.event.pull_request.head.sha || github.sha }} - - - name: build - run: yarn build - lint-prettier: runs-on: ubuntu-latest needs: [yarn-install] @@ -115,7 +86,7 @@ jobs: yarn-test: runs-on: ubuntu-latest - needs: [yarn-build] + needs: [yarn-install] steps: - uses: actions/checkout@v4 with: @@ -126,13 +97,10 @@ jobs: - name: foundry-install uses: foundry-rs/foundry-toolchain@v1 - - name: build-cache - uses: actions/cache@v4 + - name: yarn-build + uses: ./.github/actions/yarn-build-with-cache with: - path: | - ./* - !./rust - key: ${{ github.event.pull_request.head.sha || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Checkout registry uses: ./.github/actions/checkout-registry @@ -142,7 +110,7 @@ jobs: agent-configs: runs-on: ubuntu-latest - needs: [yarn-build] + needs: [yarn-install] strategy: fail-fast: false matrix: @@ -153,21 +121,10 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 - - name: yarn-cache - uses: actions/cache@v4 + - name: yarn-build + uses: ./.github/actions/yarn-build-with-cache with: - path: | - **/node_modules - .yarn - key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} - - - name: build-cache - uses: actions/cache@v4 - with: - path: | - ./* - !./rust - key: ${{ github.event.pull_request.head.sha || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Checkout registry uses: ./.github/actions/checkout-registry @@ -185,7 +142,7 @@ jobs: e2e-matrix: runs-on: larger-runner if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main' || github.base_ref == 'cli-2.0') || github.event_name == 'merge_group' - needs: [yarn-build] + needs: [yarn-install] strategy: fail-fast: false matrix: @@ -231,21 +188,10 @@ jobs: mold-version: 2.0.0 make-default: true - - name: yarn-cache - uses: actions/cache@v4 + - name: yarn-build + uses: ./.github/actions/yarn-build-with-cache with: - path: | - **/node_modules - .yarn - key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} - - - name: build-cache - uses: actions/cache@v4 - with: - path: | - ./* - !./rust - key: ${{ github.event.pull_request.head.sha || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Install system dependencies run: | @@ -272,20 +218,10 @@ jobs: E2E_KATHY_MESSAGES: '20' RUST_BACKTRACE: 'full' - e2e: - runs-on: ubuntu-latest - needs: [e2e-matrix] - if: always() # This ensures that the job runs even if the e2e jobs fail - steps: - - name: Report Matrix Result - run: | - echo "All e2e-matrix jobs have completed." - # You can add additional commands here to report the result as needed - cli-advanced-e2e: runs-on: ubuntu-latest if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main' || github.base_ref == 'cli-2.0') || github.event_name == 'merge_group' - needs: [yarn-build] + needs: [yarn-install] strategy: matrix: include: @@ -305,21 +241,10 @@ jobs: - name: foundry-install uses: foundry-rs/foundry-toolchain@v1 - - name: yarn-cache - uses: actions/cache@v4 + - name: yarn-build + uses: ./.github/actions/yarn-build-with-cache with: - path: | - **/node_modules - .yarn - key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} - - - name: build-cache - uses: actions/cache@v4 - with: - path: | - ./* - !./rust - key: ${{ github.event.pull_request.head.sha || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Checkout registry uses: ./.github/actions/checkout-registry @@ -334,7 +259,7 @@ jobs: MAINNET3_OPTIMISM_RPC_URLS: ${{ secrets.MAINNET3_OPTIMISM_RPC_URLS }} timeout-minutes: 10 - needs: [yarn-build] + needs: [yarn-install] strategy: fail-fast: false matrix: @@ -354,13 +279,10 @@ jobs: - name: foundry-install uses: foundry-rs/foundry-toolchain@v1 - - name: build-cache - uses: actions/cache@v4 + - name: yarn-build + uses: ./.github/actions/yarn-build-with-cache with: - path: | - ./* - !./rust - key: ${{ github.event.pull_request.head.sha || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Checkout registry uses: ./.github/actions/checkout-registry @@ -370,29 +292,17 @@ jobs: coverage: runs-on: ubuntu-latest - needs: [yarn-test] - + needs: [yarn-install] steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 - - name: yarn-cache - uses: actions/cache@v4 - with: - path: | - **/node_modules - .yarn - key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} - - - name: build-cache - uses: actions/cache@v4 + - name: yarn-build + uses: ./.github/actions/yarn-build-with-cache with: - path: | - ./* - !./rust - key: ${{ github.event.pull_request.head.sha || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: foundry-install uses: foundry-rs/foundry-toolchain@v1 From 085e7d04636d54a37c2b2eac2a608d925dcb3857 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 11 Sep 2024 19:04:00 +0100 Subject: [PATCH 013/224] feat: migrate large runners to buildjet (#4424) feat: migrate large runners to buildjet - includes migration to buildjet's cache - benefits: https://buildjet.com/for-github-actions/blog/launch-buildjet-cache#buildjet-cache-benefits - 20GB/week free cache is 2x what GHA provides - drive-by: add restore-keys for the yarn caches - more buildjet investigation notes [here](https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4445) --- .github/actions/yarn-build-with-cache/action.yml | 2 +- .github/workflows/agent-release-artifacts.yml | 2 +- .github/workflows/codespell.yml | 4 ++-- .github/workflows/rust-docker.yml | 2 +- .github/workflows/rust.yml | 16 ++++++++++------ .github/workflows/static-analysis.yml | 4 +++- .github/workflows/storage-analysis.yml | 4 +++- .github/workflows/test.yml | 11 ++++++++--- 8 files changed, 29 insertions(+), 16 deletions(-) diff --git a/.github/actions/yarn-build-with-cache/action.yml b/.github/actions/yarn-build-with-cache/action.yml index 11fc4bd20..7ffad99a0 100644 --- a/.github/actions/yarn-build-with-cache/action.yml +++ b/.github/actions/yarn-build-with-cache/action.yml @@ -10,7 +10,7 @@ runs: using: "composite" steps: - name: Cache - uses: actions/cache@v4 + uses: buildjet/cache@v4 with: path: | **/node_modules diff --git a/.github/workflows/agent-release-artifacts.yml b/.github/workflows/agent-release-artifacts.yml index f54822817..b1218dc54 100644 --- a/.github/workflows/agent-release-artifacts.yml +++ b/.github/workflows/agent-release-artifacts.yml @@ -16,7 +16,7 @@ env: jobs: prepare: - runs-on: larger-runner + runs-on: ubuntu-latest outputs: tag_date: ${{ steps.taggen.outputs.TAG_DATE }} tag_sha: ${{ steps.taggen.outputs.TAG_SHA }} diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 8848a92bf..461ccd3d7 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v4 - name: pip cache - uses: actions/cache@v4 + uses: buildjet/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} @@ -32,4 +32,4 @@ jobs: run: sudo pip install -r ./.codespell/requirements.txt - name: Spell check - run: codespell --config=./.codespell/.codespellrc \ No newline at end of file + run: codespell --config=./.codespell/.codespellrc diff --git a/.github/workflows/rust-docker.yml b/.github/workflows/rust-docker.yml index adf37434e..a1fed4f55 100644 --- a/.github/workflows/rust-docker.yml +++ b/.github/workflows/rust-docker.yml @@ -27,7 +27,7 @@ jobs: run: echo "defined=true" >> $GITHUB_OUTPUT build-and-push-to-gcr: - runs-on: ubuntu-latest + runs-on: buildjet-8vcpu-ubuntu-2204 # uses check-env to determine if secrets.GCLOUD_SERVICE_KEY is defined needs: [check-env] diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 62d0c718a..2c537a780 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,8 +30,7 @@ defaults: jobs: test-rs: - runs-on: larger-runner - + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: actions/checkout@v4 with: @@ -43,7 +42,10 @@ jobs: - name: rust cache uses: Swatinem/rust-cache@v2 with: - prefix-key: "v3-rust" + prefix-key: "v3" + shared-key: "rust" + cache-provider: "buildjet" + save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} workspaces: | ./rust - name: Free disk space @@ -57,8 +59,7 @@ jobs: run: cargo test lint-rs: - runs-on: larger-runner - + runs-on: buildjet-8vcpu-ubuntu-2204 steps: - uses: actions/checkout@v4 with: @@ -72,7 +73,10 @@ jobs: - name: rust cache uses: Swatinem/rust-cache@v2 with: - prefix-key: "v3-rust" + prefix-key: "v3" + shared-key: "rust" + cache-provider: "buildjet" + save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} workspaces: | ./rust - name: Free disk space diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index a3eba2c88..788324d6e 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -24,12 +24,14 @@ jobs: submodules: recursive - name: yarn-cache - uses: actions/cache@v4 + uses: buildjet/cache@v4 with: path: | **/node_modules .yarn key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn-cache- - name: yarn-install run: yarn install diff --git a/.github/workflows/storage-analysis.yml b/.github/workflows/storage-analysis.yml index 70e77f0dd..979c23fbe 100644 --- a/.github/workflows/storage-analysis.yml +++ b/.github/workflows/storage-analysis.yml @@ -24,12 +24,14 @@ jobs: node-version: 18 - name: yarn-cache - uses: actions/cache@v4 + uses: buildjet/cache@v4 with: path: | **/node_modules .yarn key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn-cache- - name: yarn-install run: yarn install diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 83ea16b65..07b0ab51a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,12 +37,14 @@ jobs: submodules: recursive - name: yarn-cache - uses: actions/cache@v4 + uses: buildjet/cache@v4 with: path: | **/node_modules .yarn key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn-cache- - name: yarn-install run: | @@ -65,12 +67,13 @@ jobs: fetch-depth: 0 - name: yarn-cache - uses: actions/cache@v4 + uses: buildjet/cache@v4 with: path: | **/node_modules .yarn key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} + fail-on-cache-miss: true - name: lint run: yarn lint @@ -140,7 +143,7 @@ jobs: fi e2e-matrix: - runs-on: larger-runner + runs-on: buildjet-8vcpu-ubuntu-2204 if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main' || github.base_ref == 'cli-2.0') || github.event_name == 'merge_group' needs: [yarn-install] strategy: @@ -171,6 +174,8 @@ jobs: with: prefix-key: "v1-${{ runner.os }}-rust-cache" shared-key: ${{ matrix.e2e-type }} + cache-provider: "buildjet" + save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} workspaces: | ./rust From d6de34ad552bcecba01a95b7d0eb7f1e39f07297 Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Wed, 11 Sep 2024 19:20:49 +0100 Subject: [PATCH 014/224] feat(sdk): Sort ISM config arrays (#4436) ### Description - Introduce sorting validator arrays and modules by type for ISM in the `normalizeConfig` method - This will avoid deploying a new version of the same ISM (in practice) for updates - Sort staticAddressSets by value before deploying - This will enable us to use ISM recovery - This will also avoid raising ISM mismatch violations for our checker tooling ### Testing Unit Tests --- .changeset/chilled-coats-boil.md | 5 + .changeset/tender-fishes-sniff.md | 5 + .../src/core/EvmCoreModule.hardhat-test.ts | 3 +- .../sdk/src/deploy/EvmModuleDeployer.ts | 22 +- .../src/hook/EvmHookModule.hardhat-test.ts | 9 +- typescript/sdk/src/hook/EvmHookModule.ts | 2 +- .../sdk/src/ism/EvmIsmModule.hardhat-test.ts | 214 ++++++++++++++++-- typescript/sdk/src/ism/EvmIsmModule.ts | 2 +- .../token/EvmERC20WarpModule.hardhat-test.ts | 2 +- .../sdk/src/token/EvmERC20WarpModule.ts | 2 +- typescript/sdk/src/utils/ism.ts | 60 +++++ typescript/utils/src/index.ts | 1 - typescript/utils/src/objects.ts | 20 -- 13 files changed, 291 insertions(+), 56 deletions(-) create mode 100644 .changeset/chilled-coats-boil.md create mode 100644 .changeset/tender-fishes-sniff.md diff --git a/.changeset/chilled-coats-boil.md b/.changeset/chilled-coats-boil.md new file mode 100644 index 000000000..6ec43005e --- /dev/null +++ b/.changeset/chilled-coats-boil.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/utils': minor +--- + +Add sortArraysInConfig method, normalizeConfig implementation to call sortArraysInConfig after current behavior diff --git a/.changeset/tender-fishes-sniff.md b/.changeset/tender-fishes-sniff.md new file mode 100644 index 000000000..9582272a5 --- /dev/null +++ b/.changeset/tender-fishes-sniff.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Sort values in EvmModuleDeployer.deployStaticAddressSet diff --git a/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts b/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts index 509e443d1..408ea4e2b 100644 --- a/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts +++ b/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts @@ -10,13 +10,14 @@ import { TimelockController__factory, ValidatorAnnounce__factory, } from '@hyperlane-xyz/core'; -import { normalizeConfig, objMap } from '@hyperlane-xyz/utils'; +import { objMap } from '@hyperlane-xyz/utils'; import { TestChainName } from '../consts/testChains.js'; import { IsmConfig, IsmType } from '../ism/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { randomAddress, testCoreConfig } from '../test/testUtils.js'; +import { normalizeConfig } from '../utils/ism.js'; import { EvmCoreModule } from './EvmCoreModule.js'; import { CoreConfig } from './types.js'; diff --git a/typescript/sdk/src/deploy/EvmModuleDeployer.ts b/typescript/sdk/src/deploy/EvmModuleDeployer.ts index 2d742c9ea..0d098134a 100644 --- a/typescript/sdk/src/deploy/EvmModuleDeployer.ts +++ b/typescript/sdk/src/deploy/EvmModuleDeployer.ts @@ -264,34 +264,40 @@ export class EvmModuleDeployer { threshold?: number; multiProvider: MultiProvider; }): Promise
{ + const sortedValues = [...values].sort(); + const address = await factory['getAddress(address[],uint8)']( - values, + sortedValues, threshold, ); const code = await multiProvider.getProvider(chain).getCode(address); if (code === '0x') { logger.debug( - `Deploying new ${threshold} of ${values.length} address set to ${chain}`, + `Deploying new ${threshold} of ${sortedValues.length} address set to ${chain}`, ); const overrides = multiProvider.getTransactionOverrides(chain); // estimate gas const estimatedGas = await factory.estimateGas['deploy(address[],uint8)']( - values, + sortedValues, threshold, overrides, ); // add 10% buffer - const hash = await factory['deploy(address[],uint8)'](values, threshold, { - ...overrides, - gasLimit: estimatedGas.add(estimatedGas.div(10)), // 10% buffer - }); + const hash = await factory['deploy(address[],uint8)']( + sortedValues, + threshold, + { + ...overrides, + gasLimit: estimatedGas.add(estimatedGas.div(10)), // 10% buffer + }, + ); await multiProvider.handleTx(chain, hash); } else { logger.debug( - `Recovered ${threshold} of ${values.length} address set on ${chain}: ${address}`, + `Recovered ${threshold} of ${sortedValues.length} address set on ${chain}: ${address}`, ); } diff --git a/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts b/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts index f1dedc91d..aa4c9d559 100644 --- a/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts +++ b/typescript/sdk/src/hook/EvmHookModule.hardhat-test.ts @@ -3,13 +3,7 @@ import { expect } from 'chai'; import { Signer } from 'ethers'; import hre from 'hardhat'; -import { - Address, - assert, - deepEquals, - eqAddress, - normalizeConfig, -} from '@hyperlane-xyz/utils'; +import { Address, assert, deepEquals, eqAddress } from '@hyperlane-xyz/utils'; import { TestChainName, testChains } from '../consts/testChains.js'; import { HyperlaneAddresses, HyperlaneContracts } from '../contracts/types.js'; @@ -20,6 +14,7 @@ import { ProxyFactoryFactories } from '../deploy/contracts.js'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { randomAddress, randomInt } from '../test/testUtils.js'; +import { normalizeConfig } from '../utils/ism.js'; import { EvmHookModule } from './EvmHookModule.js'; import { diff --git a/typescript/sdk/src/hook/EvmHookModule.ts b/typescript/sdk/src/hook/EvmHookModule.ts index ef8185140..fb8e12842 100644 --- a/typescript/sdk/src/hook/EvmHookModule.ts +++ b/typescript/sdk/src/hook/EvmHookModule.ts @@ -30,7 +30,6 @@ import { addressToBytes32, deepEquals, eqAddress, - normalizeConfig, rootLogger, } from '@hyperlane-xyz/utils'; @@ -51,6 +50,7 @@ import { ArbL2ToL1IsmConfig, IsmType, OpStackIsmConfig } from '../ism/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { ChainNameOrId } from '../types.js'; +import { normalizeConfig } from '../utils/ism.js'; import { EvmHookReader } from './EvmHookReader.js'; import { DeployedHook, HookFactories, hookFactories } from './contracts.js'; diff --git a/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts b/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts index a8deb6c24..fc03107cc 100644 --- a/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts +++ b/typescript/sdk/src/ism/EvmIsmModule.hardhat-test.ts @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { Signer } from 'ethers'; import hre from 'hardhat'; -import { Address, eqAddress, normalizeConfig } from '@hyperlane-xyz/utils'; +import { Address, eqAddress } from '@hyperlane-xyz/utils'; import { TestChainName, testChains } from '../consts/testChains.js'; import { HyperlaneAddresses, HyperlaneContracts } from '../contracts/types.js'; @@ -13,6 +13,7 @@ import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDe import { ProxyFactoryFactories } from '../deploy/contracts.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { randomAddress, randomInt } from '../test/testUtils.js'; +import { normalizeConfig } from '../utils/ism.js'; import { EvmIsmModule } from './EvmIsmModule.js'; import { HyperlaneIsmFactory } from './HyperlaneIsmFactory.js'; @@ -36,19 +37,27 @@ const randomMultisigIsmConfig = (m: number, n: number): MultisigIsmConfig => { }; }; +const ModuleTypes = [ + ModuleType.AGGREGATION, + ModuleType.MERKLE_ROOT_MULTISIG, + ModuleType.ROUTING, + ModuleType.NULL, +]; + +const NonNestedModuleTypes = [ModuleType.MERKLE_ROOT_MULTISIG, ModuleType.NULL]; + function randomModuleType(): ModuleType { - const choices = [ - ModuleType.AGGREGATION, - ModuleType.MERKLE_ROOT_MULTISIG, - ModuleType.ROUTING, - ModuleType.NULL, - ]; - return choices[randomInt(choices.length)]; + return ModuleTypes[randomInt(ModuleTypes.length)]; +} + +function randomNonNestedModuleType(): ModuleType { + return NonNestedModuleTypes[randomInt(NonNestedModuleTypes.length)]; } -const randomIsmConfig = (depth = 0, maxDepth = 2): IsmConfig => { +const randomIsmConfig = (depth = 0, maxDepth = 2) => { const moduleType = - depth == maxDepth ? ModuleType.MERKLE_ROOT_MULTISIG : randomModuleType(); + depth === maxDepth ? randomNonNestedModuleType() : randomModuleType(); + switch (moduleType) { case ModuleType.MERKLE_ROOT_MULTISIG: { const n = randomInt(5, 1); @@ -65,10 +74,21 @@ const randomIsmConfig = (depth = 0, maxDepth = 2): IsmConfig => { return config; } case ModuleType.AGGREGATION: { - const n = randomInt(5, 1); - const modules = new Array(n) - .fill(0) - .map(() => randomIsmConfig(depth + 1)); + const n = randomInt(2, 1); + const moduleTypes = new Set(); + const modules = new Array(n).fill(0).map(() => { + let moduleConfig; + let moduleType; + + // Ensure that we do not add the same module type more than once per level + do { + moduleConfig = randomIsmConfig(depth + 1, maxDepth); + moduleType = moduleConfig.type; + } while (moduleTypes.has(moduleType)); + + moduleTypes.add(moduleType); + return moduleConfig; + }); const config: AggregationIsmConfig = { type: IsmType.AGGREGATION, threshold: randomInt(n, 1), @@ -176,8 +196,10 @@ describe('EvmIsmModule', async () => { // expect that the ISM matches the config after all tests afterEach(async () => { - const normalizedDerivedConfig = normalizeConfig(await testIsm.read()); + const derivedConfiig = await testIsm.read(); + const normalizedDerivedConfig = normalizeConfig(derivedConfiig); const normalizedConfig = normalizeConfig(testConfig); + assert.deepStrictEqual(normalizedDerivedConfig, normalizedConfig); }); @@ -347,6 +369,74 @@ describe('EvmIsmModule', async () => { .true; }); + it(`reordering validators in an existing ${type} should not trigger a redeployment`, async () => { + // create a new ISM + const routerConfig = { + type: IsmType.ROUTING, + owner: (await multiProvider.getSignerAddress(chain)).toLowerCase(), + domains: { + test1: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + ], + threshold: 2, + }, + test2: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + ], + threshold: 2, + }, + }, + }; + + const { ism, initialIsmAddress } = await createIsm( + routerConfig as RoutingIsmConfig, + ); + + const updatedRouterConfig = { + type: IsmType.ROUTING, + owner: (await multiProvider.getSignerAddress(chain)).toLowerCase(), + domains: { + test1: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + ], + threshold: 2, + }, + test2: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + ], + threshold: 2, + }, + }, + }; + + // expect 0 updates + await expectTxsAndUpdate( + ism, + updatedRouterConfig as RoutingIsmConfig, + 0, + ); + + // expect the ISM address to be the same + expect(eqAddress(initialIsmAddress, ism.serialize().deployedIsm)).to.be + .true; + }); + it(`update owner in an existing ${type} not owned by deployer`, async () => { // ISM owner is not the deployer exampleRoutingConfig.owner = randomAddress(); @@ -435,5 +525,99 @@ describe('EvmIsmModule', async () => { .true; }); } + + it(`reordering modules in an existing staticAggregationIsm should not trigger a redeployment`, async () => { + // create a new ISM + const config: AggregationIsmConfig = { + type: IsmType.AGGREGATION, + modules: [ + { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + ], + threshold: 2, + }, + { + type: IsmType.ROUTING, + owner: (await multiProvider.getSignerAddress(chain)).toLowerCase(), + domains: { + test1: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + ], + threshold: 2, + }, + test2: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + ], + threshold: 2, + }, + }, + }, + ], + threshold: 2, + }; + + const { ism, initialIsmAddress } = await createIsm( + config as AggregationIsmConfig, + ); + + const updatedConfig: AggregationIsmConfig = { + type: IsmType.AGGREGATION, + modules: [ + { + type: IsmType.ROUTING, + owner: (await multiProvider.getSignerAddress(chain)).toLowerCase(), + domains: { + test2: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + ], + threshold: 2, + }, + test1: { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + ], + threshold: 2, + }, + }, + }, + { + type: IsmType.MERKLE_ROOT_MULTISIG, + validators: [ + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', + '0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db', + ], + threshold: 2, + }, + ], + threshold: 2, + }; + + // expect 0 updates + await expectTxsAndUpdate(ism, updatedConfig, 0); + + // expect the ISM address to be the same + expect(eqAddress(initialIsmAddress, ism.serialize().deployedIsm)).to.be + .true; + }); }); }); diff --git a/typescript/sdk/src/ism/EvmIsmModule.ts b/typescript/sdk/src/ism/EvmIsmModule.ts index 4b7db71c7..c000cc341 100644 --- a/typescript/sdk/src/ism/EvmIsmModule.ts +++ b/typescript/sdk/src/ism/EvmIsmModule.ts @@ -26,7 +26,6 @@ import { assert, deepEquals, eqAddress, - normalizeConfig, objFilter, rootLogger, } from '@hyperlane-xyz/utils'; @@ -46,6 +45,7 @@ import { ContractVerifier } from '../deploy/verify/ContractVerifier.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { ChainName, ChainNameOrId } from '../types.js'; +import { normalizeConfig } from '../utils/ism.js'; import { findMatchingLogEvents } from '../utils/logUtils.js'; import { EvmIsmReader } from './EvmIsmReader.js'; diff --git a/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts b/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts index 82a8e77a4..6db166c5b 100644 --- a/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts +++ b/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts @@ -24,7 +24,6 @@ import { TestChainName, serializeContracts, } from '@hyperlane-xyz/sdk'; -import { normalizeConfig } from '@hyperlane-xyz/utils'; import { TestCoreApp } from '../core/TestCoreApp.js'; import { TestCoreDeployer } from '../core/TestCoreDeployer.js'; @@ -36,6 +35,7 @@ import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { RemoteRouters } from '../router/types.js'; import { randomAddress } from '../test/testUtils.js'; import { ChainMap } from '../types.js'; +import { normalizeConfig } from '../utils/ism.js'; import { EvmERC20WarpModule } from './EvmERC20WarpModule.js'; import { TokenType } from './config.js'; diff --git a/typescript/sdk/src/token/EvmERC20WarpModule.ts b/typescript/sdk/src/token/EvmERC20WarpModule.ts index 72abe4cc5..d124093c7 100644 --- a/typescript/sdk/src/token/EvmERC20WarpModule.ts +++ b/typescript/sdk/src/token/EvmERC20WarpModule.ts @@ -12,7 +12,6 @@ import { assert, deepEquals, isObjEmpty, - normalizeConfig, rootLogger, } from '@hyperlane-xyz/utils'; @@ -25,6 +24,7 @@ import { DerivedIsmConfig } from '../ism/EvmIsmReader.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { ChainNameOrId } from '../types.js'; +import { normalizeConfig } from '../utils/ism.js'; import { EvmERC20WarpRouteReader } from './EvmERC20WarpRouteReader.js'; import { HypERC20Deployer } from './deploy.js'; diff --git a/typescript/sdk/src/utils/ism.ts b/typescript/sdk/src/utils/ism.ts index ad7c11596..92c267e66 100644 --- a/typescript/sdk/src/utils/ism.ts +++ b/typescript/sdk/src/utils/ism.ts @@ -1,3 +1,5 @@ +import { WithAddress } from '@hyperlane-xyz/utils'; + import { multisigIsmVerifyCosts } from '../consts/multisigIsmVerifyCosts.js'; export function multisigIsmVerificationCost(m: number, n: number): number { @@ -11,3 +13,61 @@ export function multisigIsmVerificationCost(m: number, n: number): number { // @ts-ignore return multisigIsmVerifyCosts[`${n}`][`${m}`]; } + +// Function to recursively remove 'address' properties and lowercase string properties +export function normalizeConfig(obj: WithAddress): any { + return sortArraysInConfig(lowerCaseConfig(obj)); +} + +function lowerCaseConfig(obj: any): any { + if (Array.isArray(obj)) { + return obj.map(normalizeConfig); + } else if (obj !== null && typeof obj === 'object') { + const newObj: any = {}; + for (const key in obj) { + if (key !== 'address') { + newObj[key] = key === 'type' ? obj[key] : normalizeConfig(obj[key]); + } + } + return newObj; + } else if (typeof obj === 'string') { + return obj.toLowerCase(); + } + + return obj; +} + +// write a function that will go through an object and sort any arrays it finds +export function sortArraysInConfig(config: any): any { + // Check if the current object is an array + if (Array.isArray(config)) { + return config.map(sortArraysInConfig); + } + // Check if it's an object and not null + else if (typeof config === 'object' && config !== null) { + const sortedConfig: any = {}; + for (const key in config) { + if (key === 'validators' && Array.isArray(config[key])) { + // Sort the validators array in lexicographical order (since they're already lowercase) + sortedConfig[key] = [...config[key]].sort(); + } + // if key is modules or hooks, sort the objects in the array by their 'type' property + else if ( + (key === 'modules' || key === 'hooks') && + Array.isArray(config[key]) + ) { + sortedConfig[key] = [...config[key]].sort((a: any, b: any) => { + if (a.type < b.type) return -1; + if (a.type > b.type) return 1; + return 0; + }); + } else { + // Recursively apply sorting to other fields + sortedConfig[key] = sortArraysInConfig(config[key]); + } + } + return sortedConfig; + } + + return config; +} diff --git a/typescript/utils/src/index.ts b/typescript/utils/src/index.ts index baf23002d..fdaa20476 100644 --- a/typescript/utils/src/index.ts +++ b/typescript/utils/src/index.ts @@ -102,7 +102,6 @@ export { invertKeysAndValues, isObjEmpty, isObject, - normalizeConfig, objFilter, objKeys, objLength, diff --git a/typescript/utils/src/objects.ts b/typescript/utils/src/objects.ts index 554552050..fda23c0b4 100644 --- a/typescript/utils/src/objects.ts +++ b/typescript/utils/src/objects.ts @@ -2,7 +2,6 @@ import { cloneDeep, isEqual } from 'lodash-es'; import { stringify as yamlStringify } from 'yaml'; import { ethersBigNumberSerializer } from './logging.js'; -import { WithAddress } from './types.js'; import { assert } from './validation.js'; export function isObject(item: any) { @@ -156,22 +155,3 @@ export function stringifyObject( } return yamlStringify(JSON.parse(json), null, space); } - -// Function to recursively remove 'address' properties and lowercase string properties -export function normalizeConfig(obj: WithAddress): any { - if (Array.isArray(obj)) { - return obj.map(normalizeConfig); - } else if (obj !== null && typeof obj === 'object') { - const newObj: any = {}; - for (const key in obj) { - if (key !== 'address') { - newObj[key] = key === 'type' ? obj[key] : normalizeConfig(obj[key]); - } - } - return newObj; - } else if (typeof obj === 'string') { - return obj.toLowerCase(); - } - - return obj; -} From 7f099419e3682b0f4329121f8f307b6e2fa4d2fb Mon Sep 17 00:00:00 2001 From: Roman V Date: Thu, 12 Sep 2024 11:00:50 +0200 Subject: [PATCH 015/224] fix: gracefully handle missing objects for GCS checkpoints (#4453) ### Description The issue with the validator was that it wasn't handling the bucket's 404 response as a correct response when the object is not found when fetching a specific checkpoint or latest index, thus it was getting stuck in a loop failing to submit a checkpoint or get the latest stored index. I fixed it by catching the 404 response in `gcs_storage.rs` and returning `Ok(None)` instead of raising an error, the same way it's handled in S3 Storage. ### Drive-by changes Bumped ya-gcp to the latest 0.11.3 ### Related issues - Fixes #4451 ### Backward compatibility Yes ### Testing Manual --- rust/Cargo.toml | 2 +- rust/hyperlane-base/src/types/gcs_storage.rs | 27 ++++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index fe5aa030e..e449b1936 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -190,7 +190,7 @@ url = "2.3" walkdir = "2" warp = "0.3" which = "4.3" -ya-gcp = { version = "0.11.1", features = ["storage"] } +ya-gcp = { version = "0.11.3", features = ["storage"] } ## TODO: remove this cosmwasm-schema = "1.2.7" diff --git a/rust/hyperlane-base/src/types/gcs_storage.rs b/rust/hyperlane-base/src/types/gcs_storage.rs index 6094ae8c3..e54f65349 100644 --- a/rust/hyperlane-base/src/types/gcs_storage.rs +++ b/rust/hyperlane-base/src/types/gcs_storage.rs @@ -4,7 +4,13 @@ use derive_new::new; use eyre::{bail, Result}; use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId}; use std::fmt; -use ya_gcp::{storage::StorageClient, AuthFlow, ClientBuilder, ClientBuilderConfig}; +use ya_gcp::{ + storage::{ + api::{error::HttpStatusError, http::StatusCode, Error}, + ObjectError, StorageClient, + }, + AuthFlow, ClientBuilder, ClientBuilderConfig, +}; const LATEST_INDEX_KEY: &str = "gcsLatestIndexKey"; const METADATA_KEY: &str = "gcsMetadataKey"; @@ -127,7 +133,10 @@ impl CheckpointSyncer for GcsStorageClient { Ok(data) => Ok(Some(serde_json::from_slice(data.as_ref())?)), Err(e) => match e { // never written before to this bucket - ya_gcp::storage::ObjectError::InvalidName(_) => Ok(None), + ObjectError::InvalidName(_) => Ok(None), + ObjectError::Failure(Error::HttpStatus(HttpStatusError(StatusCode::NOT_FOUND))) => { + Ok(None) + } _ => bail!(e), }, } @@ -153,11 +162,19 @@ impl CheckpointSyncer for GcsStorageClient { /// Attempt to fetch the signed (checkpoint, messageId) tuple at this index async fn fetch_checkpoint(&self, index: u32) -> Result> { - let res = self + match self .inner .get_object(&self.bucket, GcsStorageClient::get_checkpoint_key(index)) - .await?; - Ok(Some(serde_json::from_slice(res.as_ref())?)) + .await + { + Ok(data) => Ok(Some(serde_json::from_slice(data.as_ref())?)), + Err(e) => match e { + ObjectError::Failure(Error::HttpStatus(HttpStatusError(StatusCode::NOT_FOUND))) => { + Ok(None) + } + _ => bail!(e), + }, + } } /// Write the signed (checkpoint, messageId) tuple to this syncer From 95f6421cd93de1555aa3d47138316c602c06dcc8 Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Thu, 12 Sep 2024 10:32:28 +0100 Subject: [PATCH 016/224] fix(infra): Comment out pzETH/ethereum-solana warp route in check (#4477) ### Description - Comment out `pzETH/ethereum-solana` as it is causing the `check-warp-deploy` cronjob to fail as the config has not been added to registry ### Testing Manual --- .../mainnet3/warp/checkWarpDeploy.ts | 2 +- .../getEthereumSolanaPzETHWarpConfig.ts | 34 ------------------- typescript/infra/config/warp.ts | 3 -- typescript/infra/scripts/agent-utils.ts | 4 ++- 4 files changed, 4 insertions(+), 39 deletions(-) delete mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSolanaPzETHWarpConfig.ts diff --git a/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts b/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts index d16bb0510..262e47278 100644 --- a/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts +++ b/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts @@ -4,7 +4,7 @@ import { environment } from '../chains.js'; export const checkWarpDeployConfig: CheckWarpDeployConfig = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '36f7e14-20240823-160646', + tag: '7ce7aef-20240912-090321', }, namespace: environment, cronSchedule: '0 15 * * *', // set to 3pm utc every day diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSolanaPzETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSolanaPzETHWarpConfig.ts deleted file mode 100644 index 83b937b6e..000000000 --- a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSolanaPzETHWarpConfig.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ethers } from 'ethers'; - -import { - ChainMap, - RouterConfig, - TokenRouterConfig, - TokenType, -} from '@hyperlane-xyz/sdk'; - -import { DEPLOYER } from '../../owners.js'; - -export const getEthereumSolanaPzETHWarpConfig = async ( - routerConfig: ChainMap, -): Promise> => { - // @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig - const solana: TokenRouterConfig = { - type: TokenType.synthetic, - foreignDeployment: 'GiP8GwN1GsscVJvmKSD4muDEihRzZRa9mxnS1Toi64pa', - gas: 300_000, - }; - - const ethereum: TokenRouterConfig = { - ...routerConfig.ethereum, - type: TokenType.collateral, - interchainSecurityModule: ethers.constants.AddressZero, - token: '0x8c9532a60e0e7c6bbd2b2c1303f63ace1c3e9811', - owner: DEPLOYER, - }; - - return { - solana, - ethereum, - }; -}; diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index b5ae6f8a0..8f2ea0083 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -13,7 +13,6 @@ import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/ import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js'; import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js'; import { getEthereumInevmUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDTWarpConfig.js'; -import { getEthereumSolanaPzETHWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumSolanaPzETHWarpConfig.js'; import { getEthereumVictionETHWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionETHWarpConfig.js'; import { getEthereumVictionUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionUSDCWarpConfig.js'; import { getEthereumVictionUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionUSDTWarpConfig.js'; @@ -28,7 +27,6 @@ export enum WarpRouteIds { ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', EthereumInevmUSDC = 'USDC/ethereum-inevm', EthereumInevmUSDT = 'USDT/ethereum-inevm', - EthereumSolanaPzETH = 'pzETH/ethereum-solana', EthereumVictionETH = 'ETH/ethereum-viction', EthereumVictionUSDC = 'USDC/ethereum-viction', EthereumVictionUSDT = 'USDT/ethereum-viction', @@ -58,7 +56,6 @@ export const warpConfigGetterMap: Record< [WarpRouteIds.EthereumVictionUSDC]: getEthereumVictionUSDCWarpConfig, [WarpRouteIds.EthereumVictionUSDT]: getEthereumVictionUSDTWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, - [WarpRouteIds.EthereumSolanaPzETH]: getEthereumSolanaPzETHWarpConfig, }; export async function getWarpConfig( diff --git a/typescript/infra/scripts/agent-utils.ts b/typescript/infra/scripts/agent-utils.ts index cec21c424..d7ee700a5 100644 --- a/typescript/infra/scripts/agent-utils.ts +++ b/typescript/infra/scripts/agent-utils.ts @@ -502,7 +502,9 @@ export function getWarpAddresses(warpRouteId: string) { const warpRouteConfig = registry.getWarpRoute(warpRouteId); if (!warpRouteConfig) { - throw new Error(`Warp route config for ${warpRouteId} not found`); + throw new Error( + `Warp route config for ${warpRouteId} not found in registry`, + ); } return warpConfigToWarpAddresses(warpRouteConfig); From b326d4bfce7e7412e23983bd2bf2e948e4a63cc3 Mon Sep 17 00:00:00 2001 From: "L.Y" <141099829+lyfsn@users.noreply.github.com> Date: Thu, 12 Sep 2024 20:24:14 +0800 Subject: [PATCH 017/224] fix: incorrect use of blacklist variable (#4099) ### Description Otherwise, the whitelist will not work; any whitelist parameter will function as a blocklist. Co-authored-by: Trevor Porter --- rust/agents/relayer/src/msg/processor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/agents/relayer/src/msg/processor.rs b/rust/agents/relayer/src/msg/processor.rs index 40808ad3d..8d0422879 100644 --- a/rust/agents/relayer/src/msg/processor.rs +++ b/rust/agents/relayer/src/msg/processor.rs @@ -258,8 +258,8 @@ impl ProcessorExt for MessageProcessor { } // Skip if the message is blacklisted - if self.message_whitelist.msg_matches(&msg, false) { - debug!(?msg, blacklist=?self.message_whitelist, "Message blacklisted, skipping"); + if self.message_blacklist.msg_matches(&msg, false) { + debug!(?msg, blacklist=?self.message_blacklist, "Message blacklisted, skipping"); return Ok(()); } From 73c232b3aaa8ca21921a0151d93de35f01f30ae6 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:26:06 +0100 Subject: [PATCH 018/224] feat: deploy to oort mainnet (#4473) feat: deploy to oort mainnet - registry PR https://github.com/hyperlane-xyz/hyperlane-registry/pull/190 - builds on top of the everclear PR https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4471 --- .changeset/slimy-humans-glow.md | 5 + .registryrc | 2 +- rust/config/mainnet_config.json | 63 ++++++++++ .../config/environments/mainnet3/agent.ts | 13 +- .../mainnet3/aw-validators/hyperlane.json | 3 + .../mainnet3/core/verification.json | 112 ++++++++++++++++++ .../config/environments/mainnet3/funding.ts | 3 +- .../environments/mainnet3/gasPrices.json | 4 + .../mainnet3/ism/verification.json | 86 ++++++++++++++ .../middleware/accounts/verification.json | 40 +++++++ .../mainnet3/supportedChainNames.ts | 1 + .../environments/mainnet3/tokenPrices.json | 1 + .../environments/mainnet3/validators.ts | 12 ++ typescript/sdk/src/consts/multisigIsm.ts | 5 + 14 files changed, 343 insertions(+), 7 deletions(-) create mode 100644 .changeset/slimy-humans-glow.md diff --git a/.changeset/slimy-humans-glow.md b/.changeset/slimy-humans-glow.md new file mode 100644 index 000000000..b9360bc88 --- /dev/null +++ b/.changeset/slimy-humans-glow.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Deploy to oortmainnet diff --git a/.registryrc b/.registryrc index 074ebc6b1..a3ab34ee4 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -7512eac66d258d6cd8e8f417665b8e2ef81ab353 +8e93ecb4fa207fc4822393a4c13627be3da89eaa diff --git a/rust/config/mainnet_config.json b/rust/config/mainnet_config.json index 89255a41a..60e0a6217 100644 --- a/rust/config/mainnet_config.json +++ b/rust/config/mainnet_config.json @@ -3992,6 +3992,69 @@ "testRecipient": "0xF15D70941dE2Bf95A23d6488eBCbedE0a444137f", "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0xC88bAD76EC7acD9fd3b9Bb264f7f5C18097c5710" + }, + "oortmainnet": { + "blockExplorers": [ + { + "apiUrl": "https://mainnet-scan.oortech.com/api", + "family": "other", + "name": "Oort Olympus Explorer", + "url": "https://mainnet-scan.oortech.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 0 + }, + "chainId": 970, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Oort", + "domainId": 970, + "gasCurrencyCoinGeckoId": "oort", + "name": "oortmainnet", + "nativeToken": { + "decimals": 18, + "name": "Oort", + "symbol": "OORT" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet-rpc.oortech.com" + } + ], + "aggregationHook": "0x90F9ac2201bCC0fA177955175708eCB5963f0eCA", + "domainRoutingIsm": "0x4101B9B755FC58FcEA156e70B42a38CFF8A46F77", + "domainRoutingIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "fallbackRoutingHook": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "interchainAccountIsm": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319", + "interchainAccountRouter": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE", + "interchainGasPaymaster": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86", + "interchainSecurityModule": "0xdc2da0D5d7A69fa86366235E426ff4a0E214cC60", + "mailbox": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "merkleTreeHook": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "pausableHook": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2", + "pausableIsm": "0x989B7307d266151BE763935C856493D968b2affF", + "protocolFee": "0xfdefdDc8E153d5E0463d7E193F79A3714be16021", + "proxyAdmin": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", + "staticAggregationHookFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticAggregationIsm": "0xdc2da0D5d7A69fa86366235E426ff4a0E214cC60", + "staticAggregationIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMerkleRootMultisigIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootWeightedMultisigIsmFactory": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticMessageIdMultisigIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticMessageIdWeightedMultisigIsmFactory": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "storageGasOracle": "0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67", + "testRecipient": "0x58556AaeB2e3829d52EE5E711D44735412efA43B", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c", + "index": { + "from": 26847587 + } } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 77a29775d..961e8637f 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -93,6 +93,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< molten: true, moonbeam: true, neutron: true, + oortmainnet: true, optimism: true, osmosis: true, polygon: true, @@ -156,6 +157,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< moonbeam: true, // At the moment, we only relay between Neutron and Manta Pacific on the neutron context. neutron: false, + oortmainnet: true, optimism: true, osmosis: true, polygon: true, @@ -221,6 +223,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< moonbeam: true, // Cannot scrape non-EVM chains neutron: false, + oortmainnet: true, optimism: true, // Cannot scrape non-EVM chains osmosis: false, @@ -375,7 +378,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'd71dd4e-20240910-140936', + tag: '9c056c7-20240911-154357', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -384,7 +387,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: 'd71dd4e-20240910-140936', + tag: '9c056c7-20240911-154357', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -394,7 +397,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'd71dd4e-20240910-140936', + tag: '9c056c7-20240911-154357', }, resources: scraperResources, }, @@ -409,7 +412,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'd71dd4e-20240910-140936', + tag: '9c056c7-20240911-154357', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. @@ -421,7 +424,7 @@ const releaseCandidate: RootAgentConfig = { validators: { docker: { repo, - tag: 'd71dd4e-20240910-140936', + tag: '9c056c7-20240911-154357', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.ReleaseCandidate), diff --git a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json index 885ec4112..2e38a8dd6 100644 --- a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json @@ -160,6 +160,9 @@ "0x7885fae56dbcf5176657f54adbbd881dc6714132" ] }, + "oortmainnet": { + "validators": ["0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7"] + }, "optimism": { "validators": [ "0x20349eadc6c72e94ce38268b96692b1a5c20de4f", diff --git a/typescript/infra/config/environments/mainnet3/core/verification.json b/typescript/infra/config/environments/mainnet3/core/verification.json index 9d589b726..4c982fd36 100644 --- a/typescript/infra/config/environments/mainnet3/core/verification.json +++ b/typescript/infra/config/environments/mainnet3/core/verification.json @@ -3523,5 +3523,117 @@ "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", "isProxy": false } + ], + "oortmainnet": [ + { + "name": "PausableIsm", + "address": "0x31894E7a734540B343d67E491148EB4FC9f7A45B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x3C2b535a49c6827DF0b8e94467e6922c99E3c092", + "constructorArguments": "000000000000000000000000b163e75e2008cdc94e50278b5fcdd081761a2ee4", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", + "constructorArguments": "000000000000000000000000b163e75e2008cdc94e50278b5fcdd081761a2ee4000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000003c2b535a49c6827df0b8e94467e6922c99e3c092", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xf8344D85a1429708e0BE6724218E938087e596DF", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x8AB7A6FaC052518A39628497735C855a2Beb515B", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86", + "constructorArguments": "0000000000000000000000008ab7a6fac052518a39628497735c855a2beb515b0000000000000000000000008d078f74df9e5a4fa8da06f2abce5d01fdf793c200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x8AB7A6FaC052518A39628497735C855a2Beb515B" + }, + { + "name": "ProtocolFee", + "address": "0x199ba45E836440f2cCe00aa60466Ae0e733D6647", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xcd9D3744512F07AE844c40E27912092d7c503565", + "constructorArguments": "000000000000000000000000b163e75e2008cdc94e50278b5fcdd081761a2ee4", + "isProxy": false + }, + { + "name": "ProxyAdmin", + "address": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000003ca", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "constructorArguments": "000000000000000000000000cd849e612aaa138f03698c3edb42a34117bff631000000000000000000000000148cf67b8a242c1360bb2c93fce203ec4d4f9b5600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631" + }, + { + "name": "PausableIsm", + "address": "0x989B7307d266151BE763935C856493D968b2affF", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "constructorArguments": "000000000000000000000000b129828b9eda48192d0b2db35d0e40dcf51b3594", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "000000000000000000000000b129828b9eda48192d0b2db35d0e40dcf51b3594000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "ProtocolFee", + "address": "0xfdefdDc8E153d5E0463d7E193F79A3714be16021", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c", + "constructorArguments": "000000000000000000000000b129828b9eda48192d0b2db35d0e40dcf51b3594", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index 223f32d1a..601f07b38 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: 'd71dd4e-20240910-140936', + tag: '9c056c7-20240911-154400', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron @@ -62,6 +62,7 @@ export const keyFunderConfig: KeyFunderConfig< mode: '0.2', molten: '3', moonbeam: '5', + oortmainnet: '2000', optimism: '0.5', polygon: '20', polygonzkevm: '0.5', diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 76ed0334d..042437b60 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -155,6 +155,10 @@ "amount": "0.0053", "decimals": 1 }, + "oortmainnet": { + "amount": "100.0", + "decimals": 9 + }, "optimism": { "amount": "0.25", "decimals": 9 diff --git a/typescript/infra/config/environments/mainnet3/ism/verification.json b/typescript/infra/config/environments/mainnet3/ism/verification.json index 00d025f90..160c21939 100644 --- a/typescript/infra/config/environments/mainnet3/ism/verification.json +++ b/typescript/infra/config/environments/mainnet3/ism/verification.json @@ -4938,5 +4938,91 @@ "constructorArguments": "", "isProxy": true } + ], + "oortmainnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xe139ceA3397ABfE745B3A4a9f6976A6519754100", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x70296bdA00742EA05A46aAE3B11b16C38134c992", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x8aEA374F73d0b1182A6cdf5Cc9143f777D03b279", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0xDE3c6d94dA0b4c066b46eDE6ECf9F10237E8389a", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x23cEB84ddEe5cfC3d98F98b7501e96fB0de8D2E3", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x8928Fe94d9145623b4359F3C36C819C7f5086E6b", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xD898F08AA84b97B7a3F6f259b81bb86FaF00E867", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json index e82d33e68..d10e534a6 100644 --- a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json @@ -1159,5 +1159,45 @@ "isProxy": true, "expectedimplementation": "0x58556AaeB2e3829d52EE5E711D44735412efA43B" } + ], + "oortmainnet": [ + { + "name": "InterchainAccountIsm", + "address": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8", + "constructorArguments": "000000000000000000000000b163e75e2008cdc94e50278b5fcdd081761a2ee4", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "constructorArguments": "000000000000000000000000b163e75e2008cdc94e50278b5fcdd081761a2ee4", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "constructorArguments": "000000000000000000000000662771d29dff0d7c36bb9bb6d4241a02e77585d90000000000000000000000008d078f74df9e5a4fa8da06f2abce5d01fdf793c200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000092cdbf0ccdf8e93467fa858fb986fa650a02f2a8000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9" + }, + { + "name": "InterchainAccountIsm", + "address": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319", + "constructorArguments": "000000000000000000000000b129828b9eda48192d0b2db35d0e40dcf51b3594", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x376aD181E8cd45eAd5403F78d5A871D08c3c4D77", + "constructorArguments": "000000000000000000000000b129828b9eda48192d0b2db35d0e40dcf51b3594", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE", + "constructorArguments": "000000000000000000000000376ad181e8cd45ead5403f78d5a871d08c3c4d77000000000000000000000000148cf67b8a242c1360bb2c93fce203ec4d4f9b5600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c23baf5eb5848d19701bbe7f139645e6bd58a319000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x376aD181E8cd45eAd5403F78d5A871D08c3c4D77" + } ] } diff --git a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts index c477fe4c5..ec68bab48 100644 --- a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts +++ b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts @@ -40,6 +40,7 @@ export const mainnet3SupportedChainNames = [ 'molten', 'moonbeam', 'neutron', + 'oortmainnet', 'optimism', 'osmosis', 'polygon', diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index d0ef62336..121d89832 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -38,6 +38,7 @@ "molten": "0.663236", "moonbeam": "0.159678", "neutron": "0.359547", + "oortmainnet": "0.089435", "optimism": "2342.46", "osmosis": "0.39708", "polygon": "0.384058", diff --git a/typescript/infra/config/environments/mainnet3/validators.ts b/typescript/infra/config/environments/mainnet3/validators.ts index b0be3a142..fb0609db2 100644 --- a/typescript/infra/config/environments/mainnet3/validators.ts +++ b/typescript/infra/config/environments/mainnet3/validators.ts @@ -884,5 +884,17 @@ export const validatorChainConfig = ( 'everclear', ), }, + oortmainnet: { + interval: 5, + reorgPeriod: getReorgPeriod('oortmainnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7'], + [Contexts.ReleaseCandidate]: [''], + [Contexts.Neutron]: [], + }, + 'oortmainnet', + ), + }, }; }; diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index 9a2f49fa3..473ff86a3 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -401,6 +401,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + oortmainnet: { + threshold: 1, + validators: ['0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7'], + }, + optimism: { threshold: 3, validators: [ From 1a8cc278183188bb0f31cb40fa16b131f606da5d Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 12 Sep 2024 15:07:56 +0100 Subject: [PATCH 019/224] fix: ignore some testnet4 contracts to reduce prep queues, update testnet4 images, stop relaying solanatestnet (#4478) ### Description - Mitosis had previously done some load testing from sepolia to optimismsepolia | arbitrumsepolia, so there were prep queues of 235k+! - Ignores the offending contracts whose mailboxes are different from the ones we deployed, so these messages are forever unprocessable: ``` $ cast call 0x3da95d8d0b98d7428dc2f864511e2650e34f7087 'mailbox()(address)' --rpc-url $(rpc arbitrumsepolia) 0xBA42Ee5864884C77a683E1dda390c6f6aE144167 $ addy arbitrumsepolia mailbox 0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8 ``` - Updates the image as a drive-by - Stops relaying and validating on solantestnet, which is now old (doesn't include protocol fees) which is incompatible with the agents on `main`. This is because the account storage layout that the agents read has changed. Solantestnet isn't used for anything anymore because eclipsetestnet was also shut down ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../config/environments/testnet4/agent.ts | 55 +++++++++++++------ .../testnet4/aw-validators/hyperlane.json | 3 - 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index 9b4a4bd07..43a210e29 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -1,6 +1,7 @@ import { GasPaymentEnforcement, GasPaymentEnforcementPolicyType, + MatchingList, RpcConsensusType, } from '@hyperlane-xyz/sdk'; @@ -9,9 +10,13 @@ import { RootAgentConfig, getAgentChainNamesFromConfig, } from '../../../src/config/agent/agent.js'; -import { routerMatchingList } from '../../../src/config/agent/relayer.js'; +import { + BaseRelayerConfig, + routerMatchingList, +} from '../../../src/config/agent/relayer.js'; import { ALL_KEY_ROLES, Role } from '../../../src/roles.js'; import { Contexts } from '../../contexts.js'; +import { getDomainId } from '../../registry.js'; import { environment } from './chains.js'; import { helloWorld } from './helloworld.js'; @@ -51,7 +56,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< polygonamoy: true, scrollsepolia: true, sepolia: true, - solanatestnet: true, + solanatestnet: false, superpositiontestnet: true, }, [Role.Relayer]: { @@ -69,7 +74,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< polygonamoy: true, scrollsepolia: true, sepolia: true, - solanatestnet: true, + solanatestnet: false, superpositiontestnet: true, }, [Role.Scraper]: { @@ -137,6 +142,29 @@ const scraperResources = { }, }; +const relayBlacklist: BaseRelayerConfig['blacklist'] = [ + { + // In an effort to reduce some giant retry queues that resulted + // from spam txs to the old TestRecipient before we were charging for + // gas, we blacklist the old TestRecipient address. + recipientAddress: '0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE', + }, + // Ignore load testing done by Mitosis from sepolia when they used a different Mailbox on + // arbitrumsepolia and optimismsepolia. + { + originDomain: getDomainId('sepolia'), + senderAddress: '0xb6f4a8dccac0beab1062212f4665879d9937c83c', + destinationDomain: getDomainId('arbitrumsepolia'), + recipientAddress: '0x3da95d8d0b98d7428dc2f864511e2650e34f7087', + }, + { + originDomain: getDomainId('sepolia'), + senderAddress: '0xb6f4a8dccac0beab1062212f4665879d9937c83c', + destinationDomain: getDomainId('optimismsepolia'), + recipientAddress: '0xa49942c908ec50db14652914317518661ec04904', + }, +]; + const hyperlane: RootAgentConfig = { ...contextBase, contextChainNames: hyperlaneContextAgentChainNames, @@ -146,17 +174,9 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'd0ce062-20240813-215255', + tag: '73c232b-20240912-124300', }, - blacklist: [ - ...releaseCandidateHelloworldMatchingList, - { - // In an effort to reduce some giant retry queues that resulted - // from spam txs to the old TestRecipient before we were charging for - // gas, we blacklist the old TestRecipient address. - recipientAddress: '0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE', - }, - ], + blacklist: [...releaseCandidateHelloworldMatchingList, ...relayBlacklist], gasPaymentEnforcement, metricAppContexts: [ { @@ -176,7 +196,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'd0ce062-20240813-215255', + tag: '73c232b-20240912-124300', }, chains: validatorChainConfig(Contexts.Hyperlane), resources: validatorResources, @@ -185,7 +205,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'd0ce062-20240813-215255', + tag: '73c232b-20240912-124300', }, resources: scraperResources, }, @@ -200,9 +220,10 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '0d12ff3-20240620-173353', + tag: '73c232b-20240912-124300', }, whitelist: [...releaseCandidateHelloworldMatchingList], + blacklist: relayBlacklist, gasPaymentEnforcement, transactionGasLimit: 750000, resources: relayerResources, @@ -211,7 +232,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '0d12ff3-20240620-173353', + tag: '73c232b-20240912-124300', }, chains: validatorChainConfig(Contexts.ReleaseCandidate), resources: validatorResources, diff --git a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json index bd44812c5..e1f39aaab 100644 --- a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json @@ -62,9 +62,6 @@ "0xd3c75dcf15056012a4d74c483a0c6ea11d8c2b83" ] }, - "solanatestnet": { - "validators": ["0xd4ce8fa138d4e083fc0e480cca0dbfa4f5f30bd5"] - }, "superpositiontestnet": { "validators": ["0x1d3168504b23b73cdf9c27f13bb0a595d7f1a96a"] } From 096aeff13e58c12c453b3df51d19e958ee7e86cd Mon Sep 17 00:00:00 2001 From: Mantas-M <120508669+Mantas-M@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:02:12 +0200 Subject: [PATCH 020/224] feat: Splitting `rust` workspace into `main` and `sealevel` (#4438) ### Description The single rust workspace has been split into 2 workspaces. The sealevel workspace includes the contents of the previous `sealevel` folder and the main workspace includes everything else. The workspaces differ in rust versions as the sealevel has the old one to ensure compatability, the main workspace has and updated `rustc` version of `1.80.1`. Some dependencies and sub-dependencies have been locked in versions of the old pre-split workspace to ensure no breaking code changes. The rust CI workflow has been updated to include both workspaces in the tests. ### Drive-by changes N/A ### Related issues Relates to https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4361 ### Backward compatibility No. ### Testing Rust Unit tests from the CI --- .codespell/.codespellrc | 2 +- .github/workflows/rust.yml | 62 +- .github/workflows/test.yml | 21 +- .gitignore | 3 +- rust/Dockerfile | 35 +- .../hyperlane-fuel/abis/Mailbox.abi.json | 530 -- rust/chains/hyperlane-fuel/src/mailbox.rs | 164 - rust/chains/hyperlane-fuel/src/provider.rs | 43 - rust/chains/hyperlane-sealevel/Cargo.toml | 35 - rust/{ => main}/.cargo/config.toml | 0 rust/{ => main}/.vscode/extensions.json | 0 rust/{ => main}/.vscode/settings.json | 0 rust/{ => main}/Cargo.lock | 3936 ++++----- rust/main/Cargo.toml | 337 + .../agents/relayer/.cargo/config.toml | 0 rust/{ => main}/agents/relayer/Cargo.toml | 13 +- rust/{ => main}/agents/relayer/src/lib.rs | 0 rust/{ => main}/agents/relayer/src/main.rs | 0 .../agents/relayer/src/memory_profiler.rs | 0 .../agents/relayer/src/merkle_tree/builder.rs | 0 .../agents/relayer/src/merkle_tree/mod.rs | 0 .../relayer/src/merkle_tree/processor.rs | 0 .../agents/relayer/src/msg/blacklist.rs | 0 .../agents/relayer/src/msg/gas_payment/mod.rs | 0 .../src/msg/gas_payment/policies/minimum.rs | 0 .../src/msg/gas_payment/policies/mod.rs | 0 .../src/msg/gas_payment/policies/none.rs | 0 .../policies/on_chain_fee_quoting.rs | 0 .../relayer/src/msg/metadata/aggregation.rs | 1 + .../agents/relayer/src/msg/metadata/base.rs | 3 + .../relayer/src/msg/metadata/ccip_read.rs | 2 + .../agents/relayer/src/msg/metadata/mod.rs | 0 .../relayer/src/msg/metadata/multisig/base.rs | 0 .../metadata/multisig/merkle_root_multisig.rs | 0 .../metadata/multisig/message_id_multisig.rs | 0 .../relayer/src/msg/metadata/multisig/mod.rs | 1 + .../relayer/src/msg/metadata/null_metadata.rs | 1 + .../relayer/src/msg/metadata/routing.rs | 1 + rust/{ => main}/agents/relayer/src/msg/mod.rs | 2 + .../agents/relayer/src/msg/op_queue.rs | 0 .../agents/relayer/src/msg/op_submitter.rs | 3 + .../agents/relayer/src/msg/pending_message.rs | 6 +- .../agents/relayer/src/msg/processor.rs | 0 .../agents/relayer/src/processor.rs | 0 rust/{ => main}/agents/relayer/src/prover.rs | 0 rust/{ => main}/agents/relayer/src/relayer.rs | 0 .../relayer/src/server/list_messages.rs | 0 .../relayer/src/server/message_retry.rs | 0 .../agents/relayer/src/server/mod.rs | 0 .../relayer/src/settings/matching_list.rs | 0 .../agents/relayer/src/settings/mod.rs | 0 rust/{ => main}/agents/scraper/Cargo.toml | 1 - rust/{ => main}/agents/scraper/README.md | 0 .../agents/scraper/migration/Cargo.toml | 8 +- .../agents/scraper/migration/README.md | 0 .../agents/scraper/migration/bin/common.rs | 0 .../agents/scraper/migration/bin/down.rs | 0 .../agents/scraper/migration/bin/fresh.rs | 0 .../migration/bin/generate_entities.rs | 0 .../agents/scraper/migration/bin/init_db.rs | 0 .../scraper/migration/bin/recreate_db.rs | 0 .../scraper/migration/src/l20230309_types.rs | 0 .../agents/scraper/migration/src/lib.rs | 0 .../m20230309_000001_create_table_domain.rs | 0 .../m20230309_000002_create_table_block.rs | 0 .../m20230309_000003_create_table_cursor.rs | 0 ...0230309_000003_create_table_transaction.rs | 0 ...9_000004_create_table_delivered_message.rs | 0 ...0230309_000004_create_table_gas_payment.rs | 0 .../m20230309_000005_create_table_message.rs | 0 rust/{ => main}/agents/scraper/src/agent.rs | 0 .../agents/scraper/src/chain_scraper/mod.rs | 2 + .../agents/scraper/src/conversions.rs | 0 .../agents/scraper/src/date_time.rs | 0 .../{ => main}/agents/scraper/src/db/block.rs | 0 .../agents/scraper/src/db/block_cursor.rs | 0 .../agents/scraper/src/db/generated/block.rs | 0 .../agents/scraper/src/db/generated/cursor.rs | 0 .../src/db/generated/delivered_message.rs | 0 .../agents/scraper/src/db/generated/domain.rs | 0 .../scraper/src/db/generated/gas_payment.rs | 0 .../scraper/src/db/generated/message.rs | 0 .../agents/scraper/src/db/generated/mod.rs | 0 .../scraper/src/db/generated/prelude.rs | 2 +- .../scraper/src/db/generated/transaction.rs | 0 .../agents/scraper/src/db/message.rs | 3 +- rust/{ => main}/agents/scraper/src/db/mod.rs | 0 .../agents/scraper/src/db/payment.rs | 0 rust/{ => main}/agents/scraper/src/db/txn.rs | 0 rust/{ => main}/agents/scraper/src/main.rs | 0 .../{ => main}/agents/scraper/src/settings.rs | 0 rust/{ => main}/agents/validator/Cargo.toml | 6 +- rust/{ => main}/agents/validator/src/main.rs | 0 .../agents/validator/src/server/eigen_node.rs | 2 + .../agents/validator/src/server/mod.rs | 0 .../agents/validator/src/settings.rs | 0 .../{ => main}/agents/validator/src/submit.rs | 0 .../agents/validator/src/validator.rs | 0 .../chains/hyperlane-cosmos/Cargo.toml | 10 +- .../hyperlane-cosmos/src/aggregation_ism.rs | 1 + .../chains/hyperlane-cosmos/src/error.rs | 0 .../hyperlane-cosmos/src/interchain_gas.rs | 2 +- .../src/interchain_security_module.rs | 0 .../chains/hyperlane-cosmos/src/lib.rs | 1 + .../hyperlane-cosmos/src/libs/account.rs | 0 .../hyperlane-cosmos/src/libs/address.rs | 0 .../chains/hyperlane-cosmos/src/libs/mod.rs | 0 .../chains/hyperlane-cosmos/src/mailbox.rs | 0 .../hyperlane-cosmos/src/mailbox/contract.rs | 6 + .../src/mailbox/delivery_indexer.rs | 0 .../src/mailbox/dispatch_indexer.rs | 0 .../hyperlane-cosmos/src/merkle_tree_hook.rs | 5 +- .../hyperlane-cosmos/src/multisig_ism.rs | 0 .../src/payloads/aggregate_ism.rs | 0 .../hyperlane-cosmos/src/payloads/general.rs | 0 .../src/payloads/ism_routes.rs | 0 .../hyperlane-cosmos/src/payloads/mailbox.rs | 0 .../src/payloads/merkle_tree_hook.rs | 0 .../hyperlane-cosmos/src/payloads/mod.rs | 0 .../src/payloads/multisig_ism.rs | 0 .../src/payloads/validator_announce.rs | 0 .../hyperlane-cosmos/src/providers/grpc.rs | 0 .../src/providers/grpc/tests.rs | 0 .../hyperlane-cosmos/src/providers/mod.rs | 1 + .../hyperlane-cosmos/src/providers/rpc.rs | 4 +- .../hyperlane-cosmos/src/routing_ism.rs | 0 .../src/rpc_clients/fallback.rs | 0 .../hyperlane-cosmos/src/rpc_clients/mod.rs | 0 .../chains/hyperlane-cosmos/src/signers.rs | 0 .../hyperlane-cosmos/src/trait_builder.rs | 0 .../chains/hyperlane-cosmos/src/types.rs | 0 .../chains/hyperlane-cosmos/src/utils.rs | 0 .../src/validator_announce.rs | 0 .../chains/hyperlane-ethereum/.gitignore | 0 .../chains/hyperlane-ethereum/Cargo.toml | 4 +- .../abis/ArbitrumNodeInterface.abi.json | 0 .../abis/IAggregationIsm.abi.json | 0 .../abis/ICcipReadIsm.abi.json | 0 .../abis/IInterchainGasPaymaster.abi.json | 0 .../abis/IInterchainSecurityModule.abi.json | 0 .../hyperlane-ethereum/abis/IMailbox.abi.json | 0 .../abis/IMultisigIsm.abi.json | 0 .../abis/IRoutingIsm.abi.json | 0 .../abis/IValidatorAnnounce.abi.json | 0 .../hyperlane-ethereum/abis/Mailbox.abi.json | 0 .../abis/MerkleTreeHook.abi.json | 0 .../chains/hyperlane-ethereum/build.rs | 0 .../chains/hyperlane-ethereum/src/config.rs | 0 .../src/contracts/interchain_gas.rs | 2 + .../src/contracts/mailbox.rs | 3 + .../src/contracts/merkle_tree_hook.rs | 2 + .../hyperlane-ethereum/src/contracts/mod.rs | 0 .../src/contracts/multicall.rs | 0 .../hyperlane-ethereum/src/contracts/utils.rs | 0 .../src/contracts/validator_announce.rs | 1 + .../chains/hyperlane-ethereum/src/error.rs | 0 .../src/ism/aggregation_ism.rs | 1 + .../src/ism/ccip_read_ism.rs | 1 + .../src/ism/interchain_security_module.rs | 0 .../chains/hyperlane-ethereum/src/ism/mod.rs | 0 .../src/ism/multisig_ism.rs | 1 + .../hyperlane-ethereum/src/ism/routing_ism.rs | 1 + .../chains/hyperlane-ethereum/src/lib.rs | 0 .../src/rpc_clients/fallback.rs | 1 + .../hyperlane-ethereum/src/rpc_clients/mod.rs | 0 .../src/rpc_clients/provider.rs | 4 + .../src/rpc_clients/retrying.rs | 0 .../src/rpc_clients/trait_builder.rs | 0 .../hyperlane-ethereum/src/signer/mod.rs | 0 .../src/signer/singleton.rs | 0 .../chains/hyperlane-ethereum/src/tx.rs | 0 .../hyperlane-ethereum/tests/signer_output.rs | 0 .../chains/hyperlane-fuel/.gitignore | 0 .../chains/hyperlane-fuel/Cargo.toml | 5 +- .../hyperlane-fuel/abis/Mailbox.abi.json | 1282 +++ .../{ => main}/chains/hyperlane-fuel/build.rs | 0 .../chains/hyperlane-fuel/src/conversions.rs | 6 + .../hyperlane-fuel/src/interchain_gas.rs | 0 .../chains/hyperlane-fuel/src/lib.rs | 0 .../main/chains/hyperlane-fuel/src/mailbox.rs | 316 + .../chains/hyperlane-fuel/src/multisig_ism.rs | 0 .../chains/hyperlane-fuel/src/provider.rs | 409 + .../chains/hyperlane-fuel/src/routing_ism.rs | 0 .../hyperlane-fuel/src/trait_builder.rs | 9 +- .../hyperlane-fuel/src/validator_announce.rs | 0 .../main/chains/hyperlane-sealevel/Cargo.toml | 44 + .../chains/hyperlane-sealevel/src/client.rs | 0 .../chains/hyperlane-sealevel/src/error.rs | 0 .../hyperlane-sealevel/src/interchain_gas.rs | 3 + .../src/interchain_security_module.rs | 0 .../chains/hyperlane-sealevel/src/lib.rs | 0 .../chains/hyperlane-sealevel/src/mailbox.rs | 0 .../src/merkle_tree_hook.rs | 3 + .../hyperlane-sealevel/src/multisig_ism.rs | 0 .../chains/hyperlane-sealevel/src/provider.rs | 0 .../hyperlane-sealevel/src/trait_builder.rs | 0 .../chains/hyperlane-sealevel/src/utils.rs | 0 .../src/validator_announce.rs | 1 + rust/{ => main}/config/mainnet_config.json | 0 .../test_deployer-account.json | 0 .../test_deployer-keypair.json | 0 .../config/test_sealevel_config.json | 0 rust/{ => main}/config/testnet_config.json | 0 rust/{ => main}/ethers-prometheus/.gitignore | 0 rust/{ => main}/ethers-prometheus/Cargo.toml | 2 - .../ethers-prometheus/abis/Erc20.abi.json | 0 rust/{ => main}/ethers-prometheus/build.rs | 0 .../ethers-prometheus/src/json_rpc_client.rs | 0 rust/{ => main}/ethers-prometheus/src/lib.rs | 0 .../ethers-prometheus/src/middleware/error.rs | 0 .../ethers-prometheus/src/middleware/mod.rs | 3 +- rust/{ => main}/helm/agent-common/Chart.yaml | 0 .../helm/agent-common/templates/_helpers.tpl | 0 .../helm/hyperlane-agent/.helmignore | 0 .../helm/hyperlane-agent/Chart.lock | 0 .../helm/hyperlane-agent/Chart.yaml | 0 .../helm/hyperlane-agent/templates/NOTES.txt | 0 .../hyperlane-agent/templates/_helpers.tpl | 0 .../hyperlane-agent/templates/configmap.yaml | 0 .../templates/external-secret.yaml | 0 .../templates/relayer-external-secret.yaml | 0 .../templates/relayer-statefulset.yaml | 0 .../templates/scraper-external-secret.yaml | 0 .../templates/scraper-statefulset.yaml | 0 .../templates/serviceaccount.yaml | 0 .../templates/validator-configmap.yaml | 0 .../templates/validator-external-secret.yaml | 0 .../templates/validator-statefulset.yaml | 0 .../helm/hyperlane-agent/values.yaml | 0 rust/{ => main}/hyperlane-base/Cargo.toml | 4 +- rust/{ => main}/hyperlane-base/build.rs | 0 rust/{ => main}/hyperlane-base/src/agent.rs | 1 + .../src/contract_sync/broadcast.rs | 0 .../src/contract_sync/cursors/mod.rs | 0 .../src/contract_sync/cursors/rate_limited.rs | 0 .../cursors/sequence_aware/backward.rs | 1 + .../cursors/sequence_aware/forward.rs | 1 + .../cursors/sequence_aware/mod.rs | 0 .../src/contract_sync/eta_calculator.rs | 0 .../src/contract_sync/metrics.rs | 0 .../hyperlane-base/src/contract_sync/mod.rs | 0 rust/{ => main}/hyperlane-base/src/db/mod.rs | 0 .../src/db/rocks/hyperlane_db.rs | 0 .../hyperlane-base/src/db/rocks/iterator.rs | 0 .../hyperlane-base/src/db/rocks/mod.rs | 0 .../src/db/rocks/storage_types.rs | 0 .../hyperlane-base/src/db/rocks/test_utils.rs | 0 .../hyperlane-base/src/db/rocks/typed_db.rs | 0 rust/{ => main}/hyperlane-base/src/lib.rs | 0 .../{ => main}/hyperlane-base/src/metadata.rs | 0 .../src/metrics/agent_metrics.rs | 1 + .../hyperlane-base/src/metrics/core.rs | 0 .../src/metrics/json_rpc_client.rs | 0 .../hyperlane-base/src/metrics/mod.rs | 0 .../hyperlane-base/src/metrics/provider.rs | 0 .../src/oneline_eyre/handler.rs | 0 .../hyperlane-base/src/oneline_eyre/mod.rs | 0 .../hyperlane-base/src/server/base_server.rs | 0 .../hyperlane-base/src/server/mod.rs | 0 .../src/settings/aws_credentials.rs | 3 + .../hyperlane-base/src/settings/base.rs | 0 .../hyperlane-base/src/settings/chains.rs | 1 + .../src/settings/checkpoint_syncer.rs | 0 .../src/settings/loader/arguments.rs | 0 .../src/settings/loader/case_adapter.rs | 0 .../src/settings/loader/environment.rs | 0 .../hyperlane-base/src/settings/loader/mod.rs | 0 .../hyperlane-base/src/settings/mod.rs | 0 .../src/settings/parser/connection_parser.rs | 1 + .../src/settings/parser/json_value_parser.rs | 1 + .../hyperlane-base/src/settings/parser/mod.rs | 0 .../hyperlane-base/src/settings/signers.rs | 2 +- .../hyperlane-base/src/settings/trace/fmt.rs | 0 .../hyperlane-base/src/settings/trace/mod.rs | 0 .../src/settings/trace/span_metrics.rs | 0 .../src/traits/checkpoint_syncer.rs | 0 .../hyperlane-base/src/traits/mod.rs | 0 .../hyperlane-base/src/types/gcs_storage.rs | 0 .../hyperlane-base/src/types/local_storage.rs | 0 .../hyperlane-base/src/types/mod.rs | 0 .../hyperlane-base/src/types/multisig.rs | 0 .../hyperlane-base/src/types/s3_storage.rs | 0 .../hyperlane-base/src/types/utils.rs | 0 .../hyperlane-base/tests/chain_config.rs | 0 rust/{ => main}/hyperlane-core/Cargo.toml | 9 +- .../src/accumulator/incremental.rs | 0 .../hyperlane-core/src/accumulator/merkle.rs | 0 .../hyperlane-core/src/accumulator/mod.rs | 0 .../hyperlane-core/src/accumulator/sparse.rs | 0 .../src/accumulator/zero_hashes.rs | 0 rust/{ => main}/hyperlane-core/src/chain.rs | 0 .../hyperlane-core/src/config/config_path.rs | 0 .../hyperlane-core/src/config/mod.rs | 0 .../hyperlane-core/src/config/str_or_int.rs | 1 + .../hyperlane-core/src/config/trait_ext.rs | 0 rust/{ => main}/hyperlane-core/src/error.rs | 0 rust/{ => main}/hyperlane-core/src/lib.rs | 2 +- .../hyperlane-core/src/metrics/agent.rs | 0 .../hyperlane-core/src/metrics/mod.rs | 0 .../hyperlane-core/src/rpc_clients/error.rs | 0 .../src/rpc_clients/fallback.rs | 0 .../hyperlane-core/src/rpc_clients/mod.rs | 0 .../hyperlane-core/src/rpc_clients/retry.rs | 0 .../hyperlane-core/src/test_output.rs | 0 .../hyperlane-core/src/test_utils.rs | 0 .../src/traits/aggregation_ism.rs | 0 .../src/traits/ccip_read_ism.rs | 0 .../hyperlane-core/src/traits/cursor.rs | 0 .../hyperlane-core/src/traits/db.rs | 0 .../hyperlane-core/src/traits/deployed.rs | 0 .../hyperlane-core/src/traits/encode.rs | 0 .../hyperlane-core/src/traits/indexer.rs | 0 .../src/traits/interchain_gas.rs | 0 .../src/traits/interchain_security_module.rs | 0 .../hyperlane-core/src/traits/mailbox.rs | 0 .../src/traits/merkle_tree_hook.rs | 0 .../hyperlane-core/src/traits/mod.rs | 0 .../hyperlane-core/src/traits/multisig_ism.rs | 0 .../src/traits/pending_operation.rs | 0 .../hyperlane-core/src/traits/provider.rs | 0 .../hyperlane-core/src/traits/routing_ism.rs | 0 .../hyperlane-core/src/traits/signing.rs | 0 .../src/traits/validator_announce.rs | 0 .../hyperlane-core/src/types/announcement.rs | 0 .../hyperlane-core/src/types/chain_data.rs | 0 .../hyperlane-core/src/types/checkpoint.rs | 0 .../hyperlane-core/src/types/identifiers.rs | 0 .../hyperlane-core/src/types/indexing.rs | 0 .../hyperlane-core/src/types/log_metadata.rs | 1 + .../hyperlane-core/src/types/merkle_tree.rs | 0 .../hyperlane-core/src/types/message.rs | 2 +- .../hyperlane-core/src/types/mod.rs | 0 .../src/types/primitive_types.rs | 2 +- .../hyperlane-core/src/types/serialize.rs | 2 + .../hyperlane-core/src/types/transaction.rs | 0 rust/{ => main}/hyperlane-core/src/utils.rs | 0 rust/{ => main}/hyperlane-test/Cargo.toml | 2 - rust/{ => main}/hyperlane-test/src/lib.rs | 1 + .../hyperlane-test/src/mocks/mailbox.rs | 0 .../hyperlane-test/src/mocks/mod.rs | 0 .../src/mocks/validator_announce.rs | 0 rust/main/rust-toolchain | 3 + rust/{ => main}/terraform/.gitignore | 0 rust/{ => main}/terraform/README.md | 0 rust/{ => main}/terraform/globals.tf | 0 rust/{ => main}/terraform/main.tf | 0 rust/{ => main}/terraform/modules/efs/main.tf | 0 .../terraform/modules/efs/outputs.tf | 0 .../terraform/modules/efs/variables.tf | 0 .../terraform/modules/iam_kms/main.tf | 0 .../terraform/modules/iam_kms/outputs.tf | 0 .../terraform/modules/iam_kms/variables.tf | 0 rust/{ => main}/terraform/modules/s3/main.tf | 0 .../terraform/modules/s3/outputs.tf | 0 .../terraform/modules/s3/variables.tf | 0 .../terraform/modules/validator/main.tf | 0 .../terraform/modules/validator/outputs.tf | 0 .../terraform/modules/validator/variables.tf | 0 rust/{ => main}/terraform/outputs.tf | 0 rust/{ => main}/terraform/variables.tf | 0 rust/{ => main}/utils/abigen/Cargo.toml | 2 - rust/{ => main}/utils/abigen/src/lib.rs | 12 +- .../utils/backtrace-oneline/Cargo.toml | 4 +- .../utils/backtrace-oneline/src/lib.rs | 0 rust/{ => main}/utils/hex/Cargo.toml | 2 - rust/{ => main}/utils/hex/src/lib.rs | 0 rust/{ => main}/utils/run-locally/Cargo.toml | 10 +- rust/{ => main}/utils/run-locally/build.rs | 0 .../utils/run-locally/src/config.rs | 0 .../utils/run-locally/src/cosmos/cli.rs | 0 .../utils/run-locally/src/cosmos/crypto.rs | 0 .../utils/run-locally/src/cosmos/deploy.rs | 0 .../utils/run-locally/src/cosmos/link.rs | 0 .../utils/run-locally/src/cosmos/mod.rs | 3 + .../utils/run-locally/src/cosmos/rpc.rs | 0 .../utils/run-locally/src/cosmos/source.rs | 0 .../utils/run-locally/src/cosmos/types.rs | 0 .../utils/run-locally/src/cosmos/utils.rs | 0 .../utils/run-locally/src/ethereum/mod.rs | 0 .../run-locally/src/ethereum/multicall.rs | 0 .../utils/run-locally/src/invariants.rs | 0 .../run-locally/src/invariants/common.rs | 0 .../src/invariants/post_startup_invariants.rs | 0 .../src/invariants/termination_invariants.rs | 1 + .../utils/run-locally/src/logging.rs | 0 rust/{ => main}/utils/run-locally/src/main.rs | 28 +- .../utils/run-locally/src/metrics.rs | 0 .../utils/run-locally/src/program.rs | 0 .../utils/run-locally/src/solana.rs | 35 +- .../{ => main}/utils/run-locally/src/utils.rs | 0 rust-toolchain => rust/rust-toolchain | 0 rust/sealevel/.cargo/config.toml | 2 + rust/sealevel/.vscode/extensions.json | 13 + rust/sealevel/.vscode/settings.json | 5 + rust/sealevel/Cargo.lock | 7093 +++++++++++++++++ rust/{ => sealevel}/Cargo.toml | 106 +- rust/sealevel/client/Cargo.toml | 34 +- rust/sealevel/client/src/warp_route.rs | 1 + .../libraries/account-utils/src/lib.rs | 1 + .../libraries/ecdsa-signature/Cargo.toml | 2 +- .../Cargo.toml | 10 +- .../hyperlane-sealevel-token/Cargo.toml | 13 +- .../Cargo.toml | 1 - .../message-recipient-interface/Cargo.toml | 3 +- .../libraries/multisig-ism/Cargo.toml | 3 +- .../serializable-account-meta/Cargo.toml | 1 - .../test-transaction-utils/Cargo.toml | 1 - rust/sealevel/libraries/test-utils/Cargo.toml | 15 +- rust/sealevel/programs/helloworld/Cargo.toml | 17 +- .../hyperlane-sealevel-igp-test/Cargo.toml | 3 +- .../hyperlane-sealevel-igp/Cargo.toml | 3 +- .../Cargo.toml | 17 +- .../Cargo.toml | 15 +- .../hyperlane-sealevel-token/Cargo.toml | 15 +- .../hyperlane-sealevel-token/src/lib.rs | 2 +- .../ism/multisig-ism-message-id/Cargo.toml | 11 +- .../sealevel/programs/ism/test-ism/Cargo.toml | 13 +- .../sealevel/programs/mailbox-test/Cargo.toml | 11 +- rust/sealevel/programs/mailbox/Cargo.toml | 5 +- .../programs/test-send-receiver/Cargo.toml | 12 +- .../programs/validator-announce/Cargo.toml | 9 +- rust/sealevel/rust-toolchain | 3 + typescript/infra/scripts/agent-utils.ts | 2 +- typescript/infra/src/agents/index.ts | 2 +- 424 files changed, 11699 insertions(+), 3242 deletions(-) delete mode 100644 rust/chains/hyperlane-fuel/abis/Mailbox.abi.json delete mode 100644 rust/chains/hyperlane-fuel/src/mailbox.rs delete mode 100644 rust/chains/hyperlane-fuel/src/provider.rs delete mode 100644 rust/chains/hyperlane-sealevel/Cargo.toml rename rust/{ => main}/.cargo/config.toml (100%) rename rust/{ => main}/.vscode/extensions.json (100%) rename rust/{ => main}/.vscode/settings.json (100%) rename rust/{ => main}/Cargo.lock (80%) create mode 100644 rust/main/Cargo.toml rename rust/{ => main}/agents/relayer/.cargo/config.toml (100%) rename rust/{ => main}/agents/relayer/Cargo.toml (88%) rename rust/{ => main}/agents/relayer/src/lib.rs (100%) rename rust/{ => main}/agents/relayer/src/main.rs (100%) rename rust/{ => main}/agents/relayer/src/memory_profiler.rs (100%) rename rust/{ => main}/agents/relayer/src/merkle_tree/builder.rs (100%) rename rust/{ => main}/agents/relayer/src/merkle_tree/mod.rs (100%) rename rust/{ => main}/agents/relayer/src/merkle_tree/processor.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/blacklist.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/gas_payment/mod.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/gas_payment/policies/minimum.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/gas_payment/policies/mod.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/gas_payment/policies/none.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/gas_payment/policies/on_chain_fee_quoting.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/metadata/aggregation.rs (99%) rename rust/{ => main}/agents/relayer/src/msg/metadata/base.rs (98%) rename rust/{ => main}/agents/relayer/src/msg/metadata/ccip_read.rs (97%) rename rust/{ => main}/agents/relayer/src/msg/metadata/mod.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/metadata/multisig/base.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/metadata/multisig/mod.rs (81%) rename rust/{ => main}/agents/relayer/src/msg/metadata/null_metadata.rs (85%) rename rust/{ => main}/agents/relayer/src/msg/metadata/routing.rs (91%) rename rust/{ => main}/agents/relayer/src/msg/mod.rs (95%) rename rust/{ => main}/agents/relayer/src/msg/op_queue.rs (100%) rename rust/{ => main}/agents/relayer/src/msg/op_submitter.rs (99%) rename rust/{ => main}/agents/relayer/src/msg/pending_message.rs (99%) rename rust/{ => main}/agents/relayer/src/msg/processor.rs (100%) rename rust/{ => main}/agents/relayer/src/processor.rs (100%) rename rust/{ => main}/agents/relayer/src/prover.rs (100%) rename rust/{ => main}/agents/relayer/src/relayer.rs (100%) rename rust/{ => main}/agents/relayer/src/server/list_messages.rs (100%) rename rust/{ => main}/agents/relayer/src/server/message_retry.rs (100%) rename rust/{ => main}/agents/relayer/src/server/mod.rs (100%) rename rust/{ => main}/agents/relayer/src/settings/matching_list.rs (100%) rename rust/{ => main}/agents/relayer/src/settings/mod.rs (100%) rename rust/{ => main}/agents/scraper/Cargo.toml (96%) rename rust/{ => main}/agents/scraper/README.md (100%) rename rust/{ => main}/agents/scraper/migration/Cargo.toml (85%) rename rust/{ => main}/agents/scraper/migration/README.md (100%) rename rust/{ => main}/agents/scraper/migration/bin/common.rs (100%) rename rust/{ => main}/agents/scraper/migration/bin/down.rs (100%) rename rust/{ => main}/agents/scraper/migration/bin/fresh.rs (100%) rename rust/{ => main}/agents/scraper/migration/bin/generate_entities.rs (100%) rename rust/{ => main}/agents/scraper/migration/bin/init_db.rs (100%) rename rust/{ => main}/agents/scraper/migration/bin/recreate_db.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/l20230309_types.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/lib.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/m20230309_000002_create_table_block.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/m20230309_000003_create_table_cursor.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/m20230309_000003_create_table_transaction.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/m20230309_000004_create_table_delivered_message.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/m20230309_000004_create_table_gas_payment.rs (100%) rename rust/{ => main}/agents/scraper/migration/src/m20230309_000005_create_table_message.rs (100%) rename rust/{ => main}/agents/scraper/src/agent.rs (100%) rename rust/{ => main}/agents/scraper/src/chain_scraper/mod.rs (99%) rename rust/{ => main}/agents/scraper/src/conversions.rs (100%) rename rust/{ => main}/agents/scraper/src/date_time.rs (100%) rename rust/{ => main}/agents/scraper/src/db/block.rs (100%) rename rust/{ => main}/agents/scraper/src/db/block_cursor.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/block.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/cursor.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/delivered_message.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/domain.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/gas_payment.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/message.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/mod.rs (100%) rename rust/{ => main}/agents/scraper/src/db/generated/prelude.rs (92%) rename rust/{ => main}/agents/scraper/src/db/generated/transaction.rs (100%) rename rust/{ => main}/agents/scraper/src/db/message.rs (99%) rename rust/{ => main}/agents/scraper/src/db/mod.rs (100%) rename rust/{ => main}/agents/scraper/src/db/payment.rs (100%) rename rust/{ => main}/agents/scraper/src/db/txn.rs (100%) rename rust/{ => main}/agents/scraper/src/main.rs (100%) rename rust/{ => main}/agents/scraper/src/settings.rs (100%) rename rust/{ => main}/agents/validator/Cargo.toml (90%) rename rust/{ => main}/agents/validator/src/main.rs (100%) rename rust/{ => main}/agents/validator/src/server/eigen_node.rs (99%) rename rust/{ => main}/agents/validator/src/server/mod.rs (100%) rename rust/{ => main}/agents/validator/src/settings.rs (100%) rename rust/{ => main}/agents/validator/src/submit.rs (100%) rename rust/{ => main}/agents/validator/src/validator.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/Cargo.toml (90%) rename rust/{ => main}/chains/hyperlane-cosmos/src/aggregation_ism.rs (97%) rename rust/{ => main}/chains/hyperlane-cosmos/src/error.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/interchain_gas.rs (99%) rename rust/{ => main}/chains/hyperlane-cosmos/src/interchain_security_module.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/lib.rs (92%) rename rust/{ => main}/chains/hyperlane-cosmos/src/libs/account.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/libs/address.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/libs/mod.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/mailbox.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/mailbox/contract.rs (93%) rename rust/{ => main}/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/merkle_tree_hook.rs (98%) rename rust/{ => main}/chains/hyperlane-cosmos/src/multisig_ism.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/general.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/ism_routes.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/mailbox.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/merkle_tree_hook.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/mod.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/multisig_ism.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/payloads/validator_announce.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/providers/grpc.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/providers/grpc/tests.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/providers/mod.rs (99%) rename rust/{ => main}/chains/hyperlane-cosmos/src/providers/rpc.rs (97%) rename rust/{ => main}/chains/hyperlane-cosmos/src/routing_ism.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/rpc_clients/fallback.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/rpc_clients/mod.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/signers.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/trait_builder.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/types.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/utils.rs (100%) rename rust/{ => main}/chains/hyperlane-cosmos/src/validator_announce.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/.gitignore (100%) rename rust/{ => main}/chains/hyperlane-ethereum/Cargo.toml (95%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/ArbitrumNodeInterface.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/IAggregationIsm.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/ICcipReadIsm.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/IInterchainGasPaymaster.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/IInterchainSecurityModule.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/IMailbox.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/IMultisigIsm.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/IRoutingIsm.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/IValidatorAnnounce.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/Mailbox.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/abis/MerkleTreeHook.abi.json (100%) rename rust/{ => main}/chains/hyperlane-ethereum/build.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/config.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs (98%) rename rust/{ => main}/chains/hyperlane-ethereum/src/contracts/mailbox.rs (98%) rename rust/{ => main}/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs (98%) rename rust/{ => main}/chains/hyperlane-ethereum/src/contracts/mod.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/contracts/multicall.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/contracts/utils.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/contracts/validator_announce.rs (98%) rename rust/{ => main}/chains/hyperlane-ethereum/src/error.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/ism/aggregation_ism.rs (97%) rename rust/{ => main}/chains/hyperlane-ethereum/src/ism/ccip_read_ism.rs (97%) rename rust/{ => main}/chains/hyperlane-ethereum/src/ism/interchain_security_module.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/ism/mod.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/ism/multisig_ism.rs (97%) rename rust/{ => main}/chains/hyperlane-ethereum/src/ism/routing_ism.rs (97%) rename rust/{ => main}/chains/hyperlane-ethereum/src/lib.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/rpc_clients/fallback.rs (99%) rename rust/{ => main}/chains/hyperlane-ethereum/src/rpc_clients/mod.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/rpc_clients/provider.rs (95%) rename rust/{ => main}/chains/hyperlane-ethereum/src/rpc_clients/retrying.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/signer/mod.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/signer/singleton.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/src/tx.rs (100%) rename rust/{ => main}/chains/hyperlane-ethereum/tests/signer_output.rs (100%) rename rust/{ => main}/chains/hyperlane-fuel/.gitignore (100%) rename rust/{ => main}/chains/hyperlane-fuel/Cargo.toml (91%) create mode 100644 rust/main/chains/hyperlane-fuel/abis/Mailbox.abi.json rename rust/{ => main}/chains/hyperlane-fuel/build.rs (100%) rename rust/{ => main}/chains/hyperlane-fuel/src/conversions.rs (93%) rename rust/{ => main}/chains/hyperlane-fuel/src/interchain_gas.rs (100%) rename rust/{ => main}/chains/hyperlane-fuel/src/lib.rs (100%) create mode 100644 rust/main/chains/hyperlane-fuel/src/mailbox.rs rename rust/{ => main}/chains/hyperlane-fuel/src/multisig_ism.rs (100%) create mode 100644 rust/main/chains/hyperlane-fuel/src/provider.rs rename rust/{ => main}/chains/hyperlane-fuel/src/routing_ism.rs (100%) rename rust/{ => main}/chains/hyperlane-fuel/src/trait_builder.rs (79%) rename rust/{ => main}/chains/hyperlane-fuel/src/validator_announce.rs (100%) create mode 100644 rust/main/chains/hyperlane-sealevel/Cargo.toml rename rust/{ => main}/chains/hyperlane-sealevel/src/client.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/error.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/interchain_gas.rs (98%) rename rust/{ => main}/chains/hyperlane-sealevel/src/interchain_security_module.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/lib.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/mailbox.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/merkle_tree_hook.rs (94%) rename rust/{ => main}/chains/hyperlane-sealevel/src/multisig_ism.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/provider.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/trait_builder.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/utils.rs (100%) rename rust/{ => main}/chains/hyperlane-sealevel/src/validator_announce.rs (98%) rename rust/{ => main}/config/mainnet_config.json (100%) rename rust/{ => main}/config/test-sealevel-keys/test_deployer-account.json (100%) rename rust/{ => main}/config/test-sealevel-keys/test_deployer-keypair.json (100%) rename rust/{ => main}/config/test_sealevel_config.json (100%) rename rust/{ => main}/config/testnet_config.json (100%) rename rust/{ => main}/ethers-prometheus/.gitignore (100%) rename rust/{ => main}/ethers-prometheus/Cargo.toml (95%) rename rust/{ => main}/ethers-prometheus/abis/Erc20.abi.json (100%) rename rust/{ => main}/ethers-prometheus/build.rs (100%) rename rust/{ => main}/ethers-prometheus/src/json_rpc_client.rs (100%) rename rust/{ => main}/ethers-prometheus/src/lib.rs (100%) rename rust/{ => main}/ethers-prometheus/src/middleware/error.rs (100%) rename rust/{ => main}/ethers-prometheus/src/middleware/mod.rs (99%) rename rust/{ => main}/helm/agent-common/Chart.yaml (100%) rename rust/{ => main}/helm/agent-common/templates/_helpers.tpl (100%) rename rust/{ => main}/helm/hyperlane-agent/.helmignore (100%) rename rust/{ => main}/helm/hyperlane-agent/Chart.lock (100%) rename rust/{ => main}/helm/hyperlane-agent/Chart.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/NOTES.txt (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/_helpers.tpl (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/configmap.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/external-secret.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/relayer-external-secret.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/relayer-statefulset.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/scraper-external-secret.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/scraper-statefulset.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/serviceaccount.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/validator-configmap.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/validator-external-secret.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/templates/validator-statefulset.yaml (100%) rename rust/{ => main}/helm/hyperlane-agent/values.yaml (100%) rename rust/{ => main}/hyperlane-base/Cargo.toml (95%) rename rust/{ => main}/hyperlane-base/build.rs (100%) rename rust/{ => main}/hyperlane-base/src/agent.rs (98%) rename rust/{ => main}/hyperlane-base/src/contract_sync/broadcast.rs (100%) rename rust/{ => main}/hyperlane-base/src/contract_sync/cursors/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/contract_sync/cursors/rate_limited.rs (100%) rename rust/{ => main}/hyperlane-base/src/contract_sync/cursors/sequence_aware/backward.rs (99%) rename rust/{ => main}/hyperlane-base/src/contract_sync/cursors/sequence_aware/forward.rs (99%) rename rust/{ => main}/hyperlane-base/src/contract_sync/cursors/sequence_aware/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/contract_sync/eta_calculator.rs (100%) rename rust/{ => main}/hyperlane-base/src/contract_sync/metrics.rs (100%) rename rust/{ => main}/hyperlane-base/src/contract_sync/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/db/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/db/rocks/hyperlane_db.rs (100%) rename rust/{ => main}/hyperlane-base/src/db/rocks/iterator.rs (100%) rename rust/{ => main}/hyperlane-base/src/db/rocks/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/db/rocks/storage_types.rs (100%) rename rust/{ => main}/hyperlane-base/src/db/rocks/test_utils.rs (100%) rename rust/{ => main}/hyperlane-base/src/db/rocks/typed_db.rs (100%) rename rust/{ => main}/hyperlane-base/src/lib.rs (100%) rename rust/{ => main}/hyperlane-base/src/metadata.rs (100%) rename rust/{ => main}/hyperlane-base/src/metrics/agent_metrics.rs (99%) rename rust/{ => main}/hyperlane-base/src/metrics/core.rs (100%) rename rust/{ => main}/hyperlane-base/src/metrics/json_rpc_client.rs (100%) rename rust/{ => main}/hyperlane-base/src/metrics/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/metrics/provider.rs (100%) rename rust/{ => main}/hyperlane-base/src/oneline_eyre/handler.rs (100%) rename rust/{ => main}/hyperlane-base/src/oneline_eyre/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/server/base_server.rs (100%) rename rust/{ => main}/hyperlane-base/src/server/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/aws_credentials.rs (94%) rename rust/{ => main}/hyperlane-base/src/settings/base.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/chains.rs (99%) rename rust/{ => main}/hyperlane-base/src/settings/checkpoint_syncer.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/loader/arguments.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/loader/case_adapter.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/loader/environment.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/loader/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/parser/connection_parser.rs (98%) rename rust/{ => main}/hyperlane-base/src/settings/parser/json_value_parser.rs (99%) rename rust/{ => main}/hyperlane-base/src/settings/parser/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/signers.rs (98%) rename rust/{ => main}/hyperlane-base/src/settings/trace/fmt.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/trace/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/settings/trace/span_metrics.rs (100%) rename rust/{ => main}/hyperlane-base/src/traits/checkpoint_syncer.rs (100%) rename rust/{ => main}/hyperlane-base/src/traits/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/types/gcs_storage.rs (100%) rename rust/{ => main}/hyperlane-base/src/types/local_storage.rs (100%) rename rust/{ => main}/hyperlane-base/src/types/mod.rs (100%) rename rust/{ => main}/hyperlane-base/src/types/multisig.rs (100%) rename rust/{ => main}/hyperlane-base/src/types/s3_storage.rs (100%) rename rust/{ => main}/hyperlane-base/src/types/utils.rs (100%) rename rust/{ => main}/hyperlane-base/tests/chain_config.rs (100%) rename rust/{ => main}/hyperlane-core/Cargo.toml (91%) rename rust/{ => main}/hyperlane-core/src/accumulator/incremental.rs (100%) rename rust/{ => main}/hyperlane-core/src/accumulator/merkle.rs (100%) rename rust/{ => main}/hyperlane-core/src/accumulator/mod.rs (100%) rename rust/{ => main}/hyperlane-core/src/accumulator/sparse.rs (100%) rename rust/{ => main}/hyperlane-core/src/accumulator/zero_hashes.rs (100%) rename rust/{ => main}/hyperlane-core/src/chain.rs (100%) rename rust/{ => main}/hyperlane-core/src/config/config_path.rs (100%) rename rust/{ => main}/hyperlane-core/src/config/mod.rs (100%) rename rust/{ => main}/hyperlane-core/src/config/str_or_int.rs (96%) rename rust/{ => main}/hyperlane-core/src/config/trait_ext.rs (100%) rename rust/{ => main}/hyperlane-core/src/error.rs (100%) rename rust/{ => main}/hyperlane-core/src/lib.rs (95%) rename rust/{ => main}/hyperlane-core/src/metrics/agent.rs (100%) rename rust/{ => main}/hyperlane-core/src/metrics/mod.rs (100%) rename rust/{ => main}/hyperlane-core/src/rpc_clients/error.rs (100%) rename rust/{ => main}/hyperlane-core/src/rpc_clients/fallback.rs (100%) rename rust/{ => main}/hyperlane-core/src/rpc_clients/mod.rs (100%) rename rust/{ => main}/hyperlane-core/src/rpc_clients/retry.rs (100%) rename rust/{ => main}/hyperlane-core/src/test_output.rs (100%) rename rust/{ => main}/hyperlane-core/src/test_utils.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/aggregation_ism.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/ccip_read_ism.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/cursor.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/db.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/deployed.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/encode.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/indexer.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/interchain_gas.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/interchain_security_module.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/mailbox.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/merkle_tree_hook.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/mod.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/multisig_ism.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/pending_operation.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/provider.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/routing_ism.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/signing.rs (100%) rename rust/{ => main}/hyperlane-core/src/traits/validator_announce.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/announcement.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/chain_data.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/checkpoint.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/identifiers.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/indexing.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/log_metadata.rs (96%) rename rust/{ => main}/hyperlane-core/src/types/merkle_tree.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/message.rs (99%) rename rust/{ => main}/hyperlane-core/src/types/mod.rs (100%) rename rust/{ => main}/hyperlane-core/src/types/primitive_types.rs (99%) rename rust/{ => main}/hyperlane-core/src/types/serialize.rs (99%) rename rust/{ => main}/hyperlane-core/src/types/transaction.rs (100%) rename rust/{ => main}/hyperlane-core/src/utils.rs (100%) rename rust/{ => main}/hyperlane-test/Cargo.toml (87%) rename rust/{ => main}/hyperlane-test/src/lib.rs (77%) rename rust/{ => main}/hyperlane-test/src/mocks/mailbox.rs (100%) rename rust/{ => main}/hyperlane-test/src/mocks/mod.rs (100%) rename rust/{ => main}/hyperlane-test/src/mocks/validator_announce.rs (100%) create mode 100644 rust/main/rust-toolchain rename rust/{ => main}/terraform/.gitignore (100%) rename rust/{ => main}/terraform/README.md (100%) rename rust/{ => main}/terraform/globals.tf (100%) rename rust/{ => main}/terraform/main.tf (100%) rename rust/{ => main}/terraform/modules/efs/main.tf (100%) rename rust/{ => main}/terraform/modules/efs/outputs.tf (100%) rename rust/{ => main}/terraform/modules/efs/variables.tf (100%) rename rust/{ => main}/terraform/modules/iam_kms/main.tf (100%) rename rust/{ => main}/terraform/modules/iam_kms/outputs.tf (100%) rename rust/{ => main}/terraform/modules/iam_kms/variables.tf (100%) rename rust/{ => main}/terraform/modules/s3/main.tf (100%) rename rust/{ => main}/terraform/modules/s3/outputs.tf (100%) rename rust/{ => main}/terraform/modules/s3/variables.tf (100%) rename rust/{ => main}/terraform/modules/validator/main.tf (100%) rename rust/{ => main}/terraform/modules/validator/outputs.tf (100%) rename rust/{ => main}/terraform/modules/validator/variables.tf (100%) rename rust/{ => main}/terraform/outputs.tf (100%) rename rust/{ => main}/terraform/variables.tf (100%) rename rust/{ => main}/utils/abigen/Cargo.toml (92%) rename rust/{ => main}/utils/abigen/src/lib.rs (94%) rename rust/{ => main}/utils/backtrace-oneline/Cargo.toml (71%) rename rust/{ => main}/utils/backtrace-oneline/src/lib.rs (100%) rename rust/{ => main}/utils/hex/Cargo.toml (78%) rename rust/{ => main}/utils/hex/src/lib.rs (100%) rename rust/{ => main}/utils/run-locally/Cargo.toml (87%) rename rust/{ => main}/utils/run-locally/build.rs (100%) rename rust/{ => main}/utils/run-locally/src/config.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/cli.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/crypto.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/deploy.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/link.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/mod.rs (99%) rename rust/{ => main}/utils/run-locally/src/cosmos/rpc.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/source.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/types.rs (100%) rename rust/{ => main}/utils/run-locally/src/cosmos/utils.rs (100%) rename rust/{ => main}/utils/run-locally/src/ethereum/mod.rs (100%) rename rust/{ => main}/utils/run-locally/src/ethereum/multicall.rs (100%) rename rust/{ => main}/utils/run-locally/src/invariants.rs (100%) rename rust/{ => main}/utils/run-locally/src/invariants/common.rs (100%) rename rust/{ => main}/utils/run-locally/src/invariants/post_startup_invariants.rs (100%) rename rust/{ => main}/utils/run-locally/src/invariants/termination_invariants.rs (99%) rename rust/{ => main}/utils/run-locally/src/logging.rs (100%) rename rust/{ => main}/utils/run-locally/src/main.rs (96%) rename rust/{ => main}/utils/run-locally/src/metrics.rs (100%) rename rust/{ => main}/utils/run-locally/src/program.rs (100%) rename rust/{ => main}/utils/run-locally/src/solana.rs (92%) rename rust/{ => main}/utils/run-locally/src/utils.rs (100%) rename rust-toolchain => rust/rust-toolchain (100%) create mode 100644 rust/sealevel/.cargo/config.toml create mode 100644 rust/sealevel/.vscode/extensions.json create mode 100644 rust/sealevel/.vscode/settings.json create mode 100644 rust/sealevel/Cargo.lock rename rust/{ => sealevel}/Cargo.toml (78%) create mode 100644 rust/sealevel/rust-toolchain diff --git a/.codespell/.codespellrc b/.codespell/.codespellrc index c21a79e68..1b6b585fd 100644 --- a/.codespell/.codespellrc +++ b/.codespell/.codespellrc @@ -1,5 +1,5 @@ [codespell] -skip = .git,node_modules,yarn.lock,Cargo.lock,./typescript/helloworld,./rust/config,./rust/sealevel/environments/mainnet3/chain-config.json +skip = .git,node_modules,yarn.lock,Cargo.lock,./typescript/helloworld,./rust/main/config,./rust/sealevel/environments/mainnet3/chain-config.json count = quiet-level = 3 ignore-words = ./.codespell/ignore.txt diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2c537a780..b33ecbc92 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -4,16 +4,16 @@ on: push: branches: [main] paths: - - 'rust/**' + - 'rust/main/**' + - 'rust/sealevel/**' - .github/workflows/rust.yml pull_request: branches: [main] paths: - - 'rust/**' + - 'rust/main/**' + - 'rust/sealevel/**' - .github/workflows/rust.yml - # Support for merge queues merge_group: - # Allows you to run this workflow manually from the Actions tab workflow_dispatch: concurrency: @@ -24,10 +24,6 @@ env: CARGO_TERM_COLOR: always RUST_BACKTRACE: full -defaults: - run: - working-directory: ./rust - jobs: test-rs: runs-on: buildjet-8vcpu-ubuntu-2204 @@ -42,21 +38,25 @@ jobs: - name: rust cache uses: Swatinem/rust-cache@v2 with: - prefix-key: "v3" - shared-key: "rust" - cache-provider: "buildjet" + prefix-key: 'v3' + shared-key: 'rust' + cache-provider: 'buildjet' save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} workspaces: | - ./rust + ./rust/main + ./rust/sealevel - name: Free disk space run: | - # Based on https://github.com/actions/runner-images/issues/2840#issuecomment-790492173 sudo rm -rf /usr/share/dotnet sudo rm -rf /opt/ghc sudo rm -rf "/usr/local/share/boost" sudo rm -rf "$AGENT_TOOLSDIRECTORY" - - name: Run tests + - name: Run tests for main workspace + run: cargo test + working-directory: ./rust/main + - name: Run tests for sealevel workspace run: cargo test + working-directory: ./rust/sealevel lint-rs: runs-on: buildjet-8vcpu-ubuntu-2204 @@ -73,26 +73,40 @@ jobs: - name: rust cache uses: Swatinem/rust-cache@v2 with: - prefix-key: "v3" - shared-key: "rust" - cache-provider: "buildjet" + prefix-key: 'v3' + shared-key: 'rust' + cache-provider: 'buildjet' save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} workspaces: | - ./rust + ./rust/main + ./rust/sealevel - name: Free disk space run: | - # Based on https://github.com/actions/runner-images/issues/2840#issuecomment-790492173 sudo rm -rf /usr/share/dotnet sudo rm -rf /opt/ghc sudo rm -rf "/usr/local/share/boost" sudo rm -rf "$AGENT_TOOLSDIRECTORY" - - name: Check + - name: Check for main workspace run: cargo check --release --all-features --all-targets - - name: Rustfmt + working-directory: ./rust/main + - name: Check for sealevel workspace + run: cargo check --release --all-features --all-targets + working-directory: ./rust/sealevel + - name: Rustfmt for main workspace run: cargo fmt --all -- --check - - name: Clippy + working-directory: ./rust/main + - name: Rustfmt for sealevel workspace + run: cargo fmt --all --check + working-directory: ./rust/sealevel + - name: Clippy for main workspace + run: cargo clippy -- -D warnings + working-directory: ./rust/main + - name: Clippy for sealevel workspace run: cargo clippy -- -D warnings - - name: Setup WASM + working-directory: ./rust/sealevel + - name: Setup WASM for main workspace run: rustup target add wasm32-unknown-unknown - - name: Check WASM + working-directory: ./rust/main + - name: Check WASM for hyperlane-core run: cargo check --release -p hyperlane-core --features=strum,test-utils --target wasm32-unknown-unknown + working-directory: ./rust/main diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 07b0ab51a..b927d734f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -172,12 +172,23 @@ jobs: - name: rust cache uses: Swatinem/rust-cache@v2 with: - prefix-key: "v1-${{ runner.os }}-rust-cache" + prefix-key: 'v2-rust-main' shared-key: ${{ matrix.e2e-type }} - cache-provider: "buildjet" + cache-provider: 'buildjet' save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} workspaces: | - ./rust + ./rust/main + + - name: rust cache + uses: Swatinem/rust-cache@v2 + if: matrix.e2e-type == 'non-cosmwasm' + with: + prefix-key: 'v2-rust-sealevel' + shared-key: ${{ matrix.e2e-type }} + cache-provider: 'buildjet' + save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} + workspaces: | + ./rust/sealevel - name: Free disk space run: | @@ -209,14 +220,14 @@ jobs: - name: agent tests (CosmWasm) run: cargo test --release --package run-locally --bin run-locally --features cosmos test-utils -- cosmos::test --nocapture if: matrix.e2e-type == 'cosmwasm' - working-directory: ./rust + working-directory: ./rust/main env: RUST_BACKTRACE: 'full' - name: agent tests (EVM and Sealevel) run: cargo run --release --bin run-locally --features test-utils if: matrix.e2e-type == 'non-cosmwasm' - working-directory: ./rust + working-directory: ./rust/main env: E2E_CI_MODE: 'true' E2E_CI_TIMEOUT_SEC: '600' diff --git a/.gitignore b/.gitignore index f9892417a..5acf861cd 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ yarn-error.log .idea **/*.ignore -.vscode +/.vscode +!/.vscode/* tsconfig.editor.json diff --git a/rust/Dockerfile b/rust/Dockerfile index 75be92001..ed8c17d5b 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -9,24 +9,26 @@ RUN apt-get update && \ apt-get install -y musl-tools clang && \ rustup target add x86_64-unknown-linux-musl -RUN mkdir rust +RUN mkdir -p rust/main +RUN mkdir -p rust/sealevel # Add workspace to workdir -COPY rust/agents rust/agents -COPY rust/chains rust/chains -COPY rust/hyperlane-base rust/hyperlane-base -COPY rust/hyperlane-core rust/hyperlane-core -COPY rust/hyperlane-test rust/hyperlane-test -COPY rust/ethers-prometheus rust/ethers-prometheus -COPY rust/utils rust/utils +COPY rust/main/agents rust/main/agents +COPY rust/main/chains rust/main/chains +COPY rust/main/hyperlane-base rust/main/hyperlane-base +COPY rust/main/hyperlane-core rust/main/hyperlane-core +COPY rust/main/hyperlane-test rust/main/hyperlane-test +COPY rust/main/ethers-prometheus rust/main/ethers-prometheus +COPY rust/main/utils rust/main/utils COPY rust/sealevel rust/sealevel -COPY rust/Cargo.toml rust/. -COPY rust/Cargo.lock rust/. +COPY rust/main/Cargo.toml rust/main/. +COPY rust/main/Cargo.toml rust/main/. +COPY rust/sealevel/Cargo.lock rust/sealevel/. +COPY rust/sealevel/Cargo.lock rust/sealevel/. -COPY .git .git -WORKDIR /usr/src/rust +WORKDIR /usr/src/rust/main # Build binaries RUN \ @@ -35,9 +37,9 @@ RUN \ --mount=id=cargo-home-git,type=cache,sharing=locked,target=/usr/local/cargo/git \ RUSTFLAGS="--cfg tokio_unstable" cargo build --release --bin validator --bin relayer --bin scraper && \ mkdir -p /release && \ - cp /usr/src/rust/target/release/validator /release && \ - cp /usr/src/rust/target/release/relayer /release && \ - cp /usr/src/rust/target/release/scraper /release + cp /usr/src/rust/main/target/release/validator /release && \ + cp /usr/src/rust/main/target/release/relayer /release && \ + cp /usr/src/rust/main/target/release/scraper /release ## 2: Copy the binaries to release image FROM ubuntu:22.04 @@ -49,7 +51,8 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY rust/config ./config +RUN mkdir -p /app/config +COPY rust/main/config /app/config COPY --from=builder /release/* . RUN chmod 777 /app && \ diff --git a/rust/chains/hyperlane-fuel/abis/Mailbox.abi.json b/rust/chains/hyperlane-fuel/abis/Mailbox.abi.json deleted file mode 100644 index c979c0aa4..000000000 --- a/rust/chains/hyperlane-fuel/abis/Mailbox.abi.json +++ /dev/null @@ -1,530 +0,0 @@ -{ - "types": [ - { - "typeId": 0, - "type": "()", - "components": [], - "typeParameters": null - }, - { - "typeId": 1, - "type": "(_, _)", - "components": [ - { - "name": "__tuple_element", - "type": 2, - "typeArguments": null - }, - { - "name": "__tuple_element", - "type": 20, - "typeArguments": null - } - ], - "typeParameters": null - }, - { - "typeId": 2, - "type": "b256", - "components": null, - "typeParameters": null - }, - { - "typeId": 3, - "type": "bool", - "components": null, - "typeParameters": null - }, - { - "typeId": 4, - "type": "enum Identity", - "components": [ - { - "name": "Address", - "type": 14, - "typeArguments": null - }, - { - "name": "ContractId", - "type": 15, - "typeArguments": null - } - ], - "typeParameters": null - }, - { - "typeId": 5, - "type": "enum Option", - "components": [ - { - "name": "None", - "type": 0, - "typeArguments": null - }, - { - "name": "Some", - "type": 6, - "typeArguments": null - } - ], - "typeParameters": [ - 6 - ] - }, - { - "typeId": 6, - "type": "generic T", - "components": null, - "typeParameters": null - }, - { - "typeId": 7, - "type": "raw untyped ptr", - "components": null, - "typeParameters": null - }, - { - "typeId": 8, - "type": "str[12]", - "components": null, - "typeParameters": null - }, - { - "typeId": 9, - "type": "str[16]", - "components": null, - "typeParameters": null - }, - { - "typeId": 10, - "type": "str[6]", - "components": null, - "typeParameters": null - }, - { - "typeId": 11, - "type": "str[7]", - "components": null, - "typeParameters": null - }, - { - "typeId": 12, - "type": "str[8]", - "components": null, - "typeParameters": null - }, - { - "typeId": 13, - "type": "str[9]", - "components": null, - "typeParameters": null - }, - { - "typeId": 14, - "type": "struct Address", - "components": [ - { - "name": "value", - "type": 2, - "typeArguments": null - } - ], - "typeParameters": null - }, - { - "typeId": 15, - "type": "struct ContractId", - "components": [ - { - "name": "value", - "type": 2, - "typeArguments": null - } - ], - "typeParameters": null - }, - { - "typeId": 16, - "type": "struct Message", - "components": [ - { - "name": "version", - "type": 22, - "typeArguments": null - }, - { - "name": "nonce", - "type": 20, - "typeArguments": null - }, - { - "name": "origin", - "type": 20, - "typeArguments": null - }, - { - "name": "sender", - "type": 2, - "typeArguments": null - }, - { - "name": "destination", - "type": 20, - "typeArguments": null - }, - { - "name": "recipient", - "type": 2, - "typeArguments": null - }, - { - "name": "body", - "type": 19, - "typeArguments": [ - { - "name": "", - "type": 22, - "typeArguments": null - } - ] - } - ], - "typeParameters": null - }, - { - "typeId": 17, - "type": "struct OwnershipTransferredEvent", - "components": [ - { - "name": "previous_owner", - "type": 5, - "typeArguments": [ - { - "name": "", - "type": 4, - "typeArguments": null - } - ] - }, - { - "name": "new_owner", - "type": 5, - "typeArguments": [ - { - "name": "", - "type": 4, - "typeArguments": null - } - ] - } - ], - "typeParameters": null - }, - { - "typeId": 18, - "type": "struct RawVec", - "components": [ - { - "name": "ptr", - "type": 7, - "typeArguments": null - }, - { - "name": "cap", - "type": 21, - "typeArguments": null - } - ], - "typeParameters": [ - 6 - ] - }, - { - "typeId": 19, - "type": "struct Vec", - "components": [ - { - "name": "buf", - "type": 18, - "typeArguments": [ - { - "name": "", - "type": 6, - "typeArguments": null - } - ] - }, - { - "name": "len", - "type": 21, - "typeArguments": null - } - ], - "typeParameters": [ - 6 - ] - }, - { - "typeId": 20, - "type": "u32", - "components": null, - "typeParameters": null - }, - { - "typeId": 21, - "type": "u64", - "components": null, - "typeParameters": null - }, - { - "typeId": 22, - "type": "u8", - "components": null, - "typeParameters": null - } - ], - "functions": [ - { - "inputs": [], - "name": "count", - "output": { - "name": "", - "type": 20, - "typeArguments": null - } - }, - { - "inputs": [ - { - "name": "message_id", - "type": 2, - "typeArguments": null - } - ], - "name": "delivered", - "output": { - "name": "", - "type": 3, - "typeArguments": null - } - }, - { - "inputs": [ - { - "name": "destination_domain", - "type": 20, - "typeArguments": null - }, - { - "name": "recipient", - "type": 2, - "typeArguments": null - }, - { - "name": "message_body", - "type": 19, - "typeArguments": [ - { - "name": "", - "type": 22, - "typeArguments": null - } - ] - } - ], - "name": "dispatch", - "output": { - "name": "", - "type": 2, - "typeArguments": null - } - }, - { - "inputs": [], - "name": "get_default_ism", - "output": { - "name": "", - "type": 15, - "typeArguments": null - } - }, - { - "inputs": [], - "name": "latest_checkpoint", - "output": { - "name": "", - "type": 1, - "typeArguments": null - } - }, - { - "inputs": [ - { - "name": "metadata", - "type": 19, - "typeArguments": [ - { - "name": "", - "type": 22, - "typeArguments": null - } - ] - }, - { - "name": "_message", - "type": 16, - "typeArguments": null - } - ], - "name": "process", - "output": { - "name": "", - "type": 0, - "typeArguments": null - } - }, - { - "inputs": [], - "name": "root", - "output": { - "name": "", - "type": 2, - "typeArguments": null - } - }, - { - "inputs": [ - { - "name": "module", - "type": 15, - "typeArguments": null - } - ], - "name": "set_default_ism", - "output": { - "name": "", - "type": 0, - "typeArguments": null - } - }, - { - "inputs": [], - "name": "owner", - "output": { - "name": "", - "type": 5, - "typeArguments": [ - { - "name": "", - "type": 4, - "typeArguments": null - } - ] - } - }, - { - "inputs": [ - { - "name": "new_owner", - "type": 5, - "typeArguments": [ - { - "name": "", - "type": 4, - "typeArguments": null - } - ] - } - ], - "name": "transfer_ownership", - "output": { - "name": "", - "type": 0, - "typeArguments": null - } - } - ], - "loggedTypes": [ - { - "logId": 0, - "loggedType": { - "name": "", - "type": 8, - "typeArguments": null - } - }, - { - "logId": 1, - "loggedType": { - "name": "", - "type": 9, - "typeArguments": null - } - }, - { - "logId": 2, - "loggedType": { - "name": "", - "type": 12, - "typeArguments": null - } - }, - { - "logId": 3, - "loggedType": { - "name": "", - "type": 8, - "typeArguments": null - } - }, - { - "logId": 4, - "loggedType": { - "name": "", - "type": 13, - "typeArguments": null - } - }, - { - "logId": 5, - "loggedType": { - "name": "", - "type": 11, - "typeArguments": null - } - }, - { - "logId": 6, - "loggedType": { - "name": "", - "type": 2, - "typeArguments": null - } - }, - { - "logId": 7, - "loggedType": { - "name": "", - "type": 10, - "typeArguments": null - } - }, - { - "logId": 8, - "loggedType": { - "name": "", - "type": 10, - "typeArguments": null - } - }, - { - "logId": 9, - "loggedType": { - "name": "", - "type": 17, - "typeArguments": [] - } - } - ], - "messagesTypes": [] -} \ No newline at end of file diff --git a/rust/chains/hyperlane-fuel/src/mailbox.rs b/rust/chains/hyperlane-fuel/src/mailbox.rs deleted file mode 100644 index 5e8f0cf05..000000000 --- a/rust/chains/hyperlane-fuel/src/mailbox.rs +++ /dev/null @@ -1,164 +0,0 @@ -use std::collections::HashMap; -use std::fmt::{Debug, Formatter}; -use std::num::NonZeroU64; -use std::ops::RangeInclusive; - -use async_trait::async_trait; -use fuels::prelude::{Bech32ContractId, WalletUnlocked}; -use hyperlane_core::Indexed; -use tracing::instrument; - -use hyperlane_core::{ - utils::bytes_to_hex, ChainCommunicationError, ChainResult, ContractLocator, HyperlaneAbi, - HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, - Indexer, LogMeta, Mailbox, TxCostEstimate, TxOutcome, H256, U256, -}; - -use crate::{ - contracts::mailbox::Mailbox as FuelMailboxInner, conversions::*, make_provider, ConnectionConf, -}; - -/// A reference to a Mailbox contract on some Fuel chain -pub struct FuelMailbox { - contract: FuelMailboxInner, - domain: HyperlaneDomain, -} - -impl FuelMailbox { - /// Create a new fuel mailbox - pub fn new( - conf: &ConnectionConf, - locator: ContractLocator, - mut wallet: WalletUnlocked, - ) -> ChainResult { - let provider = make_provider(conf)?; - wallet.set_provider(provider); - let address = Bech32ContractId::from_h256(&locator.address); - - Ok(FuelMailbox { - contract: FuelMailboxInner::new(address, wallet), - domain: locator.domain.clone(), - }) - } -} - -impl HyperlaneContract for FuelMailbox { - fn address(&self) -> H256 { - self.contract.contract_id().into_h256() - } -} - -impl HyperlaneChain for FuelMailbox { - fn domain(&self) -> &HyperlaneDomain { - &self.domain - } - - fn provider(&self) -> Box { - todo!() - } -} - -impl Debug for FuelMailbox { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self as &dyn HyperlaneContract) - } -} - -#[async_trait] -impl Mailbox for FuelMailbox { - #[instrument(level = "debug", err, ret, skip(self))] - async fn count(&self, lag: Option) -> ChainResult { - assert!( - lag.is_none(), - "Fuel does not support querying point-in-time" - ); - self.contract - .methods() - .count() - .simulate() - .await - .map(|r| r.value) - .map_err(ChainCommunicationError::from_other) - } - - #[instrument(level = "debug", err, ret, skip(self))] - async fn delivered(&self, id: H256) -> ChainResult { - todo!() - } - - #[instrument(err, ret, skip(self))] - async fn default_ism(&self) -> ChainResult { - todo!() - } - - #[instrument(err, ret, skip(self))] - async fn recipient_ism(&self, recipient: H256) -> ChainResult { - todo!() - } - - #[instrument(err, ret, skip(self))] - async fn process( - &self, - message: &HyperlaneMessage, - metadata: &[u8], - tx_gas_limit: Option, - ) -> ChainResult { - todo!() - } - - #[instrument(err, ret, skip(self), fields(msg=%message, metadata=%bytes_to_hex(metadata)))] - async fn process_estimate_costs( - &self, - message: &HyperlaneMessage, - metadata: &[u8], - ) -> ChainResult { - todo!() - } - - fn process_calldata(&self, message: &HyperlaneMessage, metadata: &[u8]) -> Vec { - todo!() - } -} - -/// Struct that retrieves event data for a Fuel Mailbox contract -#[derive(Debug)] -pub struct FuelMailboxIndexer {} - -#[async_trait] -impl Indexer for FuelMailboxIndexer { - async fn fetch_logs_in_range( - &self, - range: RangeInclusive, - ) -> ChainResult, LogMeta)>> { - todo!() - } - - async fn get_finalized_block_number(&self) -> ChainResult { - todo!() - } -} - -#[async_trait] -impl Indexer for FuelMailboxIndexer { - async fn fetch_logs_in_range( - &self, - range: RangeInclusive, - ) -> ChainResult, LogMeta)>> { - todo!() - } - - async fn get_finalized_block_number(&self) -> ChainResult { - todo!() - } -} - -struct FuelMailboxAbi; - -impl HyperlaneAbi for FuelMailboxAbi { - const SELECTOR_SIZE_BYTES: usize = 8; - - fn fn_map() -> HashMap, &'static str> { - // Can't support this without Fuels exporting it in the generated code - todo!() - } -} diff --git a/rust/chains/hyperlane-fuel/src/provider.rs b/rust/chains/hyperlane-fuel/src/provider.rs deleted file mode 100644 index 992608fac..000000000 --- a/rust/chains/hyperlane-fuel/src/provider.rs +++ /dev/null @@ -1,43 +0,0 @@ -use async_trait::async_trait; - -use hyperlane_core::{ - BlockInfo, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, TxnInfo, - H256, U256, -}; - -/// A wrapper around a fuel provider to get generic blockchain information. -#[derive(Debug)] -pub struct FuelProvider {} - -impl HyperlaneChain for FuelProvider { - fn domain(&self) -> &HyperlaneDomain { - todo!() - } - - fn provider(&self) -> Box { - todo!() - } -} - -#[async_trait] -impl HyperlaneProvider for FuelProvider { - async fn get_block_by_hash(&self, hash: &H256) -> ChainResult { - todo!() - } - - async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult { - todo!() - } - - async fn is_contract(&self, address: &H256) -> ChainResult { - todo!() - } - - async fn get_balance(&self, address: String) -> ChainResult { - todo!() - } - - async fn get_chain_metrics(&self) -> ChainResult> { - Ok(None) - } -} diff --git a/rust/chains/hyperlane-sealevel/Cargo.toml b/rust/chains/hyperlane-sealevel/Cargo.toml deleted file mode 100644 index 2a3eed634..000000000 --- a/rust/chains/hyperlane-sealevel/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -cargo-features = ["workspace-inheritance"] - -[package] -name = "hyperlane-sealevel" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow.workspace = true -async-trait.workspace = true -base64.workspace = true -borsh.workspace = true -derive-new.workspace = true -jsonrpc-core.workspace = true -num-traits.workspace = true -serde.workspace = true -solana-account-decoder.workspace = true -solana-client.workspace = true -solana-sdk.workspace = true -solana-transaction-status.workspace = true -thiserror.workspace = true -tracing-futures.workspace = true -tracing.workspace = true -url.workspace = true - -account-utils = { path = "../../sealevel/libraries/account-utils" } -hyperlane-core = { path = "../../hyperlane-core", features = ["solana", "async"] } -hyperlane-sealevel-interchain-security-module-interface = { path = "../../sealevel/libraries/interchain-security-module-interface" } -hyperlane-sealevel-mailbox = { path = "../../sealevel/programs/mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../../sealevel/programs/hyperlane-sealevel-igp", features = ["no-entrypoint"] } -hyperlane-sealevel-message-recipient-interface = { path = "../../sealevel/libraries/message-recipient-interface" } -hyperlane-sealevel-multisig-ism-message-id = { path = "../../sealevel/programs/ism/multisig-ism-message-id", features = ["no-entrypoint"] } -hyperlane-sealevel-validator-announce = { path = "../../sealevel/programs/validator-announce", features = ["no-entrypoint"] } -multisig-ism = { path = "../../sealevel/libraries/multisig-ism" } -serializable-account-meta = { path = "../../sealevel/libraries/serializable-account-meta" } diff --git a/rust/.cargo/config.toml b/rust/main/.cargo/config.toml similarity index 100% rename from rust/.cargo/config.toml rename to rust/main/.cargo/config.toml diff --git a/rust/.vscode/extensions.json b/rust/main/.vscode/extensions.json similarity index 100% rename from rust/.vscode/extensions.json rename to rust/main/.vscode/extensions.json diff --git a/rust/.vscode/settings.json b/rust/main/.vscode/settings.json similarity index 100% rename from rust/.vscode/settings.json rename to rust/main/.vscode/settings.json diff --git a/rust/Cargo.lock b/rust/main/Cargo.lock similarity index 80% rename from rust/Cargo.lock rename to rust/main/Cargo.lock index b5d7c442f..d6f99c489 100644 --- a/rust/Cargo.lock +++ b/rust/main/Cargo.lock @@ -20,7 +20,7 @@ dependencies = [ "ethers", "fuels", "fuels-code-gen", - "which", + "which 4.4.2", ] [[package]] @@ -54,6 +54,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aead" version = "0.5.2" @@ -66,24 +72,12 @@ dependencies = [ [[package]] name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher 0.3.0", - "cpufeatures", - "opaque-debug 0.3.0", -] - -[[package]] -name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", - "cipher 0.4.4", + "cipher", "cpufeatures", ] @@ -94,9 +88,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" dependencies = [ "aead", - "aes 0.8.3", - "cipher 0.4.4", - "ctr 0.9.2", + "aes", + "cipher", + "ctr", "polyval", "subtle", "zeroize", @@ -104,20 +98,20 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "once_cell", @@ -127,9 +121,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -157,9 +151,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -186,70 +180,143 @@ dependencies = [ ] [[package]] -name = "anstream" -version = "0.6.7" +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", ] [[package]] -name = "anstyle" -version = "1.0.4" +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rayon", + "rustc_version", + "zeroize", +] [[package]] -name = "anstyle-parse" -version = "0.2.3" +name = "ark-ff-asm" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "utf8parse", + "quote 1.0.37", + "syn 1.0.109", ] [[package]] -name = "anstyle-query" -version = "1.0.2" +name = "ark-ff-macros" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ - "windows-sys 0.52.0", + "num-bigint 0.4.6", + "num-traits", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", ] [[package]] -name = "anstyle-wincon" -version = "3.0.2" +name = "ark-poly" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" dependencies = [ - "anstyle", - "windows-sys 0.52.0", + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", ] [[package]] -name = "anyhow" -version = "1.0.79" +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", + "rayon", +] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii" @@ -279,10 +346,10 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -291,8 +358,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -304,9 +371,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.4.5" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "brotli", "flate2", @@ -352,20 +419,20 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -415,28 +482,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ - "proc-macro-error", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 1.0.109", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -449,7 +515,7 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http", + "http 0.2.11", "http-body", "hyper", "itoa", @@ -479,7 +545,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", + "http 0.2.11", "http-body", "mime", "rustversion", @@ -489,17 +555,18 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", + "serde", ] [[package]] @@ -518,8 +585,8 @@ checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" dependencies = [ "heck 0.3.3", "proc-macro-error", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -569,6 +636,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -587,26 +660,32 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "bigdecimal" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" dependencies = [ - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-integer", "num-traits", ] [[package]] name = "bigdecimal" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06619be423ea5bb86c95f087d5707942791a08a85530df0db2209a3ecfb8bc9" +checksum = "51d712318a27c7150326677b321a5fa91b55f6d9034ffd67f20319e147d40cee" dependencies = [ "autocfg", "libm", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-integer", "num-traits", ] @@ -633,12 +712,12 @@ dependencies = [ "lazycell", "peeking_take_while", "prettyplease", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "regex", "rustc-hash", "shlex", - "syn 2.0.48", + "syn 2.0.77", ] [[package]] @@ -649,9 +728,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "bitmaps" @@ -755,15 +837,15 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bnum" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9008b6bb9fc80b5277f2fe481c09e828743d9151203e804583eb4c9e15b31d" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" [[package]] -name = "borrown" -version = "0.1.0" +name = "bnum" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b57b368e638ed60664350ea4f2f3647a0192173478df2736cc255a025a796" +checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" [[package]] name = "borsh" @@ -777,11 +859,11 @@ dependencies = [ [[package]] name = "borsh" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ - "borsh-derive 1.3.1", + "borsh-derive 1.5.1", "cfg_aliases", ] @@ -794,21 +876,21 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.76", + "proc-macro2 1.0.86", "syn 1.0.109", ] [[package]] name = "borsh-derive" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", "syn_derive", ] @@ -818,8 +900,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -829,16 +911,16 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "brotli" -version = "3.4.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -847,9 +929,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.5.1" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -863,18 +945,19 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ + "sha2 0.10.8", "tinyvec", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bv" @@ -900,9 +983,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -911,33 +994,33 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -948,23 +1031,13 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" dependencies = [ "serde", ] -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - [[package]] name = "bzip2-sys" version = "0.1.11+1.0.8" @@ -978,9 +1051,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] @@ -998,8 +1071,7 @@ dependencies = [ [[package]] name = "cargo-platform" version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +source = "git+https://github.com/rust-lang/cargo?tag=0.76.0#1d8b05cdd1287c64467306cf3ca2c8ac60c11eb0" dependencies = [ "serde", ] @@ -1020,9 +1092,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" dependencies = [ "jobserver", "libc", @@ -1045,15 +1117,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1061,25 +1133,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", -] - -[[package]] -name = "chrono-humanize" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799627e6b4d27827a814e837b9d8a504832086081806d45b1afa34dc982b023b" -dependencies = [ - "chrono", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array 0.14.7", + "windows-targets 0.52.6", ] [[package]] @@ -1100,7 +1154,7 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.4", + "libloading 0.8.5", ] [[package]] @@ -1126,35 +1180,13 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags 1.3.2", - "clap_derive 3.2.25", - "clap_lex 0.2.4", + "clap_derive", + "clap_lex", "indexmap 1.9.3", "once_cell", "strsim 0.10.0", "termcolor", - "textwrap 0.16.0", -] - -[[package]] -name = "clap" -version = "4.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80932e03c33999b9235edb8655bc9df3204adc9887c2f95b50cb1deb9fd54253" -dependencies = [ - "clap_builder", - "clap_derive 4.4.7", -] - -[[package]] -name = "clap_builder" -version = "4.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c0db58c659eef1c73e444d298c27322a1b52f6927d2ad470c0c0f96fa7b8fa" -dependencies = [ - "anstream", - "anstyle", - "clap_lex 0.6.0", - "strsim 0.10.0", + "textwrap 0.16.1", ] [[package]] @@ -1165,23 +1197,11 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] -[[package]] -name = "clap_derive" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" -dependencies = [ - "heck 0.4.1", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", -] - [[package]] name = "clap_lex" version = "0.2.4" @@ -1191,12 +1211,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" - [[package]] name = "cloudabi" version = "0.0.3" @@ -1220,9 +1234,9 @@ checksum = "634c509653de24b439672164bbf56f5f582a2ab0e313d3b0f6af0b7345cf2560" dependencies = [ "bincode", "bs58 0.4.0", - "coins-core", + "coins-core 0.7.0", "digest 0.10.7", - "getrandom 0.2.12", + "getrandom 0.2.15", "hmac 0.12.1", "k256 0.11.6", "lazy_static", @@ -1231,6 +1245,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "coins-bip32" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" +dependencies = [ + "bs58 0.5.1", + "coins-core 0.8.7", + "digest 0.10.7", + "hmac 0.12.1", + "k256 0.13.3", + "serde", + "sha2 0.10.8", + "thiserror", +] + [[package]] name = "coins-bip39" version = "0.7.0" @@ -1238,8 +1268,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a11892bcac83b4c6e95ab84b5b06c76d9d70ad73548dd07418269c5c7977171" dependencies = [ "bitvec 0.17.4", - "coins-bip32", - "getrandom 0.2.12", + "coins-bip32 0.7.0", + "getrandom 0.2.15", "hex 0.4.3", "hmac 0.12.1", "pbkdf2 0.11.0", @@ -1248,6 +1278,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "coins-bip39" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" +dependencies = [ + "bitvec 1.0.1", + "coins-bip32 0.8.7", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.12.2", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", +] + [[package]] name = "coins-core" version = "0.7.0" @@ -1269,11 +1315,31 @@ dependencies = [ "thiserror", ] +[[package]] +name = "coins-core" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" +dependencies = [ + "base64 0.21.7", + "bech32 0.9.1", + "bs58 0.5.1", + "digest 0.10.7", + "generic-array 0.14.7", + "hex 0.4.3", + "ripemd", + "serde", + "serde_derive", + "sha2 0.10.8", + "sha3 0.10.8", + "thiserror", +] + [[package]] name = "color-eyre" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" dependencies = [ "backtrace", "color-spantrace", @@ -1296,12 +1362,6 @@ dependencies = [ "tracing-error", ] -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "combine" version = "3.8.1" @@ -1354,8 +1414,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" dependencies = [ "futures-core", - "prost 0.12.4", - "prost-types 0.12.4", + "prost 0.12.6", + "prost-types 0.12.6", "tonic 0.10.2", "tracing-core", ] @@ -1372,7 +1432,7 @@ dependencies = [ "futures-task", "hdrhistogram", "humantime", - "prost-types 0.12.4", + "prost-types 0.12.6", "serde", "serde_json", "thread_local", @@ -1439,9 +1499,9 @@ dependencies = [ [[package]] name = "cookie" -version = "0.16.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" dependencies = [ "percent-encoding", "time", @@ -1450,12 +1510,12 @@ dependencies = [ [[package]] name = "cookie_store" -version = "0.16.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d606d0fba62e13cf04db20536c05cb7f13673c161cb47a47a82b9b9e7d3f1daa" +checksum = "387461abbc748185c3a6e1673d826918b450b87ff22639429c694619a83b6cf6" dependencies = [ "cookie", - "idna 0.2.3", + "idna 0.3.0", "log", "publicsuffix", "serde", @@ -1477,9 +1537,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cosmos-sdk-proto" @@ -1502,7 +1562,7 @@ dependencies = [ "cosmos-sdk-proto", "ecdsa 0.16.9", "eyre", - "getrandom 0.2.12", + "getrandom 0.2.15", "k256 0.13.3", "rand_core 0.6.4", "serde", @@ -1514,34 +1574,73 @@ dependencies = [ "tokio", ] +[[package]] +name = "cosmwasm-core" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d905990ef3afb5753bb709dc7de88e9e370aa32bcc2f31731d4b533b63e82490" + [[package]] name = "cosmwasm-crypto" -version = "1.5.2" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f862b355f7e47711e0acfe6af92cb3fd8fd5936b66a9eaa338b51edabd1e77d" +dependencies = [ + "digest 0.10.7", + "ed25519-zebra 3.1.0", + "k256 0.13.3", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-crypto" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6aa9f904de106fa16443ad14ec2abe75e94ba003bb61c681c0e43d4c58d2a" +checksum = "5b2a7bd9c1dd9a377a4dc0f4ad97d24b03c33798cd5a6d7ceb8869b41c5d2f2d" dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "cosmwasm-core", "digest 0.10.7", "ecdsa 0.16.9", - "ed25519-zebra", + "ed25519-zebra 4.0.3", "k256 0.13.3", + "num-traits", + "p256", "rand_core 0.6.4", + "rayon", + "sha2 0.10.8", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.5.2" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40abec852f3d4abec6d44ead9a58b78325021a1ead1e7229c3471414e57b2e49" +checksum = "cd85de6467cd1073688c86b39833679ae6db18cf4771471edd9809f15f1679f1" dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cosmwasm-derive" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029910b409398fdf81955d7301b906caf81f2c42b013ea074fbd89720229c424" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "cosmwasm-schema" -version = "1.5.2" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b166215fbfe93dc5575bae062aa57ae7bb41121cffe53bac33b033257949d2a9" +checksum = "5b4cd28147a66eba73720b47636a58097a979ad8c8bfdb4ed437ebcbfe362576" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -1552,44 +1651,67 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.5.2" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf12f8e20bb29d1db66b7ca590bc2f670b548d21e9be92499bc0f9022a994a8" +checksum = "9acd45c63d41bc9b16bc6dc7f6bd604a8c2ad29ce96c8f3c96d7fc8ef384392e" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "cosmwasm-std" -version = "1.5.2" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad011ae7447188e26e4a7dbca2fcd0fc186aa21ae5c86df0503ea44c78f9e469" +checksum = "2685c2182624b2e9e17f7596192de49a3f86b7a0c9a5f6b25c1df5e24592e836" dependencies = [ "base64 0.21.7", "bech32 0.9.1", - "bnum", - "cosmwasm-crypto", - "cosmwasm-derive", + "bnum 0.10.0", + "cosmwasm-crypto 1.5.7", + "cosmwasm-derive 1.5.7", "derivative", "forward_ref", "hex 0.4.3", "schemars", "serde", - "serde-json-wasm", + "serde-json-wasm 0.5.2", "sha2 0.10.8", "static_assertions 1.1.0", "thiserror", ] [[package]] -name = "cosmwasm-storage" -version = "1.5.2" +name = "cosmwasm-std" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51dec99a2e478715c0a4277f0dbeadbb8466500eb7dec873d0924edd086e77f1" +dependencies = [ + "base64 0.22.1", + "bech32 0.11.0", + "bnum 0.11.0", + "cosmwasm-core", + "cosmwasm-crypto 2.1.3", + "cosmwasm-derive 2.1.3", + "derive_more 1.0.0", + "hex 0.4.3", + "rand_core 0.6.4", + "schemars", + "serde", + "serde-json-wasm 1.0.1", + "sha2 0.10.8", + "static_assertions 1.1.0", + "thiserror", +] + +[[package]] +name = "cosmwasm-storage" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.5.7", "serde", ] @@ -1604,33 +1726,33 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "critical-section" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -1665,9 +1787,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1675,18 +1797,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-bigint" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" -dependencies = [ - "generic-array 0.14.7", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-bigint" version = "0.4.9" @@ -1734,9 +1844,9 @@ dependencies = [ [[package]] name = "crypto-mac" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ "generic-array 0.14.7", "subtle", @@ -1751,32 +1861,23 @@ dependencies = [ "sct 0.6.1", ] -[[package]] -name = "ctr" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481" -dependencies = [ - "cipher 0.3.0", -] - [[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cipher 0.4.4", + "cipher", ] [[package]] name = "ctrlc" -version = "3.4.2" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" dependencies = [ - "nix 0.27.1", - "windows-sys 0.52.0", + "nix 0.29.0", + "windows-sys 0.59.0", ] [[package]] @@ -1792,6 +1893,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -1811,7 +1939,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.5.7", "schemars", "serde", ] @@ -1823,7 +1951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" dependencies = [ "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-std 1.5.7", "cw2", "schemars", "semver", @@ -1838,7 +1966,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" dependencies = [ "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-std 1.5.7", "cw-storage-plus", "schemars", "semver", @@ -1853,7 +1981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "526e39bb20534e25a1cd0386727f0038f4da294e5e535729ba3ef54055246abd" dependencies = [ "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-std 1.5.7", "cw-utils", "schemars", "serde", @@ -1866,7 +1994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ad79e86ea3707229bf78df94e08732e8f713207b4a77b2699755596725e7d9" dependencies = [ "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-std 1.5.7", "cw-storage-plus", "cw2", "cw20", @@ -1900,8 +2028,8 @@ dependencies = [ "darling 0.13.4", "graphql-parser", "once_cell", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "strsim 0.10.0", "syn 1.0.109", ] @@ -1936,6 +2064,16 @@ dependencies = [ "darling_macro 0.14.4", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core 0.20.10", + "darling_macro 0.20.10", +] + [[package]] name = "darling_core" version = "0.13.4" @@ -1944,8 +2082,8 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "strsim 0.10.0", "syn 1.0.109", ] @@ -1958,12 +2096,26 @@ checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "strsim 0.10.0", "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.86", + "quote 1.0.37", + "strsim 0.11.1", + "syn 2.0.77", +] + [[package]] name = "darling_macro" version = "0.13.4" @@ -1971,7 +2123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.109", ] @@ -1982,26 +2134,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ "darling_core 0.14.4", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.109", ] [[package]] -name = "dashmap" -version = "4.0.2" +name = "darling_macro" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "cfg-if", - "num_cpus", - "rayon", + "darling_core 0.20.10", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" @@ -2024,9 +2176,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid 0.9.6", "zeroize", @@ -2041,7 +2193,7 @@ dependencies = [ "asn1-rs", "displaydoc", "nom", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-traits", "rusticata-macros", ] @@ -2068,8 +2220,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -2079,8 +2231,8 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -2100,8 +2252,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ "darling 0.14.4", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -2117,15 +2269,36 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case 0.4.0", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "rustc_version", - "syn 1.0.109", + "syn 2.0.77", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", + "unicode-xid 0.2.5", ] [[package]] @@ -2137,7 +2310,7 @@ dependencies = [ "backtrace", "lazy_static", "mintex", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rustc-hash", "serde", "serde_json", @@ -2192,15 +2365,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dir-diff" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ad16bf5f84253b50d6557681c58c3ab67c47c77d39fed9aeb56e947290bd10" -dependencies = [ - "walkdir", -] - [[package]] name = "dirs" version = "4.0.0" @@ -2244,13 +2408,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -2294,17 +2458,23 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "eager" @@ -2330,7 +2500,7 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.8", + "der 0.7.9", "digest 0.10.7", "elliptic-curve 0.13.8", "rfc6979 0.4.0", @@ -2342,7 +2512,7 @@ dependencies = [ name = "ecdsa-signature" version = "0.1.0" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "hyperlane-core", "solana-program", "thiserror", @@ -2385,7 +2555,7 @@ name = "ed25519-dalek" version = "1.0.1" source = "git+https://github.com/Eclipse-Laboratories-Inc/ed25519-dalek?branch=main#7529d65506147b6cb24ca6d8f4fc062cac33b395" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.2", "ed25519 1.5.3", "rand 0.7.3", "serde", @@ -2393,6 +2563,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek 4.1.3", + "ed25519 2.2.3", + "sha2 0.10.8", + "subtle", +] + [[package]] name = "ed25519-dalek-bip32" version = "0.2.0" @@ -2400,7 +2582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" dependencies = [ "derivation-path", - "ed25519-dalek", + "ed25519-dalek 1.0.1", "hmac 0.12.1", "sha2 0.10.8", ] @@ -2411,7 +2593,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.2", "hashbrown 0.12.3", "hex 0.4.3", "rand_core 0.6.4", @@ -2421,37 +2603,25 @@ dependencies = [ ] [[package]] -name = "educe" -version = "0.4.23" +name = "ed25519-zebra" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0042ff8246a363dbe77d2ceedb073339e85a804b9a47636c6e016a9a32c05f" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ - "enum-ordinalize", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 1.0.109", + "curve25519-dalek 4.1.3", + "ed25519 2.2.3", + "hashbrown 0.14.5", + "hex 0.4.3", + "rand_core 0.6.4", + "sha2 0.10.8", + "zeroize", ] [[package]] name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "elliptic-curve" -version = "0.11.12" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.3.2", - "der 0.5.1", - "generic-array 0.14.7", - "rand_core 0.6.4", - "subtle", - "zeroize", -] +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -2498,6 +2668,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encode_unicode" version = "0.3.6" @@ -2506,9 +2682,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -2519,7 +2695,16 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2953d1df47ac0eb70086ccabf0275aa8da8591a28bd358ee2b52bd9f9e3ff9e9" dependencies = [ - "enum-iterator-derive", + "enum-iterator-derive 0.8.1", +] + +[[package]] +name = "enum-iterator" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd242f399be1da0a5354aa462d57b4ab2b4ee0683cc552f7c007d2d12d36e94" +dependencies = [ + "enum-iterator-derive 1.4.0", ] [[package]] @@ -2528,34 +2713,32 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8958699f9359f0b04e691a13850d48b7de329138023876d07cbd024c2c820598" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] -name = "enum-ordinalize" -version = "3.1.15" +name = "enum-iterator-derive" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" +checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" dependencies = [ - "num-bigint 0.4.4", - "num-traits", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "enum_dispatch" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -2571,19 +2754,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "env_logger" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -2602,50 +2772,28 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", ] -[[package]] -name = "eth-keystore" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d47d900a7dea08593d398104f8288e37858b0ad714c8d08cd03fdb86563e6402" -dependencies = [ - "aes 0.7.5", - "ctr 0.7.0", - "digest 0.9.0", - "hex 0.4.3", - "hmac 0.11.0", - "pbkdf2 0.8.0", - "rand 0.8.5", - "scrypt 0.7.0", - "serde", - "serde_json", - "sha2 0.9.9", - "sha3 0.9.1", - "thiserror", - "uuid 0.8.2", -] - [[package]] name = "eth-keystore" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ - "aes 0.8.3", - "ctr 0.9.2", + "aes", + "ctr", "digest 0.10.7", "hex 0.4.3", "hmac 0.12.1", "pbkdf2 0.11.0", "rand 0.8.5", - "scrypt 0.10.0", + "scrypt", "serde", "serde_json", "sha2 0.10.8", @@ -2791,10 +2939,10 @@ dependencies = [ "dunce", "ethers-core", "eyre", - "getrandom 0.2.12", + "getrandom 0.2.15", "hex 0.4.3", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "regex", "reqwest", "serde", @@ -2813,8 +2961,8 @@ dependencies = [ "ethers-contract-abigen", "ethers-core", "hex 0.4.3", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "serde_json", "syn 1.0.109", ] @@ -2836,7 +2984,7 @@ dependencies = [ "k256 0.11.6", "once_cell", "open-fastrlp", - "proc-macro2 1.0.76", + "proc-macro2 1.0.86", "rand 0.8.5", "rlp 0.5.2", "rlp-derive", @@ -2846,7 +2994,7 @@ dependencies = [ "syn 1.0.109", "thiserror", "tiny-keccak 2.0.2", - "unicode-xid 0.2.4", + "unicode-xid 0.2.5", ] [[package]] @@ -2855,7 +3003,7 @@ version = "1.0.2" source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" dependencies = [ "ethers-core", - "getrandom 0.2.12", + "getrandom 0.2.15", "reqwest", "semver", "serde", @@ -2904,7 +3052,7 @@ dependencies = [ "hyperlane-core", "log", "maplit", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "primitive-types", "prometheus", "serde", @@ -2919,17 +3067,17 @@ version = "1.0.2" source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" dependencies = [ "async-trait", - "auto_impl 1.1.0", + "auto_impl 1.2.0", "base64 0.13.1", "ethers-core", "futures-channel", "futures-core", "futures-timer", "futures-util", - "getrandom 0.2.12", + "getrandom 0.2.15", "hashers", "hex 0.4.3", - "http", + "http 0.2.11", "once_cell", "parking_lot 0.11.2", "pin-project", @@ -2955,10 +3103,10 @@ version = "1.0.2" source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" dependencies = [ "async-trait", - "coins-bip32", - "coins-bip39", + "coins-bip32 0.7.0", + "coins-bip39 0.7.0", "elliptic-curve 0.12.3", - "eth-keystore 0.5.0", + "eth-keystore", "ethers-core", "hex 0.4.3", "rand 0.8.5", @@ -2970,6 +3118,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + [[package]] name = "event-listener" version = "2.5.3" @@ -2978,16 +3132,17 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "eventsource-client" -version = "0.10.2" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9146112ee3ce031aa5aebe3e049e10b1d353b9c7630cc6be488c2c62cc5d9c42" +checksum = "4c80c6714d1a380314fcb11a22eeff022e1e1c9642f0bb54e15dc9cb29f37b29" dependencies = [ "futures", "hyper", - "hyper-rustls 0.22.1", + "hyper-rustls 0.24.2", "hyper-timeout", "log", "pin-project", + "rand 0.8.5", "tokio", ] @@ -3009,9 +3164,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "feature-probe" @@ -3040,22 +3195,10 @@ dependencies = [ ] [[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", -] - -[[package]] -name = "finl_unicode" -version = "1.2.0" +name = "fiat-crypto" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "fixed-hash" @@ -3095,12 +3238,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -3172,38 +3315,45 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "fuel-abi-types" -version = "0.2.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d99a7aeb41cdabffa38418b00fd57b5571dc58ee5af606e845a088befecd36" +checksum = "e0e7e87f94417ff1a5d60e496906033c58bfe5367546621f131fe8cdabaa2671" dependencies = [ + "itertools 0.10.5", "lazy_static", + "proc-macro2 1.0.86", + "quote 1.0.37", "regex", "serde", + "serde_json", + "syn 2.0.77", "thiserror", ] [[package]] name = "fuel-asm" -version = "0.26.3" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0030cc1247de0507e547d8ea33484b82420fe61221b94b985d193ec7f63587ae" +checksum = "491f1777538b0e1d479609d0d75bca5242c7fd3394f2ddd4ea55b8c96bcc8387" dependencies = [ + "bitflags 2.6.0", "fuel-types", "serde", + "strum 0.24.1", ] [[package]] name = "fuel-core-chain-config" -version = "0.17.13" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff4779c1649be51e1244aca7322c625064d052f9f6f529feb26f538cc839bd6" +checksum = "05c13f888fb9b705b64bbcb56d022345cf85a86535d646bf53e20771eb4b986a" dependencies = [ "anyhow", "bech32 0.9.1", + "derivative", "fuel-core-storage", "fuel-core-types", - "hex 0.4.3", - "itertools 0.10.5", + "itertools 0.12.1", "postcard", "rand 0.8.5", "serde", @@ -3214,20 +3364,21 @@ dependencies = [ [[package]] name = "fuel-core-client" -version = "0.17.13" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39b386680fb36dfee949c2977c1c682cf459c6b7862d243fb4615193b769d2b9" +checksum = "2bd1910fce3eebe33b5acba656e092e5ede267acb4b1c3f17c122a0477270091" dependencies = [ "anyhow", "cynic", - "derive_more", + "derive_more 0.99.18", "eventsource-client", "fuel-core-types", "futures", "hex 0.4.3", - "hyper-rustls 0.22.1", - "itertools 0.10.5", + "hyper-rustls 0.24.2", + "itertools 0.12.1", "reqwest", + "schemafy_lib", "serde", "serde_json", "tai64", @@ -3235,27 +3386,85 @@ dependencies = [ "tracing", ] +[[package]] +name = "fuel-core-metrics" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e2f22f6c4ce2696c29c14083c465f276c8d8eca67f051cb7d09a72442ceb5e" +dependencies = [ + "parking_lot 0.12.3", + "pin-project-lite", + "prometheus-client", + "regex", + "tracing", +] + +[[package]] +name = "fuel-core-poa" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c646e9246bc333e365d130f5a854fb9c33f9237e178d87c75a7d136d1f3211f9" +dependencies = [ + "anyhow", + "async-trait", + "fuel-core-chain-config", + "fuel-core-services", + "fuel-core-storage", + "fuel-core-types", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "fuel-core-services" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8a175199e0e7b1373ac10d45eb26563c1e8299298c9589ab60efb1c7cae6ac" +dependencies = [ + "anyhow", + "async-trait", + "fuel-core-metrics", + "futures", + "parking_lot 0.12.3", + "tokio", + "tracing", +] + [[package]] name = "fuel-core-storage" -version = "0.17.13" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240b31746485e24215a1159b0887f2013545c78252377d55601b07f9f25367ae" +checksum = "6a3ee3b462cc9b7e62b3ae04d5e3b792e6742c479bd75d6bc0987443a92b5299" dependencies = [ "anyhow", + "derive_more 0.99.18", + "enum-iterator 1.5.0", "fuel-core-types", "fuel-vm", - "thiserror", + "impl-tools", + "itertools 0.12.1", + "num_enum 0.7.3", + "paste", + "postcard", + "primitive-types", + "serde", + "strum 0.25.0", + "strum_macros 0.25.3", ] [[package]] name = "fuel-core-types" -version = "0.17.13" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75b20301e07c8dfd793c8a5385d3b2ee0e80c36f7323957260174819d8a25fe" +checksum = "615783f63b40075d1bf64a42b4fd4edce076458c94b0fab2278a570b2b7a8e0e" dependencies = [ "anyhow", - "derive_more", + "bs58 0.5.1", + "derivative", + "derive_more 0.99.18", "fuel-vm", + "rand 0.8.5", "secrecy", "serde", "tai64", @@ -3265,16 +3474,18 @@ dependencies = [ [[package]] name = "fuel-crypto" -version = "0.26.3" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7356deff8ce5a9b6bc8d9e7cacc6c1d1f7abf5cdd4d729869afb401befa495" +checksum = "f74f03ba9b27f375a0482b1afe20d5b8cfd032fedba683a584cdbd6d10147439" dependencies = [ - "borrown", - "coins-bip32", - "coins-bip39", + "coins-bip32 0.8.7", + "coins-bip39 0.8.7", + "ecdsa 0.16.9", + "ed25519-dalek 2.1.1", "fuel-types", - "getrandom 0.2.12", + "k256 0.13.3", "lazy_static", + "p256", "rand 0.8.5", "secp256k1", "serde", @@ -3283,49 +3494,68 @@ dependencies = [ ] [[package]] -name = "fuel-merkle" -version = "0.26.3" +name = "fuel-derive" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13103bf12f62930dd26f75f90d6a95d952fdcd677a356f57d8ef8df7ae02b84" +checksum = "89ad30ad1a11e5a811ae67b6b0cb6785ce21bcd5ef0afd442fd963d5be95d09d" dependencies = [ - "digest 0.10.7", - "fuel-storage", - "hashbrown 0.13.2", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", + "synstructure 0.13.1", +] + +[[package]] +name = "fuel-merkle" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5433c41ffbf531eed1380148cd68e37f9dd7e25966a9c59518f6b09e346e80e2" +dependencies = [ + "derive_more 0.99.18", + "digest 0.10.7", + "fuel-storage", + "hashbrown 0.13.2", "hex 0.4.3", + "serde", "sha2 0.10.8", - "thiserror", ] [[package]] name = "fuel-storage" -version = "0.26.3" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998d49926c8ae3e545e348075075c2fe85caae4474e01d2da65a9a8edc3277e9" +checksum = "ce3fc3cd96fe312442cdf35966b96d66becd02582b505f856f74953f57adf020" [[package]] name = "fuel-tx" -version = "0.26.3" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e09bb28731979db1f5192c04f2a330a15b8c2f5ef2b47836b3282c7fd9d7703c" +checksum = "e00cc42ae3121b1881a6ae8306696d1bea73adca424216d9f676ee91d3927c74" dependencies = [ + "bitflags 2.6.0", "derivative", + "derive_more 0.99.18", "fuel-asm", "fuel-crypto", "fuel-merkle", "fuel-types", + "hashbrown 0.14.5", "itertools 0.10.5", - "num-integer", + "postcard", "rand 0.8.5", "serde", "serde_json", + "strum 0.24.1", + "strum_macros 0.24.3", ] [[package]] name = "fuel-types" -version = "0.26.3" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89fc99a9878b98135c4b05c71fe63b82f4cb3a00abac278935f8be7282f8e468" +checksum = "ae98e143dec4e6cb114a92435e314f1d4815e17e8fded24332fb285319d60167" dependencies = [ + "fuel-derive", "hex 0.4.3", "rand 0.8.5", "serde", @@ -3333,201 +3563,176 @@ dependencies = [ [[package]] name = "fuel-vm" -version = "0.26.3" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b36aac727729b94c620265da76112e1d36a1af0c067745491c376f084f5b7b38" +checksum = "641a2ee5a3398633fa243fba3343cbe2225ae335a09141f6b94041720cfc3520" dependencies = [ - "bitflags 1.3.2", + "anyhow", + "async-trait", + "backtrace", + "bitflags 2.6.0", "derivative", + "derive_more 0.99.18", + "ethnum", "fuel-asm", "fuel-crypto", "fuel-merkle", "fuel-storage", "fuel-tx", "fuel-types", + "hashbrown 0.14.5", "itertools 0.10.5", + "libm", + "paste", + "percent-encoding", + "primitive-types", "rand 0.8.5", "serde", + "serde_with", "sha3 0.10.8", + "static_assertions 1.1.0", + "strum 0.24.1", "tai64", - "thiserror", ] [[package]] name = "fuels" -version = "0.38.1" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eede2cde3dd4e8cba56ed5bf4412836d7be280e013e392b2756af99ffb9e714" +checksum = "601ed66a0485065471cd9c8bab2db7cfa58bc7ed5d2e68bd26fc573ac2575827" dependencies = [ "fuel-core-client", + "fuel-crypto", "fuel-tx", + "fuels-accounts", "fuels-core", "fuels-macros", "fuels-programs", - "fuels-signers", "fuels-test-helpers", - "fuels-types", -] - -[[package]] -name = "fuels-code-gen" -version = "0.38.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d03eee7fa041bb4da8cdecc84b81f1ab8e5810d67bcec0c090bdd58f07e955" -dependencies = [ - "Inflector", - "fuel-abi-types", - "itertools 0.10.5", - "lazy_static", - "proc-macro2 1.0.76", - "quote 1.0.35", - "regex", - "serde_json", - "syn 1.0.109", ] [[package]] -name = "fuels-core" -version = "0.38.1" +name = "fuels-accounts" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd7273ee45a548acbd95e67405809e4b1778f4973851c16633e75b902f0ea9e" +checksum = "fed97e653906fe0bc60b5d7a7421f3c5fe766f516b762def8f4ccac707ac4bc3" dependencies = [ + "async-trait", + "chrono", + "elliptic-curve 0.13.8", + "eth-keystore", + "fuel-core-client", + "fuel-core-types", + "fuel-crypto", "fuel-tx", "fuel-types", - "fuel-vm", - "fuels-types", - "hex 0.4.3", - "itertools 0.10.5", - "sha2 0.9.9", + "fuels-core", + "itertools 0.12.1", + "rand 0.8.5", + "semver", + "tai64", + "thiserror", + "tokio", + "zeroize", ] [[package]] -name = "fuels-macros" -version = "0.38.1" +name = "fuels-code-gen" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6107ffb7dda1051d1db5d1bc209a66d3c2911a8fc844cf3662ca4b705556b57a" +checksum = "1edef30656b740ca9c279a7bcfe9e366557c271a2751e36316f780f18dc99c85" dependencies = [ "Inflector", "fuel-abi-types", - "fuels-code-gen", - "itertools 0.10.5", - "lazy_static", - "proc-macro2 1.0.76", - "quote 1.0.35", - "rand 0.8.5", + "itertools 0.12.1", + "proc-macro2 1.0.86", + "quote 1.0.37", "regex", "serde_json", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] -name = "fuels-programs" -version = "0.38.1" +name = "fuels-core" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c1034d747824c089622ca9ec400dc44a7a7119d9caf001116d8befa441bd47" +checksum = "ff741c9f1ba2c701b50c76a98a5655d8bc0f275f7ae2dd0e724f8fc36eeb8a9f" dependencies = [ - "bytes", + "async-trait", + "bech32 0.9.1", + "chrono", "fuel-abi-types", + "fuel-asm", + "fuel-core-chain-config", + "fuel-core-client", + "fuel-core-types", + "fuel-crypto", "fuel-tx", "fuel-types", "fuel-vm", - "fuels-core", - "fuels-signers", - "fuels-types", - "futures", + "fuels-macros", "hex 0.4.3", - "itertools 0.10.5", - "proc-macro2 1.0.76", - "rand 0.8.5", - "regex", + "itertools 0.12.1", + "postcard", "serde", "serde_json", - "sha2 0.9.9", - "strum 0.21.0", - "strum_macros 0.21.1", "thiserror", - "tokio", + "uint 0.9.5", ] [[package]] -name = "fuels-signers" -version = "0.38.1" +name = "fuels-macros" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862c60e598272158d3877896b1a47ae6109733f4538711a4d898c571a88aacb7" +checksum = "bba1c2fd149a310879249144f2589336708ae860563a45b792907ae34ae6b959" +dependencies = [ + "fuels-code-gen", + "itertools 0.12.1", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "fuels-programs" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a45652fa07c48d5fba2ee50ddd279eead2c55b251b3d426d2189394b475330e9" dependencies = [ "async-trait", - "bytes", - "chrono", - "elliptic-curve 0.11.12", - "eth-keystore 0.3.0", - "fuel-core-client", - "fuel-crypto", + "fuel-abi-types", + "fuel-asm", "fuel-tx", "fuel-types", - "fuel-vm", + "fuels-accounts", "fuels-core", - "fuels-types", - "hex 0.4.3", - "itertools 0.10.5", + "itertools 0.12.1", "rand 0.8.5", - "serde", - "sha2 0.9.9", - "tai64", - "thiserror", + "serde_json", "tokio", ] [[package]] name = "fuels-test-helpers" -version = "0.38.1" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51cb48e1a813b61d811f0811d9758e0f4527097b6a17fccf613ecc3595d3e4d" +checksum = "967a140a51095d071c84970365c37f856f4f098b835cb609b934dff4b8296cce" dependencies = [ "fuel-core-chain-config", "fuel-core-client", - "fuel-core-types", + "fuel-core-poa", + "fuel-core-services", + "fuel-crypto", "fuel-tx", "fuel-types", - "fuel-vm", - "fuels-signers", - "fuels-types", + "fuels-accounts", + "fuels-core", "futures", - "hex 0.4.3", "portpicker", "rand 0.8.5", - "serde", - "serde_json", - "serde_with", "tempfile", "tokio", - "which", -] - -[[package]] -name = "fuels-types" -version = "0.38.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e2ee9c34502c6427661beb51ee954b2c7c50e51a9bb518f2a7d512682cddd31" -dependencies = [ - "bech32 0.9.1", - "chrono", - "fuel-abi-types", - "fuel-asm", - "fuel-core-chain-config", - "fuel-core-client", - "fuel-tx", - "fuel-types", - "fuels-macros", - "hex 0.4.3", - "itertools 0.10.5", - "lazy_static", - "proc-macro2 1.0.76", - "regex", - "serde", - "serde_json", - "strum 0.21.0", - "strum_macros 0.21.1", - "thiserror", + "which 6.0.3", ] [[package]] @@ -3611,9 +3816,9 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -3630,9 +3835,9 @@ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" @@ -3707,9 +3912,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -3730,17 +3935,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "goblin" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" -dependencies = [ - "log", - "plain", - "scroll", -] - [[package]] name = "graphql-parser" version = "0.4.0" @@ -3775,20 +3969,20 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.23" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b553656127a00601c8ae5590fcfdc118e4083a7924b6cf4ffc1ea4b99dc429d7" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 2.1.0", + "http 0.2.11", + "indexmap 2.5.0", "slab", "tokio", - "tokio-util 0.7.10", + "tokio-util", "tracing", ] @@ -3807,7 +4001,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", ] [[package]] @@ -3816,7 +4010,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", ] [[package]] @@ -3825,17 +4019,18 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", ] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.7", + "ahash 0.8.11", "allocator-api2", + "serde", ] [[package]] @@ -3853,7 +4048,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -3878,7 +4073,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http", + "http 0.2.11", "httpdate", "mime", "sha1", @@ -3890,7 +4085,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http", + "http 0.2.11", ] [[package]] @@ -3967,9 +4162,6 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] [[package]] name = "histogram" @@ -4002,7 +4194,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.11.0", + "crypto-mac 0.11.1", "digest 0.9.0", ] @@ -4046,6 +4238,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -4053,15 +4256,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.11", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -4087,22 +4290,22 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http", + "http 0.2.11", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -4118,7 +4321,7 @@ dependencies = [ "bytes", "futures", "headers", - "http", + "http 0.2.11", "hyper", "hyper-rustls 0.22.1", "rustls-native-certs 0.5.0", @@ -4153,13 +4356,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", + "http 0.2.11", "hyper", "log", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", + "webpki-roots 0.25.4", ] [[package]] @@ -4196,14 +4400,14 @@ dependencies = [ "axum", "backtrace", "backtrace-oneline", - "bs58 0.5.0", + "bs58 0.5.1", "color-eyre", "config", "console-subscriber", "convert_case 0.6.0", "derive-new", "derive_builder", - "ed25519-dalek", + "ed25519-dalek 1.0.1", "ethers", "ethers-prometheus", "eyre", @@ -4216,7 +4420,7 @@ dependencies = [ "hyperlane-fuel", "hyperlane-sealevel", "hyperlane-test", - "itertools 0.12.0", + "itertools 0.12.1", "maplit", "mockall", "paste", @@ -4252,26 +4456,26 @@ version = "0.1.0" dependencies = [ "async-rwlock", "async-trait", - "auto_impl 1.1.0", - "bigdecimal 0.4.2", + "auto_impl 1.2.0", + "bigdecimal 0.4.5", "borsh 0.9.3", - "bs58 0.5.0", + "bs58 0.5.1", "bytes", "config", "convert_case 0.6.0", "derive-new", - "derive_more", + "derive_more 0.99.18", "ethers-contract", "ethers-core", "ethers-providers", "eyre", "fixed-hash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures", - "getrandom 0.2.12", + "getrandom 0.2.15", "hex 0.4.3", - "itertools 0.12.0", - "num 0.4.1", - "num-derive 0.4.1", + "itertools 0.12.1", + "num 0.4.3", + "num-derive 0.4.2", "num-traits", "primitive-types", "serde", @@ -4296,18 +4500,18 @@ dependencies = [ "base64 0.21.7", "bech32 0.9.1", "cosmrs", - "cosmwasm-std", + "cosmwasm-std 2.1.3", "derive-new", "futures", "hex 0.4.3", - "http", + "http 0.2.11", "hyper", "hyper-tls", "hyperlane-core", "hyperlane-cosmwasm-interface", "injective-protobuf", "injective-std", - "itertools 0.12.0", + "itertools 0.12.1", "once_cell", "protobuf", "ripemd", @@ -4334,7 +4538,7 @@ checksum = "e5e622014ab94f1e7f0acbe71df7c1384224261e2c76115807aaf24215970942" dependencies = [ "bech32 0.9.1", "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-std 1.5.7", "cosmwasm-storage", "cw-storage-plus", "cw2", @@ -4364,8 +4568,8 @@ dependencies = [ "futures-util", "hex 0.4.3", "hyperlane-core", - "itertools 0.12.0", - "num 0.4.1", + "itertools 0.12.1", + "num 0.4.3", "num-traits", "reqwest", "serde", @@ -4385,6 +4589,7 @@ dependencies = [ "anyhow", "async-trait", "fuels", + "futures", "hyperlane-core", "serde", "thiserror", @@ -4425,71 +4630,6 @@ dependencies = [ "url", ] -[[package]] -name = "hyperlane-sealevel-client" -version = "0.1.0" -dependencies = [ - "account-utils", - "bincode", - "borsh 0.9.3", - "bs58 0.5.0", - "clap 4.4.17", - "ethers", - "hex 0.4.3", - "hyperlane-core", - "hyperlane-sealevel-connection-client", - "hyperlane-sealevel-hello-world", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-multisig-ism-message-id", - "hyperlane-sealevel-token", - "hyperlane-sealevel-token-collateral", - "hyperlane-sealevel-token-lib", - "hyperlane-sealevel-token-native", - "hyperlane-sealevel-validator-announce", - "pretty_env_logger", - "serde", - "serde_json", - "solana-clap-utils", - "solana-cli-config", - "solana-client", - "solana-program", - "solana-sdk", - "solana-transaction-status", -] - -[[package]] -name = "hyperlane-sealevel-connection-client" -version = "0.1.0" -dependencies = [ - "access-control", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-mailbox", - "solana-program", -] - -[[package]] -name = "hyperlane-sealevel-hello-world" -version = "0.1.0" -dependencies = [ - "access-control", - "account-utils", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-connection-client", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "hyperlane-test-utils", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", - "spl-noop", -] - [[package]] name = "hyperlane-sealevel-igp" version = "0.1.0" @@ -4497,32 +4637,15 @@ dependencies = [ "access-control", "account-utils", "borsh 0.9.3", - "getrandom 0.2.12", + "getrandom 0.2.15", "hyperlane-core", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", - "serde", "serializable-account-meta", "solana-program", "thiserror", ] -[[package]] -name = "hyperlane-sealevel-igp-test" -version = "0.1.0" -dependencies = [ - "access-control", - "account-utils", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-igp", - "hyperlane-test-utils", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", -] - [[package]] name = "hyperlane-sealevel-interchain-security-module-interface" version = "0.1.0" @@ -4538,48 +4661,17 @@ version = "0.1.0" dependencies = [ "access-control", "account-utils", - "base64 0.21.7", "blake3", "borsh 0.9.3", - "getrandom 0.2.12", + "getrandom 0.2.15", "hyperlane-core", "hyperlane-sealevel-interchain-security-module-interface", "hyperlane-sealevel-message-recipient-interface", - "itertools 0.12.0", - "log", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", "proc-macro-crate 1.2.1", - "serde", - "serializable-account-meta", - "solana-program", - "spl-noop", - "thiserror", -] - -[[package]] -name = "hyperlane-sealevel-mailbox-test" -version = "0.1.0" -dependencies = [ - "access-control", - "account-utils", - "base64 0.21.7", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-interchain-security-module-interface", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "hyperlane-sealevel-test-ism", - "hyperlane-sealevel-test-send-receiver", - "hyperlane-test-utils", - "itertools 0.12.0", - "log", - "num-derive 0.4.1", - "num-traits", "serializable-account-meta", "solana-program", - "solana-program-test", - "solana-sdk", "spl-noop", "thiserror", ] @@ -4589,7 +4681,7 @@ name = "hyperlane-sealevel-message-recipient-interface" version = "0.1.0" dependencies = [ "borsh 0.9.3", - "getrandom 0.2.12", + "getrandom 0.2.15", "hyperlane-core", "solana-program", "spl-type-length-value", @@ -4603,154 +4695,14 @@ dependencies = [ "account-utils", "borsh 0.9.3", "ecdsa-signature", - "hex 0.4.3", "hyperlane-core", "hyperlane-sealevel-interchain-security-module-interface", "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-multisig-ism-message-id", - "hyperlane-test-utils", "multisig-ism", - "num-derive 0.4.1", - "num-traits", - "rand 0.8.5", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "hyperlane-sealevel-test-ism" -version = "0.1.0" -dependencies = [ - "account-utils", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-interchain-security-module-interface", - "hyperlane-sealevel-mailbox", - "hyperlane-test-transaction-utils", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", -] - -[[package]] -name = "hyperlane-sealevel-test-send-receiver" -version = "0.1.0" -dependencies = [ - "account-utils", - "borsh 0.9.3", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "hyperlane-test-utils", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", - "spl-noop", -] - -[[package]] -name = "hyperlane-sealevel-token" -version = "0.1.0" -dependencies = [ - "account-utils", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-connection-client", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "hyperlane-sealevel-test-ism", - "hyperlane-sealevel-token-lib", - "hyperlane-test-utils", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", "serializable-account-meta", "solana-program", - "solana-program-test", - "solana-sdk", - "spl-associated-token-account", - "spl-noop", - "spl-token", - "spl-token-2022", - "thiserror", -] - -[[package]] -name = "hyperlane-sealevel-token-collateral" -version = "0.1.0" -dependencies = [ - "account-utils", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-connection-client", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "hyperlane-sealevel-test-ism", - "hyperlane-sealevel-token-lib", - "hyperlane-test-utils", - "num-derive 0.4.1", - "num-traits", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", - "spl-associated-token-account", - "spl-noop", - "spl-token", - "spl-token-2022", - "thiserror", -] - -[[package]] -name = "hyperlane-sealevel-token-lib" -version = "0.1.0" -dependencies = [ - "access-control", - "account-utils", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-connection-client", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "num-derive 0.4.1", - "num-traits", - "serializable-account-meta", - "solana-program", - "spl-associated-token-account", - "spl-noop", - "spl-token", - "spl-token-2022", - "thiserror", -] - -[[package]] -name = "hyperlane-sealevel-token-native" -version = "0.1.0" -dependencies = [ - "account-utils", - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-connection-client", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "hyperlane-sealevel-test-ism", - "hyperlane-sealevel-token-lib", - "hyperlane-test-utils", - "num-derive 0.4.1", - "num-traits", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", - "spl-noop", - "tarpc", "thiserror", ] @@ -4761,14 +4713,10 @@ dependencies = [ "account-utils", "borsh 0.9.3", "ecdsa-signature", - "hex 0.4.3", "hyperlane-core", "hyperlane-sealevel-mailbox", - "hyperlane-test-utils", "serializable-account-meta", "solana-program", - "solana-program-test", - "solana-sdk", "thiserror", ] @@ -4781,40 +4729,11 @@ dependencies = [ "mockall", ] -[[package]] -name = "hyperlane-test-transaction-utils" -version = "0.1.0" -dependencies = [ - "solana-program", - "solana-program-test", - "solana-sdk", -] - -[[package]] -name = "hyperlane-test-utils" -version = "0.1.0" -dependencies = [ - "borsh 0.9.3", - "hyperlane-core", - "hyperlane-sealevel-igp", - "hyperlane-sealevel-interchain-security-module-interface", - "hyperlane-sealevel-mailbox", - "hyperlane-sealevel-message-recipient-interface", - "hyperlane-sealevel-test-ism", - "hyperlane-test-transaction-utils", - "serializable-account-meta", - "solana-program", - "solana-program-test", - "solana-sdk", - "spl-noop", - "spl-token-2022", -] - [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -4839,17 +4758,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.3.0" @@ -4955,14 +4863,38 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-tools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82c305b1081f1a99fda262883c788e50ab57d36c00830bdd7e0a82894ad965c" +dependencies = [ + "autocfg", + "impl-tools-lib", + "proc-macro-error", + "syn 2.0.77", +] + +[[package]] +name = "impl-tools-lib" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85d3946d886eaab0702fa0c6585adcced581513223fa9df7ccfabbd9fa331a88" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -4972,12 +4904,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "index_list" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70891286cb8e844fdfcf1178b47569699f9e20b5ecc4b45a6240a64771444638" - [[package]] name = "indexmap" version = "1.9.3" @@ -4986,16 +4912,18 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] name = "indexmap" -version = "2.1.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", + "serde", ] [[package]] @@ -5016,9 +4944,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a52219a08aba8c17846fd23d472d1d69c817fe5b427d135273e4c7311edd6972" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.5.7", "ethereum-types 0.5.2", - "num 0.4.1", + "num 0.4.3", "protobuf", "protobuf-codegen-pure", "schemars", @@ -5033,7 +4961,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd7a5b52d19dca05823c7e4b481d41b49c04a0e56f66a5c92396a6fdd3314710" dependencies = [ "chrono", - "cosmwasm-std", + "cosmwasm-std 1.5.7", "osmosis-std-derive", "prost 0.11.9", "prost-types 0.11.9", @@ -5053,9 +4981,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", "js-sys", @@ -5075,17 +5003,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "is-terminal" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" -dependencies = [ - "hermit-abi 0.3.9", - "rustix", - "windows-sys 0.52.0", -] - [[package]] name = "itertools" version = "0.10.5" @@ -5097,18 +5014,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" @@ -5121,9 +5038,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -5192,9 +5109,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -5204,9 +5121,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libloading" @@ -5220,12 +5137,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -5236,13 +5153,12 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", ] [[package]] @@ -5328,15 +5244,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -5344,34 +5260,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "lru" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" -dependencies = [ - "hashbrown 0.12.3", -] - -[[package]] -name = "lz4" -version = "1.24.0" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" -dependencies = [ - "libc", - "lz4-sys", -] +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "109de74d5d2353660401699a4174a4ff23fcc649caf553df71933c7fb45ad868" dependencies = [ "cc", "libc", @@ -5408,12 +5305,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matchit" version = "0.7.3" @@ -5428,7 +5319,7 @@ checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", ] [[package]] @@ -5443,9 +5334,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -5498,9 +5389,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -5514,13 +5405,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mintex" version = "0.1.3" @@ -5529,9 +5429,9 @@ checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07" [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", @@ -5561,29 +5461,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" dependencies = [ "cfg-if", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 1.0.109", -] - -[[package]] -name = "modular-bitfield" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" -dependencies = [ - "modular-bitfield-impl", - "static_assertions 1.1.0", -] - -[[package]] -name = "modular-bitfield-impl" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" -dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -5596,7 +5475,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 0.2.11", "httparse", "log", "memchr", @@ -5611,7 +5490,6 @@ version = "0.1.0" dependencies = [ "borsh 0.9.3", "ecdsa-signature", - "hex 0.4.3", "hyperlane-core", "solana-program", "spl-type-length-value", @@ -5620,11 +5498,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -5661,12 +5538,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.27.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cfg-if", + "cfg_aliases", "libc", ] @@ -5712,15 +5590,15 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint 0.4.4", - "num-complex 0.4.4", + "num-bigint 0.4.6", + "num-complex 0.4.6", "num-integer", "num-iter", - "num-rational 0.4.1", + "num-rational 0.4.2", "num-traits", ] @@ -5737,11 +5615,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", "serde", @@ -5759,51 +5636,56 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", "serde", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "num-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -5824,12 +5706,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-integer", "num-traits", "serde", @@ -5837,9 +5718,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -5872,6 +5753,15 @@ dependencies = [ "num_enum_derive 0.6.1", ] +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive 0.7.3", +] + [[package]] name = "num_enum_derive" version = "0.5.11" @@ -5879,8 +5769,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate 1.2.1", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -5891,16 +5781,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate 1.2.1", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] @@ -5943,9 +5845,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "open-fastrlp" @@ -5954,7 +5856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" dependencies = [ "arrayvec", - "auto_impl 1.1.0", + "auto_impl 1.2.0", "bytes", "ethereum-types 0.14.1", "open-fastrlp-derive", @@ -5967,18 +5869,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" dependencies = [ "bytes", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "openssl" -version = "0.10.62" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -5993,9 +5895,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -6006,9 +5908,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.98" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -6016,25 +5918,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "opentelemetry" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8" -dependencies = [ - "async-trait", - "crossbeam-channel", - "futures-channel", - "futures-executor", - "futures-util", - "js-sys", - "lazy_static", - "percent-encoding", - "pin-project", - "rand 0.8.5", - "thiserror", -] - [[package]] name = "ordered-multimap" version = "0.4.3" @@ -6058,8 +5941,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4d482a16be198ee04e0f94e10dd9b8d02332dcf33bc5ea4b255e7e25eedc5df" dependencies = [ "itertools 0.10.5", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -6081,8 +5964,8 @@ checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -6098,11 +5981,23 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder", + "sha2 0.10.8", +] + [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec 1.0.1", @@ -6114,13 +6009,13 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.0", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -6137,12 +6032,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] @@ -6161,26 +6056,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "password-hash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a5d4e9c205d2c1ae73b84aab6240e98218c0e72e63b50422cfb2d1ca952282" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", + "windows-targets 0.52.6", ] [[package]] @@ -6196,9 +6080,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" @@ -6217,27 +6101,24 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.8.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "base64ct", - "crypto-mac 0.11.0", - "hmac 0.11.0", - "password-hash 0.2.1", - "sha2 0.9.9", + "digest 0.10.7", + "hmac 0.12.1", + "password-hash", + "sha2 0.10.8", ] [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", "hmac 0.12.1", - "password-hash 0.4.2", - "sha2 0.10.8", ] [[package]] @@ -6263,8 +6144,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" dependencies = [ "peg-runtime", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", ] [[package]] @@ -6299,9 +6180,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.7.6" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -6310,9 +6191,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.6" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -6320,22 +6201,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.6" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "pest_meta" -version = "2.7.6" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -6354,29 +6235,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -6411,31 +6292,25 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.8", + "der 0.7.9", "spki 0.7.3", ] [[package]] name = "pkg-config" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" - -[[package]] -name = "plain" -version = "0.2.3" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", "universal-hash", ] @@ -6450,12 +6325,13 @@ dependencies = [ [[package]] name = "postcard" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", - "embedded-io", + "embedded-io 0.4.0", + "embedded-io 0.6.1", "heapless", "serde", ] @@ -6468,9 +6344,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "predicates" @@ -6489,37 +6368,35 @@ dependencies = [ [[package]] name = "predicates-core" version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +source = "git+https://github.com/assert-rs/predicates-rs?tag=predicates-core-v1.0.6#7b72b706abbf1509fc74ee18e363d2bc7e8520a6" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", ] [[package]] -name = "pretty_env_logger" -version = "0.5.0" +name = "prettyplease" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ - "env_logger 0.10.1", - "log", + "proc-macro2 1.0.86", + "syn 2.0.77", ] [[package]] -name = "prettyplease" -version = "0.2.17" +name = "primeorder" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "proc-macro2 1.0.76", - "syn 2.0.48", + "elliptic-curve 0.13.8", ] [[package]] @@ -6557,20 +6434,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - -[[package]] -name = "proc-macro-crate" -version = "3.0.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2685dd208a3771337d8d386a89840f0f43cd68be8dae90a5f8c2384effc9cd" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.21.0", + "toml_edit 0.22.20", ] [[package]] @@ -6580,8 +6448,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", "version_check", ] @@ -6592,8 +6460,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "version_check", ] @@ -6608,28 +6476,51 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", "lazy_static", "memchr", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "protobuf", "thiserror", ] +[[package]] +name = "prometheus-client" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" +dependencies = [ + "dtoa", + "itoa", + "parking_lot 0.12.3", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "prost" version = "0.11.9" @@ -6642,12 +6533,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.12.5", + "prost-derive 0.12.6", ] [[package]] @@ -6658,22 +6549,22 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools 0.10.5", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "prost-derive" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.0", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "itertools 0.12.1", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -6687,11 +6578,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost 0.12.4", + "prost 0.12.6", ] [[package]] @@ -6743,8 +6634,8 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -6831,11 +6722,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2 1.0.76", + "proc-macro2 1.0.86", ] [[package]] @@ -6937,7 +6828,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", ] [[package]] @@ -6960,9 +6851,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -6970,9 +6861,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -7001,34 +6892,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -7042,13 +6933,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.4", ] [[package]] @@ -7059,9 +6950,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "relayer" @@ -7074,7 +6965,7 @@ dependencies = [ "convert_case 0.6.0", "ctrlc", "derive-new", - "derive_more", + "derive_more 0.99.18", "dhat", "ethers", "ethers-contract", @@ -7085,9 +6976,9 @@ dependencies = [ "hyperlane-core", "hyperlane-ethereum", "hyperlane-test", - "itertools 0.12.0", + "itertools 0.12.1", "mockall", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", "once_cell", "prometheus", @@ -7108,18 +6999,18 @@ dependencies = [ [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "async-compression", "base64 0.21.7", @@ -7130,7 +7021,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", + "http 0.2.11", "http-body", "hyper", "hyper-rustls 0.24.2", @@ -7143,22 +7034,23 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls 0.24.1", - "tokio-util 0.7.10", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.25.3", + "webpki-roots 0.25.4", "winreg", ] @@ -7200,16 +7092,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", - "getrandom 0.2.12", + "cfg-if", + "getrandom 0.2.15", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -7223,9 +7116,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.43" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ "bitvec 1.0.1", "bytecheck", @@ -7236,17 +7129,17 @@ dependencies = [ "rkyv_derive", "seahash", "tinyvec", - "uuid 1.6.1", + "uuid 1.10.0", ] [[package]] name = "rkyv_derive" -version = "0.7.43" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -7274,8 +7167,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -7345,7 +7238,7 @@ dependencies = [ "toml_edit 0.19.15", "ureq", "vergen", - "which", + "which 4.4.2", ] [[package]] @@ -7359,7 +7252,7 @@ dependencies = [ "bytes", "crc32fast", "futures", - "http", + "http 0.2.11", "hyper", "hyper-tls", "lazy_static", @@ -7431,7 +7324,7 @@ dependencies = [ "futures", "hex 0.4.3", "hmac 0.11.0", - "http", + "http 0.2.11", "hyper", "log", "md-5 0.9.1", @@ -7471,12 +7364,12 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.33.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", - "borsh 1.3.1", + "borsh 1.5.1", "bytes", "num-traits", "rand 0.8.5", @@ -7487,9 +7380,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -7505,9 +7398,9 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -7523,11 +7416,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -7561,30 +7454,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.7", - "rustls-webpki 0.101.7", + "ring 0.17.8", + "rustls-webpki", "sct 0.7.1", ] -[[package]] -name = "rustls" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" -dependencies = [ - "log", - "ring 0.17.7", - "rustls-pki-types", - "rustls-webpki 0.102.1", - "subtle", - "zeroize", -] - [[package]] name = "rustls-native-certs" version = "0.5.0" @@ -7627,53 +7506,27 @@ dependencies = [ "base64 0.21.7", ] -[[package]] -name = "rustls-pki-types" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9d979b3ce68192e42760c7810125eb6cf2ea10efae545a156063e61f314e2a" - [[package]] name = "rustls-webpki" version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - -[[package]] -name = "rustls-webpki" -version = "0.102.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4ca26037c909dedb327b48c3327d0ba91d3dd3c4e05dad328f210ffb68e95b" -dependencies = [ - "ring 0.17.7", - "rustls-pki-types", + "ring 0.17.8", "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "salsa20" -version = "0.8.1" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecbd2eb639fd7cab5804a0837fe373cc2172d15437e804c054a9fb885cb923b0" -dependencies = [ - "cipher 0.3.0", -] +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "salsa20" @@ -7681,7 +7534,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" dependencies = [ - "cipher 0.4.4", + "cipher", ] [[package]] @@ -7695,25 +7548,25 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", - "derive_more", + "derive_more 0.99.18", "parity-scale-codec", "scale-info-derive", ] [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.2.1", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -7726,11 +7579,37 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schemafy_core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41781ae092f4fd52c9287efb74456aea0d3b90032d2ecad272bd14dbbcb0511b" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "schemafy_lib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e953db32579999ca98c451d80801b6f6a7ecba6127196c5387ec0774c528befa" +dependencies = [ + "Inflector", + "proc-macro2 1.0.86", + "quote 1.0.37", + "schemafy_core", + "serde", + "serde_derive", + "serde_json", + "syn 1.0.109", +] + [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "schemars_derive", @@ -7740,14 +7619,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] @@ -7769,7 +7648,7 @@ dependencies = [ "async-trait", "config", "console-subscriber", - "derive_more", + "derive_more 0.99.18", "ethers", "eyre", "futures", @@ -7777,9 +7656,9 @@ dependencies = [ "hyperlane-base", "hyperlane-core", "hyperlane-test", - "itertools 0.12.0", + "itertools 0.12.1", "migration", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "num-traits", "prometheus", "sea-orm", @@ -7793,40 +7672,6 @@ dependencies = [ "tracing-futures", ] -[[package]] -name = "scroll" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" -dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", -] - -[[package]] -name = "scrypt" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879588d8f90906e73302547e20fffefdd240eb3e0e744e142321f5d49dea0518" -dependencies = [ - "base64ct", - "hmac 0.11.0", - "password-hash 0.2.1", - "pbkdf2 0.8.0", - "salsa20 0.8.1", - "sha2 0.9.9", -] - [[package]] name = "scrypt" version = "0.10.0" @@ -7835,7 +7680,7 @@ checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", - "salsa20 0.10.2", + "salsa20", "sha2 0.10.8", ] @@ -7855,7 +7700,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -7884,7 +7729,7 @@ dependencies = [ "time", "tracing", "url", - "uuid 1.6.1", + "uuid 1.10.0", ] [[package]] @@ -7911,8 +7756,8 @@ checksum = "28936f26d62234ff0be16f80115dbdeb3237fe9c25cf18fbcd1e3b3592360f20" dependencies = [ "bae", "heck 0.3.3", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -7945,7 +7790,7 @@ dependencies = [ "sea-query-derive", "serde_json", "time", - "uuid 1.6.1", + "uuid 1.10.0", ] [[package]] @@ -7961,7 +7806,7 @@ dependencies = [ "serde_json", "sqlx", "time", - "uuid 1.6.1", + "uuid 1.10.0", ] [[package]] @@ -7971,8 +7816,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63f62030c60f3a691f5fe251713b4e220b306e50a71e1d6f9cce1f24bb781978" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", "thiserror", ] @@ -7995,8 +7840,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", ] @@ -8016,8 +7861,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "rustversion", "syn 1.0.109", ] @@ -8049,7 +7894,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.8", + "der 0.7.9", "generic-array 0.14.7", "pkcs8 0.10.2", "subtle", @@ -8058,9 +7903,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.24.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" dependencies = [ "rand 0.8.5", "secp256k1-sys", @@ -8068,9 +7913,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.6.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" dependencies = [ "cc", ] @@ -8086,11 +7931,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -8099,9 +7944,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -8109,9 +7954,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -8124,18 +7969,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde-aux" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a86348501c129f3ad50c2f4635a01971f76974cd8a3f335988a0f1581c082765" +checksum = "0d2e8bfba469d06512e11e3311d4d051a4a387a5b42d010404fecf3200321c95" dependencies = [ "serde", "serde_json", @@ -8152,60 +7997,70 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.5.1" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-json-wasm" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" dependencies = [ "serde", ] [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 1.0.109", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_path_to_error" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -8213,13 +8068,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -8236,25 +8091,32 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ + "base64 0.22.1", + "chrono", + "hex 0.4.3", + "indexmap 1.9.3", + "indexmap 2.5.0", "serde", + "serde_derive", "serde_json", "serde_with_macros", + "time", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ - "darling 0.13.4", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 1.0.109", + "darling 0.20.10", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -8321,7 +8183,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", ] [[package]] @@ -8357,7 +8219,7 @@ dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", "keccak", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", ] [[package]] @@ -8387,15 +8249,15 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -8447,9 +8309,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -8463,12 +8325,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -8515,83 +8377,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "solana-banks-client" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "borsh 0.9.3", - "futures", - "solana-banks-interface", - "solana-program", - "solana-sdk", - "tarpc", - "thiserror", - "tokio", - "tokio-serde", -] - -[[package]] -name = "solana-banks-interface" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "serde", - "solana-sdk", - "tarpc", -] - -[[package]] -name = "solana-banks-server" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "bincode", - "crossbeam-channel", - "futures", - "solana-banks-interface", - "solana-client", - "solana-runtime", - "solana-sdk", - "solana-send-transaction-service", - "tarpc", - "tokio", - "tokio-serde", - "tokio-stream", -] - -[[package]] -name = "solana-bpf-loader-program" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "bincode", - "byteorder", - "libsecp256k1", - "log", - "solana-measure", - "solana-metrics", - "solana-program-runtime", - "solana-sdk", - "solana-zk-token-sdk", - "solana_rbpf", - "thiserror", -] - -[[package]] -name = "solana-bucket-map" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "log", - "memmap2", - "modular-bitfield", - "rand 0.7.3", - "solana-measure", - "solana-sdk", - "tempfile", -] - [[package]] name = "solana-clap-utils" version = "1.14.13" @@ -8677,15 +8462,6 @@ dependencies = [ "url", ] -[[package]] -name = "solana-compute-budget-program" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "solana-program-runtime", - "solana-sdk", -] - [[package]] name = "solana-config-program" version = "1.14.13" @@ -8727,7 +8503,7 @@ name = "solana-frozen-abi" version = "1.14.13" source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", "blake3", "block-buffer 0.9.0", "bs58 0.4.0", @@ -8760,8 +8536,8 @@ name = "solana-frozen-abi-macro" version = "1.14.13" source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "rustc_version", "syn 1.0.109", ] @@ -8771,7 +8547,7 @@ name = "solana-logger" version = "1.14.13" source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" dependencies = [ - "env_logger 0.9.3", + "env_logger", "lazy_static", "log", ] @@ -8824,11 +8600,11 @@ name = "solana-perf" version = "1.14.13" source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", "bincode", "bv", "caps", - "curve25519-dalek", + "curve25519-dalek 3.2.2", "dlopen", "dlopen_derive", "fnv", @@ -8862,8 +8638,8 @@ dependencies = [ "cc", "console_error_panic_hook", "console_log", - "curve25519-dalek", - "getrandom 0.2.12", + "curve25519-dalek 3.2.2", + "getrandom 0.2.15", "itertools 0.10.5", "js-sys", "lazy_static", @@ -8873,7 +8649,7 @@ dependencies = [ "memoffset", "num-derive 0.3.3", "num-traits", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand 0.7.3", "rand_chacha 0.2.2", "rustc_version", @@ -8901,7 +8677,7 @@ dependencies = [ "base64 0.13.1", "bincode", "eager", - "enum-iterator", + "enum-iterator 0.8.1", "itertools 0.10.5", "libc", "libloading 0.7.4", @@ -8919,30 +8695,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "solana-program-test" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "assert_matches", - "async-trait", - "base64 0.13.1", - "bincode", - "chrono-humanize", - "log", - "serde", - "solana-banks-client", - "solana-banks-server", - "solana-bpf-loader-program", - "solana-logger", - "solana-program-runtime", - "solana-runtime", - "solana-sdk", - "solana-vote-program", - "thiserror", - "tokio", -] - [[package]] name = "solana-rayon-threadlimit" version = "1.14.13" @@ -8962,7 +8714,7 @@ dependencies = [ "log", "num-derive 0.3.3", "num-traits", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "qstring", "semver", "solana-sdk", @@ -8970,66 +8722,6 @@ dependencies = [ "uriparse", ] -[[package]] -name = "solana-runtime" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "arrayref", - "bincode", - "blake3", - "bv", - "bytemuck", - "byteorder", - "bzip2", - "crossbeam-channel", - "dashmap", - "dir-diff", - "flate2", - "fnv", - "im", - "index_list", - "itertools 0.10.5", - "lazy_static", - "log", - "lru", - "lz4", - "memmap2", - "num-derive 0.3.3", - "num-traits", - "num_cpus", - "once_cell", - "ouroboros", - "rand 0.7.3", - "rayon", - "regex", - "rustc_version", - "serde", - "serde_derive", - "solana-address-lookup-table-program", - "solana-bucket-map", - "solana-compute-budget-program", - "solana-config-program", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-measure", - "solana-metrics", - "solana-program-runtime", - "solana-rayon-threadlimit", - "solana-sdk", - "solana-stake-program", - "solana-vote-program", - "solana-zk-token-proof-program", - "solana-zk-token-sdk", - "strum 0.24.1", - "strum_macros 0.24.3", - "symlink", - "tar", - "tempfile", - "thiserror", - "zstd", -] - [[package]] name = "solana-sdk" version = "1.14.13" @@ -9046,7 +8738,7 @@ dependencies = [ "chrono", "derivation-path", "digest 0.10.7", - "ed25519-dalek", + "ed25519-dalek 1.0.1", "ed25519-dalek-bip32", "generic-array 0.14.7", "hmac 0.12.1", @@ -9080,52 +8772,16 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "solana-sdk-macro" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "bs58 0.4.0", - "proc-macro2 1.0.76", - "quote 1.0.35", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "solana-send-transaction-service" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "crossbeam-channel", - "log", - "solana-client", - "solana-measure", - "solana-metrics", - "solana-runtime", - "solana-sdk", -] - -[[package]] -name = "solana-stake-program" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "bincode", - "log", - "num-derive 0.3.3", - "num-traits", - "rustc_version", - "serde", - "serde_derive", - "solana-config-program", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-metrics", - "solana-program-runtime", - "solana-sdk", - "solana-vote-program", - "thiserror", +[[package]] +name = "solana-sdk-macro" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bs58 0.4.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "rustversion", + "syn 1.0.109", ] [[package]] @@ -9219,20 +8875,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "solana-zk-token-proof-program" -version = "1.14.13" -source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" -dependencies = [ - "bytemuck", - "getrandom 0.1.16", - "num-derive 0.3.3", - "num-traits", - "solana-program-runtime", - "solana-sdk", - "solana-zk-token-sdk", -] - [[package]] name = "solana-zk-token-sdk" version = "1.14.13" @@ -9244,8 +8886,8 @@ dependencies = [ "bincode", "bytemuck", "byteorder", - "cipher 0.4.4", - "curve25519-dalek", + "cipher", + "curve25519-dalek 3.2.2", "getrandom 0.1.16", "itertools 0.10.5", "lazy_static", @@ -9263,24 +8905,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "solana_rbpf" -version = "0.2.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80a28c5dfe7e8af38daa39d6561c8e8b9ed7a2f900951ebe7362ad6348d36c73" -dependencies = [ - "byteorder", - "combine", - "goblin", - "hash32", - "libc", - "log", - "rand 0.8.5", - "rustc-demangle", - "scroll", - "thiserror", -] - [[package]] name = "spin" version = "0.5.2" @@ -9323,7 +8947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.8", + "der 0.7.9", ] [[package]] @@ -9413,11 +9037,10 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" dependencies = [ - "itertools 0.12.0", "nom", "unicode_categories", ] @@ -9438,7 +9061,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", "atoi", "base64 0.13.1", "bigdecimal 0.3.1", @@ -9465,7 +9088,7 @@ dependencies = [ "log", "md-5 0.10.6", "memchr", - "num-bigint 0.4.4", + "num-bigint 0.4.6", "once_cell", "paste", "percent-encoding", @@ -9483,7 +9106,7 @@ dependencies = [ "time", "tokio-stream", "url", - "uuid 1.6.1", + "uuid 1.10.0", "whoami", ] @@ -9497,8 +9120,8 @@ dependencies = [ "either", "heck 0.4.1", "once_cell", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "serde_json", "sqlx-core", "sqlx-rt", @@ -9538,13 +9161,13 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] @@ -9560,10 +9183,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "strum" -version = "0.21.0" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -9574,6 +9197,12 @@ dependencies = [ "strum_macros 0.24.3", ] +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + [[package]] name = "strum" version = "0.26.3" @@ -9585,27 +9214,28 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.21.1" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck 0.3.3", - "proc-macro2 1.0.76", - "quote 1.0.35", + "heck 0.4.1", + "proc-macro2 1.0.86", + "quote 1.0.37", + "rustversion", "syn 1.0.109", ] [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "rustversion", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] @@ -9615,17 +9245,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck 0.5.0", - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "rustversion", - "syn 2.0.48", + "syn 2.0.77", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "subtle-encoding" @@ -9642,12 +9272,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" -[[package]] -name = "symlink" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" - [[package]] name = "syn" version = "0.15.44" @@ -9665,19 +9289,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.48" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "unicode-ident", ] @@ -9688,9 +9312,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -9705,10 +9329,21 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", + "proc-macro2 1.0.86", + "quote 1.0.37", "syn 1.0.109", - "unicode-xid 0.2.4", + "unicode-xid 0.2.5", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -9750,7 +9385,7 @@ dependencies = [ "base64 0.13.1", "bytes", "chrono", - "http", + "http 0.2.11", "percent-encoding", "serde", "serde_json", @@ -9765,63 +9400,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tar" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "tarpc" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38a012bed6fb9681d3bf71ffaa4f88f3b4b9ed3198cda6e4c8462d24d4bb80" -dependencies = [ - "anyhow", - "fnv", - "futures", - "humantime", - "opentelemetry", - "pin-project", - "rand 0.8.5", - "serde", - "static_assertions 1.1.0", - "tarpc-plugins", - "thiserror", - "tokio", - "tokio-serde", - "tokio-util 0.6.10", - "tracing", - "tracing-opentelemetry", -] - -[[package]] -name = "tarpc-plugins" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" -dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 1.0.109", -] - [[package]] name = "tempfile" -version = "3.9.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -9911,8 +9500,8 @@ dependencies = [ "bytes", "flex-error", "futures", - "getrandom 0.2.12", - "http", + "getrandom 0.2.15", + "http 0.2.11", "hyper", "hyper-proxy", "hyper-rustls 0.22.1", @@ -9962,28 +9551,28 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -9994,9 +9583,9 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -10004,13 +9593,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", "libc", + "num-conv", "num_threads", "powerfmt", "serde", @@ -10026,10 +9616,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -10072,9 +9663,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -10087,18 +9678,18 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.1" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2 0.5.7", "tokio-macros", "tracing", "windows-sys 0.52.0", @@ -10120,9 +9711,9 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -10174,31 +9765,15 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.12", "tokio", ] -[[package]] -name = "tokio-serde" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "911a61637386b789af998ee23f50aa30d5fd7edcec8d6d3dedae5e5815205466" -dependencies = [ - "bincode", - "bytes", - "educe", - "futures-core", - "futures-sink", - "pin-project", - "serde", - "serde_json", -] - [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -10207,9 +9782,9 @@ dependencies = [ [[package]] name = "tokio-test" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b3cbabd3ae862100094ae433e1def582cf86451b4e9bf83aa7ac1d8a7d719" +checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" dependencies = [ "async-stream", "bytes", @@ -10236,43 +9811,27 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", "log", "tokio", - "tungstenite 0.20.1", -] - -[[package]] -name = "tokio-util" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "slab", - "tokio", + "tungstenite 0.21.0", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -10286,9 +9845,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" @@ -10296,31 +9855,20 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.1.0", + "indexmap 2.5.0", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.5.0", "toml_datetime", - "winnow", + "winnow 0.6.18", ] [[package]] @@ -10337,7 +9885,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", + "http 0.2.11", "http-body", "hyper", "hyper-timeout", @@ -10367,14 +9915,14 @@ dependencies = [ "base64 0.21.7", "bytes", "h2", - "http", + "http 0.2.11", "http-body", "hyper", "hyper-timeout", "percent-encoding", "pin-project", - "prost 0.12.4", - "rustls 0.21.10", + "prost 0.12.6", + "rustls 0.21.12", "rustls-native-certs 0.6.3", "rustls-pemfile 1.0.4", "tokio", @@ -10400,7 +9948,7 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.10", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -10408,15 +9956,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -10436,9 +9984,9 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -10482,19 +10030,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-opentelemetry" -version = "0.17.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbe89715c1dbbb790059e2565353978564924ee85017b5fff365c872ff6721f" -dependencies = [ - "once_cell", - "opentelemetry", - "tracing", - "tracing-core", - "tracing-subscriber", -] - [[package]] name = "tracing-serde" version = "0.1.3" @@ -10528,11 +10063,10 @@ dependencies = [ [[package]] name = "tracing-test" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a2c0ff408fe918a94c428a3f2ad04e4afd5c95bbc08fcf868eff750c15728a4" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" dependencies = [ - "lazy_static", "tracing-core", "tracing-subscriber", "tracing-test-macro", @@ -10540,13 +10074,12 @@ dependencies = [ [[package]] name = "tracing-test-macro" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bc1c4f8e2e73a977812ab339d503e6feeb92700f6d07a6de4d321522d5c08" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ - "lazy_static", - "quote 1.0.35", - "syn 1.0.109", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -10564,7 +10097,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "bytes", - "http", + "http 0.2.11", "httparse", "log", "rand 0.8.5", @@ -10579,14 +10112,14 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 1.1.0", "httparse", "log", "rand 0.8.5", @@ -10598,9 +10131,9 @@ dependencies = [ [[package]] name = "typeid" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" [[package]] name = "typenum" @@ -10610,9 +10143,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "typetag" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "661d18414ec032a49ece2d56eee03636e43c4e8d577047ab334c0ba892e29aaf" +checksum = "52ba3b6e86ffe0054b2c44f2d86407388b933b16cb0a70eea3929420db1d9bbe" dependencies = [ "erased-serde", "inventory", @@ -10623,13 +10156,13 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac73887f47b9312552aa90ef477927ff014d63d1920ca8037c6c1951eab64bb1" +checksum = "70b20a22c42c8f1cd23ce5e34f165d4d37038f5b663ad20fb6adbdf029172483" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -10673,9 +10206,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -10685,24 +10218,30 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" + [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -10712,9 +10251,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "unicode_categories" @@ -10755,11 +10294,11 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "log", "once_cell", "url", @@ -10777,9 +10316,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna 0.5.0", @@ -10792,27 +10331,21 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "uuid" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.15", "serde", ] [[package]] name = "uuid" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "serde", ] @@ -10826,7 +10359,7 @@ dependencies = [ "config", "console-subscriber", "derive-new", - "derive_more", + "derive_more 0.99.18", "ethers", "eyre", "futures", @@ -10880,9 +10413,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" @@ -10892,9 +10425,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -10911,15 +10444,15 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169" +checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" dependencies = [ "bytes", "futures-channel", "futures-util", "headers", - "http", + "http 0.2.11", "hyper", "log", "mime", @@ -10927,15 +10460,13 @@ dependencies = [ "multer", "percent-encoding", "pin-project", - "rustls-pemfile 1.0.4", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-stream", - "tokio-tungstenite 0.20.1", - "tokio-util 0.7.10", + "tokio-tungstenite 0.21.0", + "tokio-util", "tower-service", "tracing", ] @@ -10952,36 +10483,43 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -10991,32 +10529,32 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-timer" @@ -11035,9 +10573,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -11059,7 +10597,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -11083,9 +10621,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "which" @@ -11099,13 +10637,26 @@ dependencies = [ "rustix", ] +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + [[package]] name = "whoami" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "wasm-bindgen", + "redox_syscall 0.5.3", + "wasite", "web-sys", ] @@ -11127,11 +10678,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -11146,7 +10697,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -11164,7 +10715,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -11184,17 +10744,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -11205,9 +10766,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -11217,9 +10778,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -11229,9 +10790,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -11241,9 +10808,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -11253,9 +10820,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -11265,9 +10832,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -11277,15 +10844,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "winnow" -version = "0.5.34" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -11300,6 +10876,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "ws_stream_wasm" version = "0.7.4" @@ -11346,38 +10928,27 @@ dependencies = [ "time", ] -[[package]] -name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys", - "rustix", -] - [[package]] name = "xml-rs" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601" [[package]] name = "ya-gcp" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186a4237c7bddb8a13c1056f45bdfb5c548020327203a66878d74fa7cf31286e" +checksum = "acaf2e321fc6f853572b372962fa253cba1b62a0025116bb463ce3c00b4394dc" dependencies = [ "cfg-if", "futures", - "http", + "http 0.2.11", "humantime-serde", "hyper", "hyper-rustls 0.24.2", "paste", "rand 0.8.5", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-native-certs 0.6.3", "serde", "tame-gcs", @@ -11409,21 +10980,21 @@ dependencies = [ [[package]] name = "yup-oauth2" -version = "8.3.2" +version = "8.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b61da40aeb0907a65f7fb5c1de83c5a224d6a9ebb83bf918588a2bb744d636b8" +checksum = "24bea7df5a9a74a9a0de92f22e5ab3fb9505dd960c7f1f00de5b7231d9d97206" dependencies = [ "anyhow", "async-trait", - "base64 0.21.7", + "base64 0.13.1", "futures", - "http", + "http 0.2.11", "hyper", "hyper-rustls 0.24.2", - "itertools 0.12.0", + "itertools 0.10.5", "log", "percent-encoding", - "rustls 0.22.2", + "rustls 0.21.12", "rustls-pemfile 1.0.4", "seahash", "serde", @@ -11436,29 +11007,30 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -11469,9 +11041,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.76", - "quote 1.0.35", - "syn 2.0.48", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -11495,9 +11067,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/rust/main/Cargo.toml b/rust/main/Cargo.toml new file mode 100644 index 000000000..dab1d9cc4 --- /dev/null +++ b/rust/main/Cargo.toml @@ -0,0 +1,337 @@ +[workspace] +members = [ + "agents/relayer", + "agents/scraper", + "agents/validator", + "chains/hyperlane-cosmos", + "chains/hyperlane-ethereum", + "chains/hyperlane-fuel", + "chains/hyperlane-sealevel", + "ethers-prometheus", + "hyperlane-base", + "hyperlane-core", + "hyperlane-test", + "utils/abigen", + "utils/backtrace-oneline", + "utils/hex", + "utils/run-locally", +] + +[workspace.package] +documentation = "https://docs.hyperlane.xyz" +edition = "2021" +homepage = "https://hyperlane.xyz" +license-file = "../LICENSE.md" +publish = false +version = "0.1.0" + +[workspace.dependencies] +Inflector = "0.11.4" +anyhow = "1.0" +async-trait = "0.1" +async-rwlock = "1.3" +auto_impl = "1.0" +axum = "0.6.1" +backtrace = "0.3" +base64 = "0.21.2" +bigdecimal = "0.4.2" +bincode = "1.3" +borsh = "0.9" +bs58 = "0.5.0" +bytes = "1" +clap = "4" +color-eyre = "0.6" +config = "0.13.3" +console-subscriber = "0.2.0" +convert_case = "0.6" +cosmrs = { version = "0.14", default-features = false, features = [ + "cosmwasm", + "rpc", + "tokio", + "grpc", +] } +cosmwasm-std = "*" +crunchy = "0.2" +ctrlc = "3.2" +curve25519-dalek = { version = "~3.2", features = ["serde"] } +derive-new = "0.5" +derive_builder = "0.12" +derive_more = "0.99" +dhat = "0.3.3" +ed25519-dalek = "~1.0" +eyre = "=0.6.8" +fixed-hash = "0.8.0" +fuels = "0.65.0" +fuels-code-gen = "0.65.0" +futures = "0.3" +futures-util = "0.3" +generic-array = { version = "0.14", features = ["serde", "more_lengths"] } +# Required for WASM support https://docs.rs/getrandom/latest/getrandom/#webassembly-support +bech32 = "0.9.1" +elliptic-curve = "0.12.3" +getrandom = { version = "0.2", features = ["js"] } +hex = "0.4.3" +http = "*" +hyper = "0.14" +hyper-tls = "0.5.0" +hyperlane-cosmwasm-interface = "=0.0.6-rc6" +injective-protobuf = "0.2.2" +injective-std = "=0.1.5" +itertools = "*" +jobserver = "=0.1.26" +jsonrpc-core = "18.0" +k256 = { version = "0.13.1", features = ["std", "ecdsa"] } +log = "0.4" +macro_rules_attribute = "0.2" +maplit = "1.0" +mockall = "0.11" +nix = { version = "0.26", default-features = false } +num = "0.4" +num-bigint = "0.4" +num-derive = "0.4.0" +num-traits = "0.2" +once_cell = "1.18.0" +parking_lot = "0.12" +paste = "1.0" +pretty_env_logger = "0.5.0" +primitive-types = "=0.12.1" +prometheus = "0.13" +protobuf = "*" +rand = "0.8.5" +regex = "1.5" +reqwest = "0.11" +ripemd = "0.1.3" +rlp = "=0.5.2" +rocksdb = "0.21.0" +sea-orm = { version = "0.11.1", features = [ + "sqlx-postgres", + "runtime-tokio-native-tls", + "with-bigdecimal", + "with-time", + "macros", +] } +sea-orm-migration = { version = "0.11.1", features = [ + "sqlx-postgres", + "runtime-tokio-native-tls", +] } +semver = "1.0" +serde = { version = "1.0", features = ["derive"] } +serde_bytes = "0.11" +serde_derive = "1.0" +serde_json = "1.0" +sha2 = { version = "0.10.6", default-features = false } +sha256 = "1.1.4" +sha3 = "0.10" +solana-account-decoder = "=1.14.13" +solana-banks-client = "=1.14.13" +solana-banks-interface = "=1.14.13" +solana-banks-server = "=1.14.13" +solana-clap-utils = "=1.14.13" +solana-cli-config = "=1.14.13" +solana-client = "=1.14.13" +solana-program = "=1.14.13" +solana-program-test = "=1.14.13" +solana-sdk = "=1.14.13" +solana-transaction-status = "=1.14.13" +solana-zk-token-sdk = "=1.14.13" +spl-associated-token-account = { version = "=1.1.2", features = [ + "no-entrypoint", +] } +spl-noop = { version = "=0.1.3", features = ["no-entrypoint"] } +spl-token = { version = "=3.5.0", features = ["no-entrypoint"] } +spl-token-2022 = { version = "=0.5.0", features = ["no-entrypoint"] } +spl-type-length-value = "=0.1.0" +static_assertions = "1.1" +strum = "0.26.2" +strum_macros = "0.26.2" +tempfile = "3.3" +tendermint = "0.32.2" +tendermint-rpc = { version = "0.32.0", features = ["http-client", "tokio"] } +thiserror = "1.0" +time = "0.3" +tiny-keccak = "2.0.2" +tokio = { version = "1.4", features = ["parking_lot", "tracing"] } +tokio-metrics = { version = "0.3.1", default-features = false } +tokio-test = "0.4" +toml_edit = "0.19.14" +tonic = "0.9.2" +tracing = { version = "0.1" } +tracing-error = "0.2" +tracing-futures = "0.2" +tracing-subscriber = { version = "0.3", default-features = false } +tracing-test = "0.2.2" +typetag = "0.2" +uint = "0.9.5" +ureq = { version = "2.4", default-features = false } +url = "2.3" +walkdir = "2" +warp = "0.3" +which = "4.3" +ya-gcp = { version = "0.11.3", features = ["storage"] } + +## TODO: remove this +cosmwasm-schema = "1.2.7" + +[profile.release.package.access-control] +overflow-checks = true + +[profile.release.package.account-utils] +overflow-checks = true + +[profile.release.package.ecdsa-signature] +overflow-checks = true + +[profile.release.package.hyperlane-sealevel-interchain-security-module-interface] +overflow-checks = true + +[profile.release.package.hyperlane-sealevel-message-recipient-interface] +overflow-checks = true + +[profile.release.package.multisig-ism] +overflow-checks = true + +[profile.release.package.serializable-account-meta] +overflow-checks = true + +[profile.release.package.hyperlane-sealevel-mailbox] +overflow-checks = true + +[profile.release.package.hyperlane-sealevel-igp] +overflow-checks = true + +[profile.release.package.hyperlane-sealevel-multisig-ism-message-id] +overflow-checks = true + +[profile.release.package.hyperlane-sealevel-validator-announce] +overflow-checks = true + + +[workspace.dependencies.ethers] +features = [] +git = "https://github.com/hyperlane-xyz/ethers-rs" +tag = "2024-04-25" + +[workspace.dependencies.ethers-contract] +features = ["legacy"] +git = "https://github.com/hyperlane-xyz/ethers-rs" +tag = "2024-04-25" + +[workspace.dependencies.ethers-core] +features = [] +git = "https://github.com/hyperlane-xyz/ethers-rs" +tag = "2024-04-25" + +[workspace.dependencies.ethers-providers] +features = [] +git = "https://github.com/hyperlane-xyz/ethers-rs" +tag = "2024-04-25" + +[workspace.dependencies.ethers-signers] +features = ["aws"] +git = "https://github.com/hyperlane-xyz/ethers-rs" +tag = "2024-04-25" + +[patch.crates-io.cargo-platform] +git = "https://github.com/rust-lang/cargo" +tag = "0.76.0" +version = "=0.1.6" + +[patch.crates-io.predicates-core] +git = "https://github.com/assert-rs/predicates-rs" +tag = "predicates-core-v1.0.6" +version = "=1.0.6" + +[patch.crates-io.curve25519-dalek] +branch = "v3.2.2-relax-zeroize" +git = "https://github.com/Eclipse-Laboratories-Inc/curve25519-dalek" +version = "3.2.2" + +[patch.crates-io.ed25519-dalek] +branch = "main" +git = "https://github.com/Eclipse-Laboratories-Inc/ed25519-dalek" +version = "1.0.1" + +[patch.crates-io.primitive-types] +branch = "hyperlane" +git = "https://github.com/hyperlane-xyz/parity-common.git" +version = "=0.12.1" + +[patch.crates-io.rlp] +branch = "hyperlane" +git = "https://github.com/hyperlane-xyz/parity-common.git" +version = "=0.5.2" + +[patch.crates-io.solana-account-decoder] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.solana-clap-utils] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.solana-cli-config] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.solana-client] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.solana-program] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.solana-sdk] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.solana-transaction-status] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.solana-zk-token-sdk] +git = "https://github.com/hyperlane-xyz/solana.git" +tag = "hyperlane-1.14.13-2023-07-04" +version = "=1.14.13" + +[patch.crates-io.spl-associated-token-account] +branch = "hyperlane" +git = "https://github.com/hyperlane-xyz/solana-program-library.git" +version = "=1.1.2" + +[patch.crates-io.spl-noop] +branch = "hyperlane" +git = "https://github.com/hyperlane-xyz/solana-program-library.git" +version = "=0.1.3" + +[patch.crates-io.spl-token] +branch = "hyperlane" +git = "https://github.com/hyperlane-xyz/solana-program-library.git" +version = "=3.5.0" + +[patch.crates-io.spl-token-2022] +branch = "hyperlane" +git = "https://github.com/hyperlane-xyz/solana-program-library.git" +version = "=0.5.0" + +[patch.crates-io.spl-type-length-value] +version = "=0.1.0" +git = "https://github.com/hyperlane-xyz/solana-program-library.git" +branch = "hyperlane" + +[patch.crates-io.tendermint] +branch = "trevor/0.32.2-fork" +git = "https://github.com/hyperlane-xyz/tendermint-rs.git" +version = "=0.32.2" + +[patch.crates-io.tendermint-rpc] +branch = "trevor/0.32.2-fork" +git = "https://github.com/hyperlane-xyz/tendermint-rs.git" +version = "=0.32.2" diff --git a/rust/agents/relayer/.cargo/config.toml b/rust/main/agents/relayer/.cargo/config.toml similarity index 100% rename from rust/agents/relayer/.cargo/config.toml rename to rust/main/agents/relayer/.cargo/config.toml diff --git a/rust/agents/relayer/Cargo.toml b/rust/main/agents/relayer/Cargo.toml similarity index 88% rename from rust/agents/relayer/Cargo.toml rename to rust/main/agents/relayer/Cargo.toml index 41fff1b24..3a7f5c6bb 100644 --- a/rust/agents/relayer/Cargo.toml +++ b/rust/main/agents/relayer/Cargo.toml @@ -1,4 +1,3 @@ -cargo-features = ["workspace-inheritance"] [package] name = "relayer" @@ -35,13 +34,21 @@ serde.workspace = true serde_json.workspace = true strum.workspace = true thiserror.workspace = true -tokio = { workspace = true, features = ["rt", "macros", "parking_lot", "rt-multi-thread"] } +tokio = { workspace = true, features = [ + "rt", + "macros", + "parking_lot", + "rt-multi-thread", +] } tokio-metrics.workspace = true tracing-futures.workspace = true tracing.workspace = true typetag.workspace = true -hyperlane-core = { path = "../../hyperlane-core", features = ["agent", "async"] } +hyperlane-core = { path = "../../hyperlane-core", features = [ + "agent", + "async", +] } hyperlane-base = { path = "../../hyperlane-base", features = ["test-utils"] } hyperlane-ethereum = { path = "../../chains/hyperlane-ethereum" } diff --git a/rust/agents/relayer/src/lib.rs b/rust/main/agents/relayer/src/lib.rs similarity index 100% rename from rust/agents/relayer/src/lib.rs rename to rust/main/agents/relayer/src/lib.rs diff --git a/rust/agents/relayer/src/main.rs b/rust/main/agents/relayer/src/main.rs similarity index 100% rename from rust/agents/relayer/src/main.rs rename to rust/main/agents/relayer/src/main.rs diff --git a/rust/agents/relayer/src/memory_profiler.rs b/rust/main/agents/relayer/src/memory_profiler.rs similarity index 100% rename from rust/agents/relayer/src/memory_profiler.rs rename to rust/main/agents/relayer/src/memory_profiler.rs diff --git a/rust/agents/relayer/src/merkle_tree/builder.rs b/rust/main/agents/relayer/src/merkle_tree/builder.rs similarity index 100% rename from rust/agents/relayer/src/merkle_tree/builder.rs rename to rust/main/agents/relayer/src/merkle_tree/builder.rs diff --git a/rust/agents/relayer/src/merkle_tree/mod.rs b/rust/main/agents/relayer/src/merkle_tree/mod.rs similarity index 100% rename from rust/agents/relayer/src/merkle_tree/mod.rs rename to rust/main/agents/relayer/src/merkle_tree/mod.rs diff --git a/rust/agents/relayer/src/merkle_tree/processor.rs b/rust/main/agents/relayer/src/merkle_tree/processor.rs similarity index 100% rename from rust/agents/relayer/src/merkle_tree/processor.rs rename to rust/main/agents/relayer/src/merkle_tree/processor.rs diff --git a/rust/agents/relayer/src/msg/blacklist.rs b/rust/main/agents/relayer/src/msg/blacklist.rs similarity index 100% rename from rust/agents/relayer/src/msg/blacklist.rs rename to rust/main/agents/relayer/src/msg/blacklist.rs diff --git a/rust/agents/relayer/src/msg/gas_payment/mod.rs b/rust/main/agents/relayer/src/msg/gas_payment/mod.rs similarity index 100% rename from rust/agents/relayer/src/msg/gas_payment/mod.rs rename to rust/main/agents/relayer/src/msg/gas_payment/mod.rs diff --git a/rust/agents/relayer/src/msg/gas_payment/policies/minimum.rs b/rust/main/agents/relayer/src/msg/gas_payment/policies/minimum.rs similarity index 100% rename from rust/agents/relayer/src/msg/gas_payment/policies/minimum.rs rename to rust/main/agents/relayer/src/msg/gas_payment/policies/minimum.rs diff --git a/rust/agents/relayer/src/msg/gas_payment/policies/mod.rs b/rust/main/agents/relayer/src/msg/gas_payment/policies/mod.rs similarity index 100% rename from rust/agents/relayer/src/msg/gas_payment/policies/mod.rs rename to rust/main/agents/relayer/src/msg/gas_payment/policies/mod.rs diff --git a/rust/agents/relayer/src/msg/gas_payment/policies/none.rs b/rust/main/agents/relayer/src/msg/gas_payment/policies/none.rs similarity index 100% rename from rust/agents/relayer/src/msg/gas_payment/policies/none.rs rename to rust/main/agents/relayer/src/msg/gas_payment/policies/none.rs diff --git a/rust/agents/relayer/src/msg/gas_payment/policies/on_chain_fee_quoting.rs b/rust/main/agents/relayer/src/msg/gas_payment/policies/on_chain_fee_quoting.rs similarity index 100% rename from rust/agents/relayer/src/msg/gas_payment/policies/on_chain_fee_quoting.rs rename to rust/main/agents/relayer/src/msg/gas_payment/policies/on_chain_fee_quoting.rs diff --git a/rust/agents/relayer/src/msg/metadata/aggregation.rs b/rust/main/agents/relayer/src/msg/metadata/aggregation.rs similarity index 99% rename from rust/agents/relayer/src/msg/metadata/aggregation.rs rename to rust/main/agents/relayer/src/msg/metadata/aggregation.rs index a5022e727..072ce62b6 100644 --- a/rust/agents/relayer/src/msg/metadata/aggregation.rs +++ b/rust/main/agents/relayer/src/msg/metadata/aggregation.rs @@ -118,6 +118,7 @@ impl AggregationIsmMetadataBuilder { #[async_trait] impl MetadataBuilder for AggregationIsmMetadataBuilder { #[instrument(err, skip(self), ret)] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn build( &self, ism_address: H256, diff --git a/rust/agents/relayer/src/msg/metadata/base.rs b/rust/main/agents/relayer/src/msg/metadata/base.rs similarity index 98% rename from rust/agents/relayer/src/msg/metadata/base.rs rename to rust/main/agents/relayer/src/msg/metadata/base.rs index 1416a7f56..e4b7ebb19 100644 --- a/rust/agents/relayer/src/msg/metadata/base.rs +++ b/rust/main/agents/relayer/src/msg/metadata/base.rs @@ -1,3 +1,6 @@ +#![allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue +#![allow(clippy::unnecessary_get_then_check)] // TODO: `rustc` 1.80.1 clippy issue + use std::{ collections::HashMap, fmt::Debug, diff --git a/rust/agents/relayer/src/msg/metadata/ccip_read.rs b/rust/main/agents/relayer/src/msg/metadata/ccip_read.rs similarity index 97% rename from rust/agents/relayer/src/msg/metadata/ccip_read.rs rename to rust/main/agents/relayer/src/msg/metadata/ccip_read.rs index 1ca3fbe1b..507271c12 100644 --- a/rust/agents/relayer/src/msg/metadata/ccip_read.rs +++ b/rust/main/agents/relayer/src/msg/metadata/ccip_read.rs @@ -1,3 +1,5 @@ +#![allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + use async_trait::async_trait; use derive_more::Deref; use derive_new::new; diff --git a/rust/agents/relayer/src/msg/metadata/mod.rs b/rust/main/agents/relayer/src/msg/metadata/mod.rs similarity index 100% rename from rust/agents/relayer/src/msg/metadata/mod.rs rename to rust/main/agents/relayer/src/msg/metadata/mod.rs diff --git a/rust/agents/relayer/src/msg/metadata/multisig/base.rs b/rust/main/agents/relayer/src/msg/metadata/multisig/base.rs similarity index 100% rename from rust/agents/relayer/src/msg/metadata/multisig/base.rs rename to rust/main/agents/relayer/src/msg/metadata/multisig/base.rs diff --git a/rust/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs b/rust/main/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs similarity index 100% rename from rust/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs rename to rust/main/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs diff --git a/rust/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs b/rust/main/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs similarity index 100% rename from rust/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs rename to rust/main/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs diff --git a/rust/agents/relayer/src/msg/metadata/multisig/mod.rs b/rust/main/agents/relayer/src/msg/metadata/multisig/mod.rs similarity index 81% rename from rust/agents/relayer/src/msg/metadata/multisig/mod.rs rename to rust/main/agents/relayer/src/msg/metadata/multisig/mod.rs index 5c53cc414..37265d24e 100644 --- a/rust/agents/relayer/src/msg/metadata/multisig/mod.rs +++ b/rust/main/agents/relayer/src/msg/metadata/multisig/mod.rs @@ -2,6 +2,7 @@ mod base; mod merkle_root_multisig; mod message_id_multisig; +#[allow(unused_imports)] // TODO: `rustc` 1.80.1 clippy issue pub use base::{MetadataToken, MultisigIsmMetadataBuilder, MultisigMetadata}; pub use merkle_root_multisig::MerkleRootMultisigMetadataBuilder; diff --git a/rust/agents/relayer/src/msg/metadata/null_metadata.rs b/rust/main/agents/relayer/src/msg/metadata/null_metadata.rs similarity index 85% rename from rust/agents/relayer/src/msg/metadata/null_metadata.rs rename to rust/main/agents/relayer/src/msg/metadata/null_metadata.rs index 1291f8d49..3793fe6b1 100644 --- a/rust/agents/relayer/src/msg/metadata/null_metadata.rs +++ b/rust/main/agents/relayer/src/msg/metadata/null_metadata.rs @@ -10,6 +10,7 @@ pub struct NullMetadataBuilder {} #[async_trait] impl MetadataBuilder for NullMetadataBuilder { + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue #[instrument(err, skip(self))] async fn build( &self, diff --git a/rust/agents/relayer/src/msg/metadata/routing.rs b/rust/main/agents/relayer/src/msg/metadata/routing.rs similarity index 91% rename from rust/agents/relayer/src/msg/metadata/routing.rs rename to rust/main/agents/relayer/src/msg/metadata/routing.rs index c16fbc2a2..0f319e825 100644 --- a/rust/agents/relayer/src/msg/metadata/routing.rs +++ b/rust/main/agents/relayer/src/msg/metadata/routing.rs @@ -15,6 +15,7 @@ pub struct RoutingIsmMetadataBuilder { #[async_trait] impl MetadataBuilder for RoutingIsmMetadataBuilder { #[instrument(err, skip(self), ret)] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn build( &self, ism_address: H256, diff --git a/rust/agents/relayer/src/msg/mod.rs b/rust/main/agents/relayer/src/msg/mod.rs similarity index 95% rename from rust/agents/relayer/src/msg/mod.rs rename to rust/main/agents/relayer/src/msg/mod.rs index abf00ec05..e47015709 100644 --- a/rust/agents/relayer/src/msg/mod.rs +++ b/rust/main/agents/relayer/src/msg/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::doc_lazy_continuation)] // TODO: `rustc` 1.80.1 clippy issue + //! Processor scans DB for new messages and wraps relevant messages as a //! `PendingOperation` and then sends it over a channel to a submitter for //! delivery. diff --git a/rust/agents/relayer/src/msg/op_queue.rs b/rust/main/agents/relayer/src/msg/op_queue.rs similarity index 100% rename from rust/agents/relayer/src/msg/op_queue.rs rename to rust/main/agents/relayer/src/msg/op_queue.rs diff --git a/rust/agents/relayer/src/msg/op_submitter.rs b/rust/main/agents/relayer/src/msg/op_submitter.rs similarity index 99% rename from rust/agents/relayer/src/msg/op_submitter.rs rename to rust/main/agents/relayer/src/msg/op_submitter.rs index 53dba8525..bacc7f747 100644 --- a/rust/agents/relayer/src/msg/op_submitter.rs +++ b/rust/main/agents/relayer/src/msg/op_submitter.rs @@ -1,3 +1,6 @@ +#![allow(clippy::doc_markdown)] // TODO: `rustc` 1.80.1 clippy issue +#![allow(clippy::doc_lazy_continuation)] // TODO: `rustc` 1.80.1 clippy issue + use std::sync::Arc; use std::time::Duration; diff --git a/rust/agents/relayer/src/msg/pending_message.rs b/rust/main/agents/relayer/src/msg/pending_message.rs similarity index 99% rename from rust/agents/relayer/src/msg/pending_message.rs rename to rust/main/agents/relayer/src/msg/pending_message.rs index a65fde909..5d7d824b0 100644 --- a/rust/agents/relayer/src/msg/pending_message.rs +++ b/rust/main/agents/relayer/src/msg/pending_message.rs @@ -1,3 +1,5 @@ +#![allow(clippy::clone_on_ref_ptr)] // TODO: `rustc` 1.80.1 clippy issue + use std::{ fmt::{Debug, Formatter}, sync::Arc, @@ -510,9 +512,9 @@ impl PendingMessage { fn on_reconfirm(&mut self, err: Option, reason: &str) -> PendingOperationResult { self.inc_attempts(); if let Some(e) = err { - warn!(error = ?e, id = ?self.id(), "Reconfirming message: {}", reason.clone()); + warn!(error = ?e, id = ?self.id(), "Reconfirming message: {}", reason); } else { - warn!(id = ?self.id(), "Reconfirming message: {}", reason.clone()); + warn!(id = ?self.id(), "Reconfirming message: {}", reason); } PendingOperationResult::NotReady } diff --git a/rust/agents/relayer/src/msg/processor.rs b/rust/main/agents/relayer/src/msg/processor.rs similarity index 100% rename from rust/agents/relayer/src/msg/processor.rs rename to rust/main/agents/relayer/src/msg/processor.rs diff --git a/rust/agents/relayer/src/processor.rs b/rust/main/agents/relayer/src/processor.rs similarity index 100% rename from rust/agents/relayer/src/processor.rs rename to rust/main/agents/relayer/src/processor.rs diff --git a/rust/agents/relayer/src/prover.rs b/rust/main/agents/relayer/src/prover.rs similarity index 100% rename from rust/agents/relayer/src/prover.rs rename to rust/main/agents/relayer/src/prover.rs diff --git a/rust/agents/relayer/src/relayer.rs b/rust/main/agents/relayer/src/relayer.rs similarity index 100% rename from rust/agents/relayer/src/relayer.rs rename to rust/main/agents/relayer/src/relayer.rs diff --git a/rust/agents/relayer/src/server/list_messages.rs b/rust/main/agents/relayer/src/server/list_messages.rs similarity index 100% rename from rust/agents/relayer/src/server/list_messages.rs rename to rust/main/agents/relayer/src/server/list_messages.rs diff --git a/rust/agents/relayer/src/server/message_retry.rs b/rust/main/agents/relayer/src/server/message_retry.rs similarity index 100% rename from rust/agents/relayer/src/server/message_retry.rs rename to rust/main/agents/relayer/src/server/message_retry.rs diff --git a/rust/agents/relayer/src/server/mod.rs b/rust/main/agents/relayer/src/server/mod.rs similarity index 100% rename from rust/agents/relayer/src/server/mod.rs rename to rust/main/agents/relayer/src/server/mod.rs diff --git a/rust/agents/relayer/src/settings/matching_list.rs b/rust/main/agents/relayer/src/settings/matching_list.rs similarity index 100% rename from rust/agents/relayer/src/settings/matching_list.rs rename to rust/main/agents/relayer/src/settings/matching_list.rs diff --git a/rust/agents/relayer/src/settings/mod.rs b/rust/main/agents/relayer/src/settings/mod.rs similarity index 100% rename from rust/agents/relayer/src/settings/mod.rs rename to rust/main/agents/relayer/src/settings/mod.rs diff --git a/rust/agents/scraper/Cargo.toml b/rust/main/agents/scraper/Cargo.toml similarity index 96% rename from rust/agents/scraper/Cargo.toml rename to rust/main/agents/scraper/Cargo.toml index 234813573..7bad1ec7e 100644 --- a/rust/agents/scraper/Cargo.toml +++ b/rust/main/agents/scraper/Cargo.toml @@ -1,4 +1,3 @@ -cargo-features = ["workspace-inheritance"] [package] name = "scraper" diff --git a/rust/agents/scraper/README.md b/rust/main/agents/scraper/README.md similarity index 100% rename from rust/agents/scraper/README.md rename to rust/main/agents/scraper/README.md diff --git a/rust/agents/scraper/migration/Cargo.toml b/rust/main/agents/scraper/migration/Cargo.toml similarity index 85% rename from rust/agents/scraper/migration/Cargo.toml rename to rust/main/agents/scraper/migration/Cargo.toml index ff9ea4d31..f7cb3a5ce 100644 --- a/rust/agents/scraper/migration/Cargo.toml +++ b/rust/main/agents/scraper/migration/Cargo.toml @@ -1,4 +1,3 @@ -cargo-features = ["workspace-inheritance"] [package] name = "migration" @@ -18,7 +17,12 @@ sea-orm.workspace = true sea-orm-migration.workspace = true serde.workspace = true time.workspace = true -tokio = { workspace = true, features = ["rt", "process", "macros", "parking_lot"] } +tokio = { workspace = true, features = [ + "rt", + "process", + "macros", + "parking_lot", +] } # bin-only deps tracing-subscriber.workspace = true diff --git a/rust/agents/scraper/migration/README.md b/rust/main/agents/scraper/migration/README.md similarity index 100% rename from rust/agents/scraper/migration/README.md rename to rust/main/agents/scraper/migration/README.md diff --git a/rust/agents/scraper/migration/bin/common.rs b/rust/main/agents/scraper/migration/bin/common.rs similarity index 100% rename from rust/agents/scraper/migration/bin/common.rs rename to rust/main/agents/scraper/migration/bin/common.rs diff --git a/rust/agents/scraper/migration/bin/down.rs b/rust/main/agents/scraper/migration/bin/down.rs similarity index 100% rename from rust/agents/scraper/migration/bin/down.rs rename to rust/main/agents/scraper/migration/bin/down.rs diff --git a/rust/agents/scraper/migration/bin/fresh.rs b/rust/main/agents/scraper/migration/bin/fresh.rs similarity index 100% rename from rust/agents/scraper/migration/bin/fresh.rs rename to rust/main/agents/scraper/migration/bin/fresh.rs diff --git a/rust/agents/scraper/migration/bin/generate_entities.rs b/rust/main/agents/scraper/migration/bin/generate_entities.rs similarity index 100% rename from rust/agents/scraper/migration/bin/generate_entities.rs rename to rust/main/agents/scraper/migration/bin/generate_entities.rs diff --git a/rust/agents/scraper/migration/bin/init_db.rs b/rust/main/agents/scraper/migration/bin/init_db.rs similarity index 100% rename from rust/agents/scraper/migration/bin/init_db.rs rename to rust/main/agents/scraper/migration/bin/init_db.rs diff --git a/rust/agents/scraper/migration/bin/recreate_db.rs b/rust/main/agents/scraper/migration/bin/recreate_db.rs similarity index 100% rename from rust/agents/scraper/migration/bin/recreate_db.rs rename to rust/main/agents/scraper/migration/bin/recreate_db.rs diff --git a/rust/agents/scraper/migration/src/l20230309_types.rs b/rust/main/agents/scraper/migration/src/l20230309_types.rs similarity index 100% rename from rust/agents/scraper/migration/src/l20230309_types.rs rename to rust/main/agents/scraper/migration/src/l20230309_types.rs diff --git a/rust/agents/scraper/migration/src/lib.rs b/rust/main/agents/scraper/migration/src/lib.rs similarity index 100% rename from rust/agents/scraper/migration/src/lib.rs rename to rust/main/agents/scraper/migration/src/lib.rs diff --git a/rust/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs b/rust/main/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs similarity index 100% rename from rust/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs rename to rust/main/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs diff --git a/rust/agents/scraper/migration/src/m20230309_000002_create_table_block.rs b/rust/main/agents/scraper/migration/src/m20230309_000002_create_table_block.rs similarity index 100% rename from rust/agents/scraper/migration/src/m20230309_000002_create_table_block.rs rename to rust/main/agents/scraper/migration/src/m20230309_000002_create_table_block.rs diff --git a/rust/agents/scraper/migration/src/m20230309_000003_create_table_cursor.rs b/rust/main/agents/scraper/migration/src/m20230309_000003_create_table_cursor.rs similarity index 100% rename from rust/agents/scraper/migration/src/m20230309_000003_create_table_cursor.rs rename to rust/main/agents/scraper/migration/src/m20230309_000003_create_table_cursor.rs diff --git a/rust/agents/scraper/migration/src/m20230309_000003_create_table_transaction.rs b/rust/main/agents/scraper/migration/src/m20230309_000003_create_table_transaction.rs similarity index 100% rename from rust/agents/scraper/migration/src/m20230309_000003_create_table_transaction.rs rename to rust/main/agents/scraper/migration/src/m20230309_000003_create_table_transaction.rs diff --git a/rust/agents/scraper/migration/src/m20230309_000004_create_table_delivered_message.rs b/rust/main/agents/scraper/migration/src/m20230309_000004_create_table_delivered_message.rs similarity index 100% rename from rust/agents/scraper/migration/src/m20230309_000004_create_table_delivered_message.rs rename to rust/main/agents/scraper/migration/src/m20230309_000004_create_table_delivered_message.rs diff --git a/rust/agents/scraper/migration/src/m20230309_000004_create_table_gas_payment.rs b/rust/main/agents/scraper/migration/src/m20230309_000004_create_table_gas_payment.rs similarity index 100% rename from rust/agents/scraper/migration/src/m20230309_000004_create_table_gas_payment.rs rename to rust/main/agents/scraper/migration/src/m20230309_000004_create_table_gas_payment.rs diff --git a/rust/agents/scraper/migration/src/m20230309_000005_create_table_message.rs b/rust/main/agents/scraper/migration/src/m20230309_000005_create_table_message.rs similarity index 100% rename from rust/agents/scraper/migration/src/m20230309_000005_create_table_message.rs rename to rust/main/agents/scraper/migration/src/m20230309_000005_create_table_message.rs diff --git a/rust/agents/scraper/src/agent.rs b/rust/main/agents/scraper/src/agent.rs similarity index 100% rename from rust/agents/scraper/src/agent.rs rename to rust/main/agents/scraper/src/agent.rs diff --git a/rust/agents/scraper/src/chain_scraper/mod.rs b/rust/main/agents/scraper/src/chain_scraper/mod.rs similarity index 99% rename from rust/agents/scraper/src/chain_scraper/mod.rs rename to rust/main/agents/scraper/src/chain_scraper/mod.rs index 813f11967..23997766c 100644 --- a/rust/agents/scraper/src/chain_scraper/mod.rs +++ b/rust/main/agents/scraper/src/chain_scraper/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_fallible_conversions)] // TODO: `rustc` 1.80.1 clippy issue + //! This module (and children) are responsible for scraping blockchain data and //! keeping things updated. diff --git a/rust/agents/scraper/src/conversions.rs b/rust/main/agents/scraper/src/conversions.rs similarity index 100% rename from rust/agents/scraper/src/conversions.rs rename to rust/main/agents/scraper/src/conversions.rs diff --git a/rust/agents/scraper/src/date_time.rs b/rust/main/agents/scraper/src/date_time.rs similarity index 100% rename from rust/agents/scraper/src/date_time.rs rename to rust/main/agents/scraper/src/date_time.rs diff --git a/rust/agents/scraper/src/db/block.rs b/rust/main/agents/scraper/src/db/block.rs similarity index 100% rename from rust/agents/scraper/src/db/block.rs rename to rust/main/agents/scraper/src/db/block.rs diff --git a/rust/agents/scraper/src/db/block_cursor.rs b/rust/main/agents/scraper/src/db/block_cursor.rs similarity index 100% rename from rust/agents/scraper/src/db/block_cursor.rs rename to rust/main/agents/scraper/src/db/block_cursor.rs diff --git a/rust/agents/scraper/src/db/generated/block.rs b/rust/main/agents/scraper/src/db/generated/block.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/block.rs rename to rust/main/agents/scraper/src/db/generated/block.rs diff --git a/rust/agents/scraper/src/db/generated/cursor.rs b/rust/main/agents/scraper/src/db/generated/cursor.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/cursor.rs rename to rust/main/agents/scraper/src/db/generated/cursor.rs diff --git a/rust/agents/scraper/src/db/generated/delivered_message.rs b/rust/main/agents/scraper/src/db/generated/delivered_message.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/delivered_message.rs rename to rust/main/agents/scraper/src/db/generated/delivered_message.rs diff --git a/rust/agents/scraper/src/db/generated/domain.rs b/rust/main/agents/scraper/src/db/generated/domain.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/domain.rs rename to rust/main/agents/scraper/src/db/generated/domain.rs diff --git a/rust/agents/scraper/src/db/generated/gas_payment.rs b/rust/main/agents/scraper/src/db/generated/gas_payment.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/gas_payment.rs rename to rust/main/agents/scraper/src/db/generated/gas_payment.rs diff --git a/rust/agents/scraper/src/db/generated/message.rs b/rust/main/agents/scraper/src/db/generated/message.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/message.rs rename to rust/main/agents/scraper/src/db/generated/message.rs diff --git a/rust/agents/scraper/src/db/generated/mod.rs b/rust/main/agents/scraper/src/db/generated/mod.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/mod.rs rename to rust/main/agents/scraper/src/db/generated/mod.rs diff --git a/rust/agents/scraper/src/db/generated/prelude.rs b/rust/main/agents/scraper/src/db/generated/prelude.rs similarity index 92% rename from rust/agents/scraper/src/db/generated/prelude.rs rename to rust/main/agents/scraper/src/db/generated/prelude.rs index 2bee035aa..1280bf70d 100644 --- a/rust/agents/scraper/src/db/generated/prelude.rs +++ b/rust/main/agents/scraper/src/db/generated/prelude.rs @@ -1,5 +1,5 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 - +#[allow(unused_imports)] pub use super::{ block::Entity as Block, cursor::Entity as Cursor, delivered_message::Entity as DeliveredMessage, domain::Entity as Domain, diff --git a/rust/agents/scraper/src/db/generated/transaction.rs b/rust/main/agents/scraper/src/db/generated/transaction.rs similarity index 100% rename from rust/agents/scraper/src/db/generated/transaction.rs rename to rust/main/agents/scraper/src/db/generated/transaction.rs diff --git a/rust/agents/scraper/src/db/message.rs b/rust/main/agents/scraper/src/db/message.rs similarity index 99% rename from rust/agents/scraper/src/db/message.rs rename to rust/main/agents/scraper/src/db/message.rs index fdf034c51..1f62c6fa0 100644 --- a/rust/agents/scraper/src/db/message.rs +++ b/rust/main/agents/scraper/src/db/message.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] // TODO: `rustc` 1.80.1 clippy issue + use eyre::Result; use itertools::Itertools; use sea_orm::{prelude::*, ActiveValue::*, DeriveColumn, EnumIter, Insert, QuerySelect}; @@ -11,7 +13,6 @@ use crate::date_time; use crate::db::ScraperDb; use super::generated::{delivered_message, message}; - #[derive(Debug, Clone)] pub struct StorableDelivery<'a> { pub message_id: H256, diff --git a/rust/agents/scraper/src/db/mod.rs b/rust/main/agents/scraper/src/db/mod.rs similarity index 100% rename from rust/agents/scraper/src/db/mod.rs rename to rust/main/agents/scraper/src/db/mod.rs diff --git a/rust/agents/scraper/src/db/payment.rs b/rust/main/agents/scraper/src/db/payment.rs similarity index 100% rename from rust/agents/scraper/src/db/payment.rs rename to rust/main/agents/scraper/src/db/payment.rs diff --git a/rust/agents/scraper/src/db/txn.rs b/rust/main/agents/scraper/src/db/txn.rs similarity index 100% rename from rust/agents/scraper/src/db/txn.rs rename to rust/main/agents/scraper/src/db/txn.rs diff --git a/rust/agents/scraper/src/main.rs b/rust/main/agents/scraper/src/main.rs similarity index 100% rename from rust/agents/scraper/src/main.rs rename to rust/main/agents/scraper/src/main.rs diff --git a/rust/agents/scraper/src/settings.rs b/rust/main/agents/scraper/src/settings.rs similarity index 100% rename from rust/agents/scraper/src/settings.rs rename to rust/main/agents/scraper/src/settings.rs diff --git a/rust/agents/validator/Cargo.toml b/rust/main/agents/validator/Cargo.toml similarity index 90% rename from rust/agents/validator/Cargo.toml rename to rust/main/agents/validator/Cargo.toml index e9e66eb30..7b3f1049c 100644 --- a/rust/agents/validator/Cargo.toml +++ b/rust/main/agents/validator/Cargo.toml @@ -1,4 +1,3 @@ -cargo-features = ["workspace-inheritance"] [package] name = "validator" @@ -28,7 +27,10 @@ tokio = { workspace = true, features = ["rt", "macros", "parking_lot"] } tracing-futures.workspace = true tracing.workspace = true -hyperlane-core = { path = "../../hyperlane-core", features = ["agent", "async"] } +hyperlane-core = { path = "../../hyperlane-core", features = [ + "agent", + "async", +] } hyperlane-base = { path = "../../hyperlane-base" } hyperlane-ethereum = { path = "../../chains/hyperlane-ethereum" } hyperlane-cosmos = { path = "../../chains/hyperlane-cosmos" } diff --git a/rust/agents/validator/src/main.rs b/rust/main/agents/validator/src/main.rs similarity index 100% rename from rust/agents/validator/src/main.rs rename to rust/main/agents/validator/src/main.rs diff --git a/rust/agents/validator/src/server/eigen_node.rs b/rust/main/agents/validator/src/server/eigen_node.rs similarity index 99% rename from rust/agents/validator/src/server/eigen_node.rs rename to rust/main/agents/validator/src/server/eigen_node.rs index 90bcd5e98..7a927d727 100644 --- a/rust/agents/validator/src/server/eigen_node.rs +++ b/rust/main/agents/validator/src/server/eigen_node.rs @@ -1,3 +1,5 @@ +// TODO: `rustc` 1.80.1 clippy issue +#![allow(clippy::doc_lazy_continuation)] //! A server that serves EigenLayer specific routes //! compliant with the spec here https://eigen.nethermind.io/docs/spec/api/ //! diff --git a/rust/agents/validator/src/server/mod.rs b/rust/main/agents/validator/src/server/mod.rs similarity index 100% rename from rust/agents/validator/src/server/mod.rs rename to rust/main/agents/validator/src/server/mod.rs diff --git a/rust/agents/validator/src/settings.rs b/rust/main/agents/validator/src/settings.rs similarity index 100% rename from rust/agents/validator/src/settings.rs rename to rust/main/agents/validator/src/settings.rs diff --git a/rust/agents/validator/src/submit.rs b/rust/main/agents/validator/src/submit.rs similarity index 100% rename from rust/agents/validator/src/submit.rs rename to rust/main/agents/validator/src/submit.rs diff --git a/rust/agents/validator/src/validator.rs b/rust/main/agents/validator/src/validator.rs similarity index 100% rename from rust/agents/validator/src/validator.rs rename to rust/main/agents/validator/src/validator.rs diff --git a/rust/chains/hyperlane-cosmos/Cargo.toml b/rust/main/chains/hyperlane-cosmos/Cargo.toml similarity index 90% rename from rust/chains/hyperlane-cosmos/Cargo.toml rename to rust/main/chains/hyperlane-cosmos/Cargo.toml index f1caaeec0..e8b1af668 100644 --- a/rust/chains/hyperlane-cosmos/Cargo.toml +++ b/rust/main/chains/hyperlane-cosmos/Cargo.toml @@ -1,4 +1,3 @@ -cargo-features = ["workspace-inheritance"] [package] name = "hyperlane-cosmos" @@ -19,7 +18,7 @@ derive-new = { workspace = true } futures = { workspace = true } hex = { workspace = true } http = { workspace = true } -hyperlane-core = { path = "../../hyperlane-core", features = ["async"]} +hyperlane-core = { path = "../../hyperlane-core", features = ["async"] } hyperlane-cosmwasm-interface.workspace = true hyper = { workspace = true } hyper-tls = { workspace = true } @@ -38,7 +37,12 @@ tendermint-rpc = { workspace = true } time = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } -tonic = { workspace = true, features = ["transport", "tls", "tls-roots","tls-roots-common"] } +tonic = { workspace = true, features = [ + "transport", + "tls", + "tls-roots", + "tls-roots-common", +] } tracing = { workspace = true } tracing-futures = { workspace = true } url = { workspace = true } diff --git a/rust/chains/hyperlane-cosmos/src/aggregation_ism.rs b/rust/main/chains/hyperlane-cosmos/src/aggregation_ism.rs similarity index 97% rename from rust/chains/hyperlane-cosmos/src/aggregation_ism.rs rename to rust/main/chains/hyperlane-cosmos/src/aggregation_ism.rs index df41c440b..835b2cf04 100644 --- a/rust/chains/hyperlane-cosmos/src/aggregation_ism.rs +++ b/rust/main/chains/hyperlane-cosmos/src/aggregation_ism.rs @@ -63,6 +63,7 @@ impl HyperlaneChain for CosmosAggregationIsm { #[async_trait] impl AggregationIsm for CosmosAggregationIsm { + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue #[instrument(err)] async fn modules_and_threshold( &self, diff --git a/rust/chains/hyperlane-cosmos/src/error.rs b/rust/main/chains/hyperlane-cosmos/src/error.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/error.rs rename to rust/main/chains/hyperlane-cosmos/src/error.rs diff --git a/rust/chains/hyperlane-cosmos/src/interchain_gas.rs b/rust/main/chains/hyperlane-cosmos/src/interchain_gas.rs similarity index 99% rename from rust/chains/hyperlane-cosmos/src/interchain_gas.rs rename to rust/main/chains/hyperlane-cosmos/src/interchain_gas.rs index 7b9e68af8..0ab0a707e 100644 --- a/rust/chains/hyperlane-cosmos/src/interchain_gas.rs +++ b/rust/main/chains/hyperlane-cosmos/src/interchain_gas.rs @@ -95,7 +95,7 @@ pub struct CosmosInterchainGasPaymasterIndexer { impl CosmosInterchainGasPaymasterIndexer { /// The interchain gas payment event type from the CW contract. - const INTERCHAIN_GAS_PAYMENT_EVENT_TYPE: &str = "igp-core-pay-for-gas"; + const INTERCHAIN_GAS_PAYMENT_EVENT_TYPE: &'static str = "igp-core-pay-for-gas"; /// create new Cosmos InterchainGasPaymasterIndexer agent pub fn new( diff --git a/rust/chains/hyperlane-cosmos/src/interchain_security_module.rs b/rust/main/chains/hyperlane-cosmos/src/interchain_security_module.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/interchain_security_module.rs rename to rust/main/chains/hyperlane-cosmos/src/interchain_security_module.rs diff --git a/rust/chains/hyperlane-cosmos/src/lib.rs b/rust/main/chains/hyperlane-cosmos/src/lib.rs similarity index 92% rename from rust/chains/hyperlane-cosmos/src/lib.rs rename to rust/main/chains/hyperlane-cosmos/src/lib.rs index c0ce3ad54..64f9c96b8 100644 --- a/rust/chains/hyperlane-cosmos/src/lib.rs +++ b/rust/main/chains/hyperlane-cosmos/src/lib.rs @@ -4,6 +4,7 @@ #![warn(missing_docs)] // TODO: Remove once we start filling things in #![allow(unused_variables)] +#![allow(unused_imports)] // TODO: `rustc` 1.80.1 clippy issue mod aggregation_ism; mod error; diff --git a/rust/chains/hyperlane-cosmos/src/libs/account.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/libs/account.rs rename to rust/main/chains/hyperlane-cosmos/src/libs/account.rs diff --git a/rust/chains/hyperlane-cosmos/src/libs/address.rs b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/libs/address.rs rename to rust/main/chains/hyperlane-cosmos/src/libs/address.rs diff --git a/rust/chains/hyperlane-cosmos/src/libs/mod.rs b/rust/main/chains/hyperlane-cosmos/src/libs/mod.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/libs/mod.rs rename to rust/main/chains/hyperlane-cosmos/src/libs/mod.rs diff --git a/rust/chains/hyperlane-cosmos/src/mailbox.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/mailbox.rs rename to rust/main/chains/hyperlane-cosmos/src/mailbox.rs diff --git a/rust/chains/hyperlane-cosmos/src/mailbox/contract.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs similarity index 93% rename from rust/chains/hyperlane-cosmos/src/mailbox/contract.rs rename to rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs index df63f0c06..754a84ce7 100644 --- a/rust/chains/hyperlane-cosmos/src/mailbox/contract.rs +++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs @@ -82,12 +82,14 @@ impl HyperlaneChain for CosmosMailbox { #[async_trait] impl Mailbox for CosmosMailbox { #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn count(&self, lag: Option) -> ChainResult { let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?; self.nonce_at_block(block_height).await } #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn delivered(&self, id: H256) -> ChainResult { let id = hex::encode(id); let payload = payloads::mailbox::DeliveredRequest { @@ -105,6 +107,7 @@ impl Mailbox for CosmosMailbox { } #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn default_ism(&self) -> ChainResult { let payload = payloads::mailbox::DefaultIsmRequest { default_ism: general::EmptyStruct {}, @@ -123,6 +126,7 @@ impl Mailbox for CosmosMailbox { } #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn recipient_ism(&self, recipient: H256) -> ChainResult { let address = CosmosAddress::from_h256( recipient, @@ -150,6 +154,7 @@ impl Mailbox for CosmosMailbox { } #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn process( &self, message: &HyperlaneMessage, @@ -173,6 +178,7 @@ impl Mailbox for CosmosMailbox { } #[instrument(err, ret, skip(self), fields(msg=%message, metadata=%bytes_to_hex(metadata)))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn process_estimate_costs( &self, message: &HyperlaneMessage, diff --git a/rust/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs rename to rust/main/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs diff --git a/rust/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs rename to rust/main/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs diff --git a/rust/chains/hyperlane-cosmos/src/merkle_tree_hook.rs b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs similarity index 98% rename from rust/chains/hyperlane-cosmos/src/merkle_tree_hook.rs rename to rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs index 35fe73a23..ce9283fe2 100644 --- a/rust/chains/hyperlane-cosmos/src/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs @@ -76,6 +76,7 @@ impl HyperlaneChain for CosmosMerkleTreeHook { impl MerkleTreeHook for CosmosMerkleTreeHook { /// Return the incremental merkle tree in storage #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn tree(&self, lag: Option) -> ChainResult { let payload = merkle_tree_hook::MerkleTreeRequest { tree: general::EmptyStruct {}, @@ -119,8 +120,8 @@ impl MerkleTreeHook for CosmosMerkleTreeHook { self.count_at_block(block_height).await } - #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn latest_checkpoint(&self, lag: Option) -> ChainResult { let payload = merkle_tree_hook::CheckPointRequest { check_point: general::EmptyStruct {}, @@ -193,7 +194,7 @@ pub struct CosmosMerkleTreeHookIndexer { impl CosmosMerkleTreeHookIndexer { /// The message dispatch event type from the CW contract. - const MERKLE_TREE_INSERTION_EVENT_TYPE: &str = "hpl_hook_merkle::post_dispatch"; + const MERKLE_TREE_INSERTION_EVENT_TYPE: &'static str = "hpl_hook_merkle::post_dispatch"; /// create new Cosmos MerkleTreeHookIndexer agent pub fn new( diff --git a/rust/chains/hyperlane-cosmos/src/multisig_ism.rs b/rust/main/chains/hyperlane-cosmos/src/multisig_ism.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/multisig_ism.rs rename to rust/main/chains/hyperlane-cosmos/src/multisig_ism.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/aggregate_ism.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/general.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/general.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/general.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/general.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/ism_routes.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/ism_routes.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/ism_routes.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/ism_routes.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/mailbox.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/mailbox.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/mailbox.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/mailbox.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/merkle_tree_hook.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/merkle_tree_hook.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/merkle_tree_hook.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/merkle_tree_hook.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/mod.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/mod.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/mod.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/mod.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/multisig_ism.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/multisig_ism.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/multisig_ism.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/multisig_ism.rs diff --git a/rust/chains/hyperlane-cosmos/src/payloads/validator_announce.rs b/rust/main/chains/hyperlane-cosmos/src/payloads/validator_announce.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/payloads/validator_announce.rs rename to rust/main/chains/hyperlane-cosmos/src/payloads/validator_announce.rs diff --git a/rust/chains/hyperlane-cosmos/src/providers/grpc.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/providers/grpc.rs rename to rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs diff --git a/rust/chains/hyperlane-cosmos/src/providers/grpc/tests.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/providers/grpc/tests.rs rename to rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs diff --git a/rust/chains/hyperlane-cosmos/src/providers/mod.rs b/rust/main/chains/hyperlane-cosmos/src/providers/mod.rs similarity index 99% rename from rust/chains/hyperlane-cosmos/src/providers/mod.rs rename to rust/main/chains/hyperlane-cosmos/src/providers/mod.rs index f033b313c..0d3d2a854 100644 --- a/rust/chains/hyperlane-cosmos/src/providers/mod.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/mod.rs @@ -131,6 +131,7 @@ impl CosmosProvider { .map(|payer| self.search_payer_in_signer_infos(&tx.auth_info.signer_infos, payer)) .map_or_else( || { + #[allow(clippy::get_first)] // TODO: `rustc` 1.80.1 clippy issue let signer_info = tx.auth_info.signer_infos.get(0).ok_or_else(|| { HyperlaneCosmosError::SignerInfoError( "no signer info in default signer".to_owned(), diff --git a/rust/chains/hyperlane-cosmos/src/providers/rpc.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc.rs similarity index 97% rename from rust/chains/hyperlane-cosmos/src/providers/rpc.rs rename to rust/main/chains/hyperlane-cosmos/src/providers/rpc.rs index b5b924def..fac93e008 100644 --- a/rust/chains/hyperlane-cosmos/src/providers/rpc.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc.rs @@ -63,7 +63,7 @@ pub struct CosmosWasmIndexer { } impl CosmosWasmIndexer { - const WASM_TYPE: &str = "wasm"; + const WASM_TYPE: &'static str = "wasm"; /// create new Cosmwasm RPC Provider pub fn new( @@ -214,6 +214,7 @@ impl CosmosWasmIndexer { #[async_trait] impl WasmIndexer for CosmosWasmIndexer { #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { let latest_block = Self::get_latest_block(self.provider.rpc().clone()).await?; let latest_height: u32 = latest_block @@ -227,6 +228,7 @@ impl WasmIndexer for CosmosWasmIndexer { } #[instrument(err, skip(self, parser))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_logs_in_block( &self, block_number: u32, diff --git a/rust/chains/hyperlane-cosmos/src/routing_ism.rs b/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/routing_ism.rs rename to rust/main/chains/hyperlane-cosmos/src/routing_ism.rs diff --git a/rust/chains/hyperlane-cosmos/src/rpc_clients/fallback.rs b/rust/main/chains/hyperlane-cosmos/src/rpc_clients/fallback.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/rpc_clients/fallback.rs rename to rust/main/chains/hyperlane-cosmos/src/rpc_clients/fallback.rs diff --git a/rust/chains/hyperlane-cosmos/src/rpc_clients/mod.rs b/rust/main/chains/hyperlane-cosmos/src/rpc_clients/mod.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/rpc_clients/mod.rs rename to rust/main/chains/hyperlane-cosmos/src/rpc_clients/mod.rs diff --git a/rust/chains/hyperlane-cosmos/src/signers.rs b/rust/main/chains/hyperlane-cosmos/src/signers.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/signers.rs rename to rust/main/chains/hyperlane-cosmos/src/signers.rs diff --git a/rust/chains/hyperlane-cosmos/src/trait_builder.rs b/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/trait_builder.rs rename to rust/main/chains/hyperlane-cosmos/src/trait_builder.rs diff --git a/rust/chains/hyperlane-cosmos/src/types.rs b/rust/main/chains/hyperlane-cosmos/src/types.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/types.rs rename to rust/main/chains/hyperlane-cosmos/src/types.rs diff --git a/rust/chains/hyperlane-cosmos/src/utils.rs b/rust/main/chains/hyperlane-cosmos/src/utils.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/utils.rs rename to rust/main/chains/hyperlane-cosmos/src/utils.rs diff --git a/rust/chains/hyperlane-cosmos/src/validator_announce.rs b/rust/main/chains/hyperlane-cosmos/src/validator_announce.rs similarity index 100% rename from rust/chains/hyperlane-cosmos/src/validator_announce.rs rename to rust/main/chains/hyperlane-cosmos/src/validator_announce.rs diff --git a/rust/chains/hyperlane-ethereum/.gitignore b/rust/main/chains/hyperlane-ethereum/.gitignore similarity index 100% rename from rust/chains/hyperlane-ethereum/.gitignore rename to rust/main/chains/hyperlane-ethereum/.gitignore diff --git a/rust/chains/hyperlane-ethereum/Cargo.toml b/rust/main/chains/hyperlane-ethereum/Cargo.toml similarity index 95% rename from rust/chains/hyperlane-ethereum/Cargo.toml rename to rust/main/chains/hyperlane-ethereum/Cargo.toml index b1f75335f..c096965c9 100644 --- a/rust/chains/hyperlane-ethereum/Cargo.toml +++ b/rust/main/chains/hyperlane-ethereum/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "hyperlane-ethereum" documentation.workspace = true @@ -32,7 +30,7 @@ tracing-futures.workspace = true tracing.workspace = true url.workspace = true -hyperlane-core = { path = "../../hyperlane-core", features = ["async"]} +hyperlane-core = { path = "../../hyperlane-core", features = ["async"] } ethers-prometheus = { path = "../../ethers-prometheus", features = ["serde"] } [build-dependencies] diff --git a/rust/chains/hyperlane-ethereum/abis/ArbitrumNodeInterface.abi.json b/rust/main/chains/hyperlane-ethereum/abis/ArbitrumNodeInterface.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/ArbitrumNodeInterface.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/ArbitrumNodeInterface.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/IAggregationIsm.abi.json b/rust/main/chains/hyperlane-ethereum/abis/IAggregationIsm.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/IAggregationIsm.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/IAggregationIsm.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/ICcipReadIsm.abi.json b/rust/main/chains/hyperlane-ethereum/abis/ICcipReadIsm.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/ICcipReadIsm.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/ICcipReadIsm.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/IInterchainGasPaymaster.abi.json b/rust/main/chains/hyperlane-ethereum/abis/IInterchainGasPaymaster.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/IInterchainGasPaymaster.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/IInterchainGasPaymaster.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/IInterchainSecurityModule.abi.json b/rust/main/chains/hyperlane-ethereum/abis/IInterchainSecurityModule.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/IInterchainSecurityModule.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/IInterchainSecurityModule.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/IMailbox.abi.json b/rust/main/chains/hyperlane-ethereum/abis/IMailbox.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/IMailbox.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/IMailbox.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/IMultisigIsm.abi.json b/rust/main/chains/hyperlane-ethereum/abis/IMultisigIsm.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/IMultisigIsm.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/IMultisigIsm.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/IRoutingIsm.abi.json b/rust/main/chains/hyperlane-ethereum/abis/IRoutingIsm.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/IRoutingIsm.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/IRoutingIsm.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/IValidatorAnnounce.abi.json b/rust/main/chains/hyperlane-ethereum/abis/IValidatorAnnounce.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/IValidatorAnnounce.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/IValidatorAnnounce.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/Mailbox.abi.json b/rust/main/chains/hyperlane-ethereum/abis/Mailbox.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/Mailbox.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/Mailbox.abi.json diff --git a/rust/chains/hyperlane-ethereum/abis/MerkleTreeHook.abi.json b/rust/main/chains/hyperlane-ethereum/abis/MerkleTreeHook.abi.json similarity index 100% rename from rust/chains/hyperlane-ethereum/abis/MerkleTreeHook.abi.json rename to rust/main/chains/hyperlane-ethereum/abis/MerkleTreeHook.abi.json diff --git a/rust/chains/hyperlane-ethereum/build.rs b/rust/main/chains/hyperlane-ethereum/build.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/build.rs rename to rust/main/chains/hyperlane-ethereum/build.rs diff --git a/rust/chains/hyperlane-ethereum/src/config.rs b/rust/main/chains/hyperlane-ethereum/src/config.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/config.rs rename to rust/main/chains/hyperlane-ethereum/src/config.rs diff --git a/rust/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs similarity index 98% rename from rust/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs rename to rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs index e6f2c8a4a..b14903a64 100644 --- a/rust/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs @@ -90,6 +90,7 @@ where { /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn fetch_logs_in_range( &self, range: RangeInclusive, @@ -119,6 +120,7 @@ where } #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { Ok(self .provider diff --git a/rust/chains/hyperlane-ethereum/src/contracts/mailbox.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs similarity index 98% rename from rust/chains/hyperlane-ethereum/src/contracts/mailbox.rs rename to rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs index e751ab9b7..406673b51 100644 --- a/rust/chains/hyperlane-ethereum/src/contracts/mailbox.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs @@ -143,6 +143,7 @@ where /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn fetch_logs_in_range( &self, range: RangeInclusive, @@ -198,6 +199,7 @@ where M: Middleware + 'static, { #[instrument(err, skip(self), ret)] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn latest_sequence_count_and_tip(&self) -> ChainResult<(Option, u32)> { let tip = Indexer::::get_finalized_block_number(self).await?; let sequence = self.contract.nonce().block(u64::from(tip)).call().await?; @@ -216,6 +218,7 @@ where /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn fetch_logs_in_range( &self, range: RangeInclusive, diff --git a/rust/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs similarity index 98% rename from rust/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs rename to rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs index c307621c2..a2f8a4a74 100644 --- a/rust/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs @@ -115,6 +115,7 @@ where { /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn fetch_logs_in_range( &self, range: RangeInclusive, @@ -140,6 +141,7 @@ where } #[instrument(level = "debug", err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { Ok(self .provider diff --git a/rust/chains/hyperlane-ethereum/src/contracts/mod.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/mod.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/contracts/mod.rs rename to rust/main/chains/hyperlane-ethereum/src/contracts/mod.rs diff --git a/rust/chains/hyperlane-ethereum/src/contracts/multicall.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/multicall.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/contracts/multicall.rs rename to rust/main/chains/hyperlane-ethereum/src/contracts/multicall.rs diff --git a/rust/chains/hyperlane-ethereum/src/contracts/utils.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/utils.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/contracts/utils.rs rename to rust/main/chains/hyperlane-ethereum/src/contracts/utils.rs diff --git a/rust/chains/hyperlane-ethereum/src/contracts/validator_announce.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/validator_announce.rs similarity index 98% rename from rust/chains/hyperlane-ethereum/src/contracts/validator_announce.rs rename to rust/main/chains/hyperlane-ethereum/src/contracts/validator_announce.rs index 2479f5a19..2da1078f9 100644 --- a/rust/chains/hyperlane-ethereum/src/contracts/validator_announce.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/validator_announce.rs @@ -163,6 +163,7 @@ where } #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn announce(&self, announcement: SignedType) -> ChainResult { let contract_call = self.announce_contract_call(announcement).await?; let receipt = report_tx(contract_call).await?; diff --git a/rust/chains/hyperlane-ethereum/src/error.rs b/rust/main/chains/hyperlane-ethereum/src/error.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/error.rs rename to rust/main/chains/hyperlane-ethereum/src/error.rs diff --git a/rust/chains/hyperlane-ethereum/src/ism/aggregation_ism.rs b/rust/main/chains/hyperlane-ethereum/src/ism/aggregation_ism.rs similarity index 97% rename from rust/chains/hyperlane-ethereum/src/ism/aggregation_ism.rs rename to rust/main/chains/hyperlane-ethereum/src/ism/aggregation_ism.rs index 5f685cf26..61b371f3b 100644 --- a/rust/chains/hyperlane-ethereum/src/ism/aggregation_ism.rs +++ b/rust/main/chains/hyperlane-ethereum/src/ism/aggregation_ism.rs @@ -93,6 +93,7 @@ where M: Middleware + 'static, { #[instrument(err)] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn modules_and_threshold( &self, message: &HyperlaneMessage, diff --git a/rust/chains/hyperlane-ethereum/src/ism/ccip_read_ism.rs b/rust/main/chains/hyperlane-ethereum/src/ism/ccip_read_ism.rs similarity index 97% rename from rust/chains/hyperlane-ethereum/src/ism/ccip_read_ism.rs rename to rust/main/chains/hyperlane-ethereum/src/ism/ccip_read_ism.rs index 8f0ef6b91..dc76d43fa 100644 --- a/rust/chains/hyperlane-ethereum/src/ism/ccip_read_ism.rs +++ b/rust/main/chains/hyperlane-ethereum/src/ism/ccip_read_ism.rs @@ -90,6 +90,7 @@ where M: Middleware + 'static, { #[instrument(err)] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_offchain_verify_info(&self, message: Vec) -> ChainResult<()> { self.contract .get_offchain_verify_info(message.into()) diff --git a/rust/chains/hyperlane-ethereum/src/ism/interchain_security_module.rs b/rust/main/chains/hyperlane-ethereum/src/ism/interchain_security_module.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/ism/interchain_security_module.rs rename to rust/main/chains/hyperlane-ethereum/src/ism/interchain_security_module.rs diff --git a/rust/chains/hyperlane-ethereum/src/ism/mod.rs b/rust/main/chains/hyperlane-ethereum/src/ism/mod.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/ism/mod.rs rename to rust/main/chains/hyperlane-ethereum/src/ism/mod.rs diff --git a/rust/chains/hyperlane-ethereum/src/ism/multisig_ism.rs b/rust/main/chains/hyperlane-ethereum/src/ism/multisig_ism.rs similarity index 97% rename from rust/chains/hyperlane-ethereum/src/ism/multisig_ism.rs rename to rust/main/chains/hyperlane-ethereum/src/ism/multisig_ism.rs index 87e6b030b..2c71c900c 100644 --- a/rust/chains/hyperlane-ethereum/src/ism/multisig_ism.rs +++ b/rust/main/chains/hyperlane-ethereum/src/ism/multisig_ism.rs @@ -99,6 +99,7 @@ where M: Middleware + 'static, { #[instrument(err)] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn validators_and_threshold( &self, message: &HyperlaneMessage, diff --git a/rust/chains/hyperlane-ethereum/src/ism/routing_ism.rs b/rust/main/chains/hyperlane-ethereum/src/ism/routing_ism.rs similarity index 97% rename from rust/chains/hyperlane-ethereum/src/ism/routing_ism.rs rename to rust/main/chains/hyperlane-ethereum/src/ism/routing_ism.rs index d23d06ca6..39aaf7ecd 100644 --- a/rust/chains/hyperlane-ethereum/src/ism/routing_ism.rs +++ b/rust/main/chains/hyperlane-ethereum/src/ism/routing_ism.rs @@ -90,6 +90,7 @@ where M: Middleware + 'static, { #[instrument(err)] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn route(&self, message: &HyperlaneMessage) -> ChainResult { let ism = self .contract diff --git a/rust/chains/hyperlane-ethereum/src/lib.rs b/rust/main/chains/hyperlane-ethereum/src/lib.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/lib.rs rename to rust/main/chains/hyperlane-ethereum/src/lib.rs diff --git a/rust/chains/hyperlane-ethereum/src/rpc_clients/fallback.rs b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/fallback.rs similarity index 99% rename from rust/chains/hyperlane-ethereum/src/rpc_clients/fallback.rs rename to rust/main/chains/hyperlane-ethereum/src/rpc_clients/fallback.rs index 6d57a10e2..9c52a6bb3 100644 --- a/rust/chains/hyperlane-ethereum/src/rpc_clients/fallback.rs +++ b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/fallback.rs @@ -32,6 +32,7 @@ impl Debug for EthereumFallbackProvider where C: JsonRpcClient + PrometheusJsonRpcClientConfigExt, { + #[allow(clippy::get_first)] // TODO: `rustc` 1.80.1 clippy issue fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("FallbackProvider") .field( diff --git a/rust/chains/hyperlane-ethereum/src/rpc_clients/mod.rs b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/mod.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/rpc_clients/mod.rs rename to rust/main/chains/hyperlane-ethereum/src/rpc_clients/mod.rs diff --git a/rust/chains/hyperlane-ethereum/src/rpc_clients/provider.rs b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs similarity index 95% rename from rust/chains/hyperlane-ethereum/src/rpc_clients/provider.rs rename to rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs index a5e333342..8434a4de3 100644 --- a/rust/chains/hyperlane-ethereum/src/rpc_clients/provider.rs +++ b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs @@ -48,6 +48,7 @@ where M: Middleware + 'static, { #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_block_by_hash(&self, hash: &H256) -> ChainResult { let block = get_with_retry_on_none(hash, |h| { let eth_h256: ethers_core_types::H256 = h.into(); @@ -65,6 +66,7 @@ where } #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult { let txn = get_with_retry_on_none(hash, |h| self.provider.get_transaction(*h)).await?; let receipt = self @@ -95,6 +97,7 @@ where } #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn is_contract(&self, address: &H256) -> ChainResult { let code = self .provider @@ -105,6 +108,7 @@ where } #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_balance(&self, address: String) -> ChainResult { // Can't use the address directly as a string, because ethers interprets it // as an ENS name rather than an address. diff --git a/rust/chains/hyperlane-ethereum/src/rpc_clients/retrying.rs b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/retrying.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/rpc_clients/retrying.rs rename to rust/main/chains/hyperlane-ethereum/src/rpc_clients/retrying.rs diff --git a/rust/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs rename to rust/main/chains/hyperlane-ethereum/src/rpc_clients/trait_builder.rs diff --git a/rust/chains/hyperlane-ethereum/src/signer/mod.rs b/rust/main/chains/hyperlane-ethereum/src/signer/mod.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/signer/mod.rs rename to rust/main/chains/hyperlane-ethereum/src/signer/mod.rs diff --git a/rust/chains/hyperlane-ethereum/src/signer/singleton.rs b/rust/main/chains/hyperlane-ethereum/src/signer/singleton.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/signer/singleton.rs rename to rust/main/chains/hyperlane-ethereum/src/signer/singleton.rs diff --git a/rust/chains/hyperlane-ethereum/src/tx.rs b/rust/main/chains/hyperlane-ethereum/src/tx.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/src/tx.rs rename to rust/main/chains/hyperlane-ethereum/src/tx.rs diff --git a/rust/chains/hyperlane-ethereum/tests/signer_output.rs b/rust/main/chains/hyperlane-ethereum/tests/signer_output.rs similarity index 100% rename from rust/chains/hyperlane-ethereum/tests/signer_output.rs rename to rust/main/chains/hyperlane-ethereum/tests/signer_output.rs diff --git a/rust/chains/hyperlane-fuel/.gitignore b/rust/main/chains/hyperlane-fuel/.gitignore similarity index 100% rename from rust/chains/hyperlane-fuel/.gitignore rename to rust/main/chains/hyperlane-fuel/.gitignore diff --git a/rust/chains/hyperlane-fuel/Cargo.toml b/rust/main/chains/hyperlane-fuel/Cargo.toml similarity index 91% rename from rust/chains/hyperlane-fuel/Cargo.toml rename to rust/main/chains/hyperlane-fuel/Cargo.toml index d2a711feb..bb82a9c07 100644 --- a/rust/chains/hyperlane-fuel/Cargo.toml +++ b/rust/main/chains/hyperlane-fuel/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "hyperlane-fuel" documentation.workspace = true @@ -13,13 +11,14 @@ version.workspace = true anyhow.workspace = true async-trait.workspace = true fuels.workspace = true +futures.workspace = true serde.workspace = true thiserror.workspace = true tracing-futures.workspace = true tracing.workspace = true url.workspace = true -hyperlane-core = { path = "../../hyperlane-core", features = ["async"]} +hyperlane-core = { path = "../../hyperlane-core", features = ["async"] } [build-dependencies] abigen = { path = "../../utils/abigen", features = ["fuels"] } diff --git a/rust/main/chains/hyperlane-fuel/abis/Mailbox.abi.json b/rust/main/chains/hyperlane-fuel/abis/Mailbox.abi.json new file mode 100644 index 000000000..5c357aa4b --- /dev/null +++ b/rust/main/chains/hyperlane-fuel/abis/Mailbox.abi.json @@ -0,0 +1,1282 @@ +{ + "encoding": "1", + "types": [ + { + "typeId": 0, + "type": "()", + "components": [], + "typeParameters": null + }, + { + "typeId": 1, + "type": "b256", + "components": null, + "typeParameters": null + }, + { + "typeId": 2, + "type": "bool", + "components": null, + "typeParameters": null + }, + { + "typeId": 3, + "type": "enum AccessError", + "components": [ + { + "name": "NotOwner", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 4, + "type": "enum Identity", + "components": [ + { + "name": "Address", + "type": 11, + "typeArguments": null + }, + { + "name": "ContractId", + "type": 13, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 5, + "type": "enum InitializationError", + "components": [ + { + "name": "CannotReinitialized", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 6, + "type": "enum MailboxError", + "components": [ + { + "name": "InvalidISMAddress", + "type": 0, + "typeArguments": null + }, + { + "name": "InvalidHookAddress", + "type": 0, + "typeArguments": null + }, + { + "name": "InvalidProtocolVersion", + "type": 27, + "typeArguments": null + }, + { + "name": "InvalidMessageOrigin", + "type": 25, + "typeArguments": null + }, + { + "name": "MessageAlreadyDelivered", + "type": 0, + "typeArguments": null + }, + { + "name": "MessageVerificationFailed", + "type": 0, + "typeArguments": null + }, + { + "name": "AlreadyInitialized", + "type": 0, + "typeArguments": null + }, + { + "name": "MessageTooLarge", + "type": 26, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 7, + "type": "enum PauseError", + "components": [ + { + "name": "Paused", + "type": 0, + "typeArguments": null + }, + { + "name": "NotPaused", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 8, + "type": "enum ReentrancyError", + "components": [ + { + "name": "NonReentrant", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 9, + "type": "enum State", + "components": [ + { + "name": "Uninitialized", + "type": 0, + "typeArguments": null + }, + { + "name": "Initialized", + "type": 4, + "typeArguments": null + }, + { + "name": "Revoked", + "type": 0, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 10, + "type": "raw untyped ptr", + "components": null, + "typeParameters": null + }, + { + "typeId": 11, + "type": "struct Address", + "components": [ + { + "name": "bits", + "type": 1, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 12, + "type": "struct Bytes", + "components": [ + { + "name": "buf", + "type": 23, + "typeArguments": null + }, + { + "name": "len", + "type": 26, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 13, + "type": "struct ContractId", + "components": [ + { + "name": "bits", + "type": 1, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 14, + "type": "struct DefaultHookSetEvent", + "components": [ + { + "name": "module", + "type": 13, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 15, + "type": "struct DefaultIsmSetEvent", + "components": [ + { + "name": "module", + "type": 13, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 16, + "type": "struct DispatchEvent", + "components": [ + { + "name": "message_id", + "type": 1, + "typeArguments": null + }, + { + "name": "destination_domain", + "type": 25, + "typeArguments": null + }, + { + "name": "recipient_address", + "type": 1, + "typeArguments": null + }, + { + "name": "message", + "type": 18, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 17, + "type": "struct DispatchIdEvent", + "components": [ + { + "name": "message_id", + "type": 1, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 18, + "type": "struct EncodedMessage", + "components": [ + { + "name": "bytes", + "type": 12, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 19, + "type": "struct OwnershipRenounced", + "components": [ + { + "name": "previous_owner", + "type": 4, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 20, + "type": "struct OwnershipSet", + "components": [ + { + "name": "new_owner", + "type": 4, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 21, + "type": "struct OwnershipTransferred", + "components": [ + { + "name": "new_owner", + "type": 4, + "typeArguments": null + }, + { + "name": "previous_owner", + "type": 4, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 22, + "type": "struct ProcessEvent", + "components": [ + { + "name": "message_id", + "type": 1, + "typeArguments": null + }, + { + "name": "origin", + "type": 25, + "typeArguments": null + }, + { + "name": "sender", + "type": 1, + "typeArguments": null + }, + { + "name": "recipient", + "type": 1, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 23, + "type": "struct RawBytes", + "components": [ + { + "name": "ptr", + "type": 10, + "typeArguments": null + }, + { + "name": "cap", + "type": 26, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 24, + "type": "struct RequiredHookSetEvent", + "components": [ + { + "name": "module", + "type": 13, + "typeArguments": null + } + ], + "typeParameters": null + }, + { + "typeId": 25, + "type": "u32", + "components": null, + "typeParameters": null + }, + { + "typeId": 26, + "type": "u64", + "components": null, + "typeParameters": null + }, + { + "typeId": 27, + "type": "u8", + "components": null, + "typeParameters": null + } + ], + "functions": [ + { + "inputs": [], + "name": "default_hook", + "output": { + "name": "", + "type": 13, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Gets the default hook used for message processing." + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "default_ism", + "output": { + "name": "", + "type": 13, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Gets the default ISM used for message verification." + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "message_id", + "type": 1, + "typeArguments": null + } + ], + "name": "delivered", + "output": { + "name": "", + "type": 2, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Returns true if the message has been processed." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " ### Arguments" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `message_id` - The unique identifier of the message." + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "destination_domain", + "type": 25, + "typeArguments": null + }, + { + "name": "recipient_address", + "type": 1, + "typeArguments": null + }, + { + "name": "message_body", + "type": 12, + "typeArguments": null + }, + { + "name": "metadata", + "type": 12, + "typeArguments": null + }, + { + "name": "hook", + "type": 13, + "typeArguments": null + } + ], + "name": "dispatch", + "output": { + "name": "", + "type": 1, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Dispatches a message to the destination domain and recipient." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " Returns the message's ID." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " ### Arguments" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `destination_domain` - The domain of the destination chain." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `recipient` - Address of the recipient on the destination chain." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `message_body` - Raw bytes content of the message body." + ] + }, + { + "name": "payable", + "arguments": [] + }, + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "owner", + "type": 1, + "typeArguments": null + }, + { + "name": "default_ism", + "type": 1, + "typeArguments": null + }, + { + "name": "default_hook", + "type": 1, + "typeArguments": null + }, + { + "name": "required_hook", + "type": 1, + "typeArguments": null + } + ], + "name": "initialize", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Initializes the contract." + ] + }, + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + }, + { + "inputs": [], + "name": "latest_dispatched_id", + "output": { + "name": "", + "type": 1, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "local_domain", + "output": { + "name": "", + "type": 25, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Returns the domain of the chain where the contract is deployed." + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "nonce", + "output": { + "name": "", + "type": 25, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "metadata", + "type": 12, + "typeArguments": null + }, + { + "name": "message", + "type": 12, + "typeArguments": null + } + ], + "name": "process", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Processes a message." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " ### Arguments" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `metadata` - The metadata for ISM verification." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `message` - The message as emitted by dispatch." + ] + }, + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "destination_domain", + "type": 25, + "typeArguments": null + }, + { + "name": "recipient_address", + "type": 1, + "typeArguments": null + }, + { + "name": "message_body", + "type": 12, + "typeArguments": null + }, + { + "name": "metadata", + "type": 12, + "typeArguments": null + }, + { + "name": "hook", + "type": 13, + "typeArguments": null + } + ], + "name": "quote_dispatch", + "output": { + "name": "", + "type": 26, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Quotes the cost of dispatching a message to the destination domain and recipient." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " ### Arguments" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `destination_domain` - The domain of the destination chain." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `recipient` - Address of the recipient on the destination chain." + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `message_body` - Raw bytes content of the message body." + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "recipient", + "type": 13, + "typeArguments": null + } + ], + "name": "recipient_ism", + "output": { + "name": "", + "type": 13, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [], + "name": "required_hook", + "output": { + "name": "", + "type": 13, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Gets the required hook used for message processing." + ] + }, + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [ + { + "name": "module", + "type": 13, + "typeArguments": null + } + ], + "name": "set_default_hook", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Sets the default hook used for message processing." + ] + }, + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "module", + "type": 13, + "typeArguments": null + } + ], + "name": "set_default_ism", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Sets the default ISM used for message verification." + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " ### Arguments" + ] + }, + { + "name": "doc-comment", + "arguments": [ + "" + ] + }, + { + "name": "doc-comment", + "arguments": [ + " * `module` - Address implementing ISM interface." + ] + }, + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "module", + "type": 13, + "typeArguments": null + } + ], + "name": "set_required_hook", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "doc-comment", + "arguments": [ + " Sets the required hook used for message processing." + ] + }, + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + }, + { + "inputs": [], + "name": "is_paused", + "output": { + "name": "", + "type": 2, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "pause", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + }, + { + "inputs": [], + "name": "unpause", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "new_owner", + "type": 4, + "typeArguments": null + } + ], + "name": "initialize_ownership", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [], + "name": "only_owner", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "owner", + "output": { + "name": "", + "type": 9, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read" + ] + } + ] + }, + { + "inputs": [], + "name": "renounce_ownership", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "read", + "write" + ] + } + ] + }, + { + "inputs": [ + { + "name": "new_owner", + "type": 4, + "typeArguments": null + } + ], + "name": "transfer_ownership", + "output": { + "name": "", + "type": 0, + "typeArguments": null + }, + "attributes": [ + { + "name": "storage", + "arguments": [ + "write" + ] + } + ] + } + ], + "loggedTypes": [ + { + "logId": "5557842539076482339", + "loggedType": { + "name": "", + "type": 8, + "typeArguments": [] + } + }, + { + "logId": "10032608944051208538", + "loggedType": { + "name": "", + "type": 7, + "typeArguments": [] + } + }, + { + "logId": "4904025822840310122", + "loggedType": { + "name": "", + "type": 6, + "typeArguments": [] + } + }, + { + "logId": "10811788483172643035", + "loggedType": { + "name": "", + "type": 16, + "typeArguments": [] + } + }, + { + "logId": "2522729423758891677", + "loggedType": { + "name": "", + "type": 17, + "typeArguments": [] + } + }, + { + "logId": "2161305517876418151", + "loggedType": { + "name": "", + "type": 5, + "typeArguments": [] + } + }, + { + "logId": "16280289466020123285", + "loggedType": { + "name": "", + "type": 20, + "typeArguments": [] + } + }, + { + "logId": "7929134096091764817", + "loggedType": { + "name": "", + "type": 22, + "typeArguments": [] + } + }, + { + "logId": "4571204900286667806", + "loggedType": { + "name": "", + "type": 3, + "typeArguments": [] + } + }, + { + "logId": "14400248731700551312", + "loggedType": { + "name": "", + "type": 14, + "typeArguments": [] + } + }, + { + "logId": "1889958695533330661", + "loggedType": { + "name": "", + "type": 15, + "typeArguments": [] + } + }, + { + "logId": "1134555198745859881", + "loggedType": { + "name": "", + "type": 24, + "typeArguments": [] + } + }, + { + "logId": "4883303303013154842", + "loggedType": { + "name": "", + "type": 19, + "typeArguments": [] + } + }, + { + "logId": "12970362301975156672", + "loggedType": { + "name": "", + "type": 21, + "typeArguments": [] + } + } + ], + "messagesTypes": [], + "configurables": [ + { + "name": "LOCAL_DOMAIN", + "configurableType": { + "name": "", + "type": 25, + "typeArguments": null + }, + "offset": 51792 + } + ] +} \ No newline at end of file diff --git a/rust/chains/hyperlane-fuel/build.rs b/rust/main/chains/hyperlane-fuel/build.rs similarity index 100% rename from rust/chains/hyperlane-fuel/build.rs rename to rust/main/chains/hyperlane-fuel/build.rs diff --git a/rust/chains/hyperlane-fuel/src/conversions.rs b/rust/main/chains/hyperlane-fuel/src/conversions.rs similarity index 93% rename from rust/chains/hyperlane-fuel/src/conversions.rs rename to rust/main/chains/hyperlane-fuel/src/conversions.rs index fb420b3ef..af16b8067 100644 --- a/rust/chains/hyperlane-fuel/src/conversions.rs +++ b/rust/main/chains/hyperlane-fuel/src/conversions.rs @@ -52,3 +52,9 @@ impl_h256!( |v| fuels::prelude::ContractId::new(v.0), |v| H256::from(<[u8; 32]>::from(v)) ); + +impl_h256!( + fuels::types::Bytes32, + |v| fuels::types::Bytes32::new(v.0), + |v| H256::from(*v) +); diff --git a/rust/chains/hyperlane-fuel/src/interchain_gas.rs b/rust/main/chains/hyperlane-fuel/src/interchain_gas.rs similarity index 100% rename from rust/chains/hyperlane-fuel/src/interchain_gas.rs rename to rust/main/chains/hyperlane-fuel/src/interchain_gas.rs diff --git a/rust/chains/hyperlane-fuel/src/lib.rs b/rust/main/chains/hyperlane-fuel/src/lib.rs similarity index 100% rename from rust/chains/hyperlane-fuel/src/lib.rs rename to rust/main/chains/hyperlane-fuel/src/lib.rs diff --git a/rust/main/chains/hyperlane-fuel/src/mailbox.rs b/rust/main/chains/hyperlane-fuel/src/mailbox.rs new file mode 100644 index 000000000..3df6bdc9e --- /dev/null +++ b/rust/main/chains/hyperlane-fuel/src/mailbox.rs @@ -0,0 +1,316 @@ +use crate::{ + contracts::mailbox::Mailbox as FuelMailboxInner, conversions::*, ConnectionConf, FuelProvider, +}; +use async_trait::async_trait; +use fuels::{ + prelude::{Bech32ContractId, WalletUnlocked}, + tx::{Receipt, ScriptExecutionResult}, + types::{transaction::TxPolicies, Bytes}, +}; +use hyperlane_core::{ + utils::bytes_to_hex, ChainCommunicationError, ChainResult, ContractLocator, HyperlaneAbi, + HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, + Indexed, Indexer, LogMeta, Mailbox, RawHyperlaneMessage, SequenceAwareIndexer, TxCostEstimate, + TxOutcome, H256, H512, U256, +}; +use std::{ + collections::HashMap, + fmt::{Debug, Formatter}, + num::NonZeroU64, + ops::RangeInclusive, +}; +use tracing::{instrument, warn}; + +/// A reference to a Mailbox contract on some Fuel chain +pub struct FuelMailbox { + contract: FuelMailboxInner, + provider: FuelProvider, + domain: HyperlaneDomain, +} + +impl FuelMailbox { + /// Create a new fuel mailbox + pub async fn new( + conf: &ConnectionConf, + locator: ContractLocator<'_>, + mut wallet: WalletUnlocked, + ) -> ChainResult { + let fuel_provider = FuelProvider::new(locator.domain.clone(), conf).await; + + wallet.set_provider(fuel_provider.provider().clone()); + let address = Bech32ContractId::from_h256(&locator.address); + + Ok(FuelMailbox { + contract: FuelMailboxInner::new(address, wallet), + domain: locator.domain.clone(), + provider: fuel_provider, + }) + } +} + +impl HyperlaneContract for FuelMailbox { + fn address(&self) -> H256 { + self.contract.contract_id().into_h256() + } +} + +impl HyperlaneChain for FuelMailbox { + fn domain(&self) -> &HyperlaneDomain { + &self.domain + } + + fn provider(&self) -> Box { + Box::new(self.provider.clone()) + } +} + +impl Debug for FuelMailbox { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self as &dyn HyperlaneContract) + } +} + +#[async_trait] +impl Mailbox for FuelMailbox { + #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn count(&self, lag: Option) -> ChainResult { + assert!( + lag.is_none(), + "Fuel does not support querying point-in-time" + ); + self.contract + .methods() + .nonce() + .simulate() + .await + .map(|r| r.value) + .map_err(ChainCommunicationError::from_other) + } + + #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn delivered(&self, id: H256) -> ChainResult { + self.contract + .methods() + .delivered(fuels::types::Bits256::from_h256(&id)) + .simulate() + .await + .map(|r| r.value) + .map_err(ChainCommunicationError::from_other) + } + + #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn default_ism(&self) -> ChainResult { + self.contract + .methods() + .default_ism() + .simulate() + .await + .map(|r| r.value.into_h256()) + .map_err(ChainCommunicationError::from_other) + } + + #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn recipient_ism(&self, recipient: H256) -> ChainResult { + self.contract + .methods() + .recipient_ism(Bech32ContractId::from_h256(&recipient)) + .simulate() + .await + .map(|r| r.value.into_h256()) + .map_err(ChainCommunicationError::from_other) + } + + #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn process( + &self, + message: &HyperlaneMessage, + metadata: &[u8], + tx_gas_limit: Option, + ) -> ChainResult { + // The max gas limit per transaction is 30000000 so it should always be safe to convert to u64 + let tx_policies = match tx_gas_limit { + Some(gas_limit) if gas_limit <= U256::from(u64::MAX) => { + match u64::try_from(gas_limit) { + Ok(parsed_gas_limit) => { + TxPolicies::default().with_script_gas_limit(parsed_gas_limit) + } + Err(_) => { + warn!("Failed to convert U256 to u64 during process call"); + TxPolicies::default() + } + } + } + _ => TxPolicies::default(), + }; + + let gas_price = self.provider.get_gas_price().await?; + + let call_res = self + .contract + .methods() + .process( + Bytes(metadata.to_vec()), + Bytes(RawHyperlaneMessage::from(message)), + ) + .with_tx_policies(tx_policies) + .determine_missing_contracts(Some(3)) + .await + .map_err(ChainCommunicationError::from_other)? + .call() + .await + .map_err(ChainCommunicationError::from_other)?; + + // Extract transaction success from the receipts + let success = call_res + .receipts + .iter() + .filter_map(|r| match r { + Receipt::ScriptResult { result, .. } => Some(result), + _ => None, + }) + .any(|result| matches!(result, ScriptExecutionResult::Success)); + + let tx_id = H512::from(call_res.tx_id.unwrap().into_h256()); + Ok(TxOutcome { + transaction_id: tx_id, + executed: success, + gas_used: call_res.gas_used.into(), + gas_price: gas_price.into(), + }) + } + + // Process cost of the `process` method + #[instrument(err, ret, skip(self), fields(msg=%message, metadata=%bytes_to_hex(metadata)))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn process_estimate_costs( + &self, + message: &HyperlaneMessage, + metadata: &[u8], + ) -> ChainResult { + let call_res = self + .contract + .methods() + .process( + Bytes(metadata.to_vec()), + Bytes(RawHyperlaneMessage::from(message)), + ) + .determine_missing_contracts(Some(3)) + .await + .map_err(ChainCommunicationError::from_other)? + .estimate_transaction_cost(None, None) + .await + .map_err(ChainCommunicationError::from_other)?; + + Ok(TxCostEstimate { + gas_limit: call_res.total_fee.into(), + gas_price: call_res.gas_price.into(), + l2_gas_limit: None, + }) + } + + fn process_calldata(&self, message: &HyperlaneMessage, metadata: &[u8]) -> Vec { + // Seems like this is not needed for Fuel, as it's only used in mocks + todo!() + } +} + +/// Struct that retrieves event data for a Fuel Mailbox contract +#[derive(Debug)] +pub struct FuelMailboxIndexer { + contract: FuelMailboxInner, + provider: FuelProvider, +} + +impl FuelMailboxIndexer { + /// Create a new FuelMailboxIndexer + pub async fn new( + conf: &ConnectionConf, + locator: ContractLocator<'_>, + wallet: WalletUnlocked, + ) -> ChainResult { + let fuel_provider = FuelProvider::new(locator.domain.clone(), conf).await; + + let address = Bech32ContractId::from_h256(&locator.address); + let contract = FuelMailboxInner::new(address, wallet); + + Ok(FuelMailboxIndexer { + contract, + provider: fuel_provider, + }) + } +} + +#[async_trait] +impl Indexer for FuelMailboxIndexer { + async fn fetch_logs_in_range( + &self, + range: RangeInclusive, + ) -> ChainResult, LogMeta)>> { + let mailbox_address = self.contract.contract_id().clone(); + self.provider + .index_logs_in_range(range, mailbox_address) + .await + } + + async fn get_finalized_block_number(&self) -> ChainResult { + self.provider.get_finalized_block_number().await + } +} + +#[async_trait] +impl Indexer for FuelMailboxIndexer { + async fn fetch_logs_in_range( + &self, + range: RangeInclusive, + ) -> ChainResult, LogMeta)>> { + todo!() // Needed for scraper + } + + async fn get_finalized_block_number(&self) -> ChainResult { + self.provider.get_finalized_block_number().await + } +} + +#[async_trait] +impl SequenceAwareIndexer for FuelMailboxIndexer { + async fn latest_sequence_count_and_tip(&self) -> ChainResult<(Option, u32)> { + let tip = Indexer::::get_finalized_block_number(&self).await?; + + // No sequence for message deliveries. + Ok((None, tip)) + } +} + +#[async_trait] +impl SequenceAwareIndexer for FuelMailboxIndexer { + #[allow(clippy::unnecessary_cast)] // TODO: `rustc` 1.80.1 clippy issue + async fn latest_sequence_count_and_tip(&self) -> ChainResult<(Option, u32)> { + let tip = Indexer::::get_finalized_block_number(&self).await?; + + self.contract + .methods() + .nonce() + .simulate() + .await + .map(|r| r.value) + .map_err(ChainCommunicationError::from_other) + .map(|sequence| (Some(sequence as u32), tip)) + } +} + +#[allow(dead_code)] // TODO: Remove this once the FuelMailboxAbi is implemented +struct FuelMailboxAbi; + +impl HyperlaneAbi for FuelMailboxAbi { + const SELECTOR_SIZE_BYTES: usize = 8; + + fn fn_map() -> HashMap, &'static str> { + // Can't support this without Fuels exporting it in the generated code + todo!() + } +} diff --git a/rust/chains/hyperlane-fuel/src/multisig_ism.rs b/rust/main/chains/hyperlane-fuel/src/multisig_ism.rs similarity index 100% rename from rust/chains/hyperlane-fuel/src/multisig_ism.rs rename to rust/main/chains/hyperlane-fuel/src/multisig_ism.rs diff --git a/rust/main/chains/hyperlane-fuel/src/provider.rs b/rust/main/chains/hyperlane-fuel/src/provider.rs new file mode 100644 index 000000000..e3836f141 --- /dev/null +++ b/rust/main/chains/hyperlane-fuel/src/provider.rs @@ -0,0 +1,409 @@ +use std::{collections::HashMap, ops::Deref}; + +use async_trait::async_trait; + +use fuels::{ + client::{FuelClient, PageDirection, PaginationRequest}, + prelude::Provider, + tx::Receipt, + types::{ + bech32::Bech32ContractId, + block::Block, + gas_price::LatestGasPrice, + transaction::{Transaction, TransactionType}, + transaction_response::TransactionResponse, + tx_status::TxStatus, + Address, Bytes32, ContractId, + }, +}; +use futures::future::join_all; +use hyperlane_core::{ + BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, + HyperlaneMessage, HyperlaneProvider, Indexed, LogMeta, TxnInfo, H256, H512, U256, +}; + +use crate::{make_client, make_provider, prelude::FuelIntoH256, ConnectionConf}; + +/// A wrapper around a fuel provider to get generic blockchain information. +#[derive(Debug, Clone)] +pub struct FuelProvider { + domain: HyperlaneDomain, + provider: Provider, + client: FuelClient, +} + +impl FuelProvider { + /// Create a new fuel provider + pub async fn new(domain: HyperlaneDomain, conf: &ConnectionConf) -> Self { + let provider = make_provider(conf).await.unwrap(); + let client = make_client(conf).unwrap(); + + Self { + domain, + provider, + client, + } + } + + /// Get the inner provider + pub fn provider(&self) -> &Provider { + &self.provider + } + + /// Get the latest gas price + pub async fn get_gas_price(&self) -> ChainResult { + let LatestGasPrice { gas_price, .. } = self + .provider() + .latest_gas_price() + .await + .map_err(ChainCommunicationError::from_other)?; + + Ok(gas_price) + } + + /// Check if a transaction is from a contract + /// @note: Only works for checking script transactions + /// Assumes that the first input is the contract id + #[allow(clippy::get_first)] // TODO: `rustc` 1.80.1 clippy issue + fn is_transaction_from_contract( + res: &TransactionResponse, + contract: &Bech32ContractId, + ) -> bool { + if let TransactionType::Script(script_transaction) = &res.transaction { + if script_transaction.inputs().get(0).is_some_and(|input| { + input + .contract_id() + .is_some_and(|id| id == &ContractId::from(&contract.into())) + }) { + return true; + } + } + false + } + + /// Check if a transaction is a call to the dispatch function of the Mailbox contract + #[allow(clippy::match_like_matches_macro)] // TODO: `rustc` 1.80.1 clippy issue + #[allow(clippy::into_iter_on_ref)] // TODO: `rustc` 1.80.1 clippy issue + fn is_dispatch_call(res: &TransactionResponse) -> bool { + // let selector = encode_fn_selector("dispatch"); + // println!("selector: {:?}", selector); // XXX see if we can get the correct txn by selector + // Apparently we should be able to see it in the call logs + + let receipts = match &res.status { + TxStatus::Success { receipts } => receipts, + _ => return false, + }; + let log_data_receipts = receipts + .into_iter() + .filter(|rec| { + // if let Receipt::Call { param1, param2, .. } = rec { + // print!( + // "param1: {:?}, param2: {:?}", + // param1.to_be_bytes(), + // param2.to_be_bytes() + // ); + // } + + match rec { + Receipt::LogData { .. } => true, + _ => false, + } + }) + .collect::>(); + + // Dispatch is the only call that has 2 log data receipts + match log_data_receipts.len() { + 2 => true, + _ => false, + } + } + + #[allow(clippy::clone_on_copy)] // TODO: `rustc` 1.80.1 clippy issue + async fn get_block_data( + &self, + range: std::ops::RangeInclusive, + ) -> ChainResult<(Vec, HashMap)> { + let result_amount = range.end() - range.start() + 1; + let req = PaginationRequest { + cursor: Some(range.start().to_string()), + results: i32::try_from(result_amount).expect("Invalid range"), + direction: PageDirection::Forward, + }; + + let blocks = self + .provider + .get_blocks(req) + .await + .map_err(ChainCommunicationError::from_other)?; + + let mut transaction_map: HashMap = HashMap::new(); + blocks.results.iter().for_each(|block| { + block + .transactions + .iter() + .enumerate() + .for_each(|(index, tx)| { + transaction_map.insert(tx.clone(), (block.id, index as u64)); + }); + }); + Ok((blocks.results, transaction_map)) + } + + /// Get the finalized block number + /// XXX might be inaccurate as we do not know the block finality + pub async fn get_finalized_block_number(&self) -> ChainResult { + self.provider + .latest_block_height() + .await + .map_err(ChainCommunicationError::from_other) + } + + /// index logs in a range + #[allow(clippy::clone_on_copy)] // TODO: `rustc` 1.80.1 clippy issue + #[allow(clippy::manual_map)] // TODO: `rustc` 1.80.1 clippy issue + #[allow(clippy::into_iter_on_ref)] // TODO: `rustc` 1.80.1 clippy issue + #[allow(clippy::needless_borrow)] // TODO: `rustc` 1.80.1 clippy issue + pub async fn index_logs_in_range( + &self, + range: std::ops::RangeInclusive, + mailbox_contract: Bech32ContractId, + ) -> ChainResult, LogMeta)>> { + let (blocks, transaction_map) = self.get_block_data(range.clone()).await.unwrap(); + + // Transaction ids from selected blocks + let transaction_ids = blocks + .into_iter() + .map(|block| block.transactions) + .flat_map(|txs| txs.into_iter()) + .collect::>(); + + let futures = transaction_ids + .into_iter() + .map(|tx_id| { + let provider = self.provider.clone(); + let tx_clone = tx_id.clone(); + async move { + let result = provider.get_transaction_by_id(&tx_id).await.unwrap(); + (tx_clone, result) + } + }) + .collect::>(); + + // Filter transactions + // 1. Transaction type is Script + // 2. Transaction status is Success + // 3. Transaction is from mailbox contract + // 4. Transaction is a dispatch call + // 5. Transaction data is valid + let transaction_data = join_all(futures) + .await + .into_iter() + .filter_map(|(tx_id, tx_data)| match tx_data { + Some(tx_data) => Some((tx_id, tx_data)), + _ => None, + }) + .filter(|(_, tx_data)| { + matches!(tx_data.transaction, TransactionType::Script(_)) + && matches!(tx_data.status, TxStatus::Success { .. }) + && Self::is_transaction_from_contract(&tx_data, &mailbox_contract) + && Self::is_dispatch_call(&tx_data) + }) + .collect::>(); + + // Full data needed to construct the logs + let full_tx_data = transaction_data + .into_iter() + .filter_map(|(tx_id, tx_data)| { + let receipts = match &tx_data.status { + TxStatus::Success { receipts } => receipts, + _ => return None, + }; + + let (log_index, mut receipt_log_data) = receipts + .into_iter() + .enumerate() + .filter_map(|(log_index, rec)| { + // We only care about LogData receipts with data length greater than 32 bytes + match rec { + Receipt::LogData { .. } + if rec.data().is_some_and(|data| data.len() > 32) => + { + let data = rec.data().map(|data| data.to_owned()); + + match data { + Some(data) => Some((U256::from(log_index), data)), + _ => None, + } + } + _ => None, + } + }) + .next()?; // Each dispatch call should have only one log data receipt + + if !receipt_log_data.is_empty() { + // We cut out the message id, recipient and domain which are encoded in the first 76 bytes + receipt_log_data.drain(0..76); + let encoded_message = HyperlaneMessage::from(receipt_log_data); + Some((tx_id, tx_data, encoded_message, log_index)) + } else { + None + } + }) + .collect::>(); // Collect all Vec from each transaction into a Vec> + + let indexed_logs: Vec<(Indexed, LogMeta)> = full_tx_data + .into_iter() + .map(|(tx_id, tx, message, log_index)| { + let (block_hash, transaction_index) = transaction_map.get(&tx_id).unwrap(); + + let log_meta = LogMeta { + address: mailbox_contract.clone().into_h256(), + block_number: *tx.block_height.unwrap().deref() as u64, + block_hash: block_hash.into_h256(), + transaction_id: H512::from(tx_id.into_h256()), + transaction_index: transaction_index.clone(), + log_index, + }; + (message.into(), log_meta) + }) + .collect::>(); + Ok(indexed_logs) + } +} + +impl HyperlaneChain for FuelProvider { + fn domain(&self) -> &HyperlaneDomain { + &self.domain + } + + fn provider(&self) -> Box { + Box::new(self.clone()) + } +} + +#[async_trait] +impl HyperlaneProvider for FuelProvider { + /// Used by scraper + #[allow(clippy::clone_on_copy)] // TODO: `rustc` 1.80.1 clippy issue + async fn get_block_by_hash(&self, hash: &H256) -> ChainResult { + let block_res = self.provider.block(&hash.0.into()).await.map_err(|e| { + ChainCommunicationError::CustomError(format!("Failed to get block: {}", e)) + })?; + + match block_res { + Some(block) => Ok(BlockInfo { + hash: H256::from_slice(block.id.as_slice()), + number: block.header.height.into(), + timestamp: block.header.time.map_or(0, |t| t.timestamp() as u64), + }), + None => Err(ChainCommunicationError::BlockNotFound(hash.clone())), + } + } + + /// Used by scraper + #[allow(clippy::clone_on_copy)] // TODO: `rustc` 1.80.1 clippy issue + #[allow(clippy::match_like_matches_macro)] // TODO: `rustc` 1.80.1 clippy issue + async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult { + let transaction_res = self + .provider + .get_transaction_by_id(&hash.0.into()) + .await + .map_err(|e| { + ChainCommunicationError::CustomError(format!("Failed to get transaction: {}", e)) + })?; + + match transaction_res { + Some(transaction) => { + let block_number = transaction.block_height.unwrap(); + + let gas_price = self + .provider + .estimate_gas_price(block_number.into()) + .await + .map_or(0, |estimate| estimate.gas_price); + + let gas_limit = match transaction.transaction { + TransactionType::Script(tx) => tx.gas_limit(), + _ => 0, + }; + + let (sender, recipient, nonce) = match transaction.status { + TxStatus::Success { receipts } => { + let valid_receipt = receipts.into_iter().find(|receipt| match receipt { + Receipt::MessageOut { .. } => true, + _ => false, + }); + + match valid_receipt { + Some(Receipt::MessageOut { + sender, + recipient, + nonce, + .. + }) => { + let mut arr = [0u8; 8]; + let nonce_bytes = <[u8; 32]>::from(nonce); + arr.copy_from_slice(&nonce_bytes[0..8]); + let parsed_nonce = u64::from_be_bytes(arr); + + ( + <[u8; 32]>::from(sender).into(), + Some(<[u8; 32]>::from(recipient).into()), + parsed_nonce, + ) + } + _ => (H256::zero(), None, 0), + } + } + _ => (H256::zero(), None, 0), + }; + + Ok(TxnInfo { + hash: hash.clone(), + gas_limit: gas_limit.into(), + max_priority_fee_per_gas: None, + max_fee_per_gas: None, + nonce, + sender, + gas_price: Some(gas_price.into()), + recipient, + receipt: None, + }) + } + None => Err(ChainCommunicationError::CustomError(format!( + "Transaction not found: {}", + hash + ))), + } + } + + async fn is_contract(&self, address: &H256) -> ChainResult { + let contract_res = self.client.contract(&ContractId::from(address.0)).await; + + match contract_res { + Ok(contract) => Ok(contract.is_some()), + Err(e) => Err(ChainCommunicationError::CustomError(format!( + "Failed to get contract: {}", + e + ))), + } + } + + async fn get_balance(&self, address: String) -> ChainResult { + let base = self.provider.base_asset_id(); + let asset = *Address::from_bytes_ref_checked(address.as_bytes()).expect("Invalid address"); + + self.provider + .get_asset_balance(&asset.into(), *base) + .await + .map(|balance| Ok(U256::from(balance))) + .map_err(|e| { + ChainCommunicationError::CustomError(format!("Failed to get balance: {}", e)) + })? + } + + /// Used by hyperlane base metrics (scraper) + async fn get_chain_metrics(&self) -> ChainResult> { + Ok(None) + } +} diff --git a/rust/chains/hyperlane-fuel/src/routing_ism.rs b/rust/main/chains/hyperlane-fuel/src/routing_ism.rs similarity index 100% rename from rust/chains/hyperlane-fuel/src/routing_ism.rs rename to rust/main/chains/hyperlane-fuel/src/routing_ism.rs diff --git a/rust/chains/hyperlane-fuel/src/trait_builder.rs b/rust/main/chains/hyperlane-fuel/src/trait_builder.rs similarity index 79% rename from rust/chains/hyperlane-fuel/src/trait_builder.rs rename to rust/main/chains/hyperlane-fuel/src/trait_builder.rs index b056a17ee..b9efd9060 100644 --- a/rust/chains/hyperlane-fuel/src/trait_builder.rs +++ b/rust/main/chains/hyperlane-fuel/src/trait_builder.rs @@ -30,11 +30,14 @@ impl From for ChainCommunicationError { } } -fn make_client(conf: &ConnectionConf) -> ChainResult { +/// Create a new Fuel client +pub fn make_client(conf: &ConnectionConf) -> ChainResult { FuelClient::new(&conf.url).map_err(|e| FuelNewConnectionError(e).into()) } /// Create a new fuel provider and connection -pub fn make_provider(conf: &ConnectionConf) -> ChainResult { - Ok(Provider::new(make_client(conf)?)) +pub async fn make_provider(conf: &ConnectionConf) -> ChainResult { + Provider::connect(&conf.url) + .await + .map_err(|e| FuelNewConnectionError(e.into()).into()) } diff --git a/rust/chains/hyperlane-fuel/src/validator_announce.rs b/rust/main/chains/hyperlane-fuel/src/validator_announce.rs similarity index 100% rename from rust/chains/hyperlane-fuel/src/validator_announce.rs rename to rust/main/chains/hyperlane-fuel/src/validator_announce.rs diff --git a/rust/main/chains/hyperlane-sealevel/Cargo.toml b/rust/main/chains/hyperlane-sealevel/Cargo.toml new file mode 100644 index 000000000..8179ff94c --- /dev/null +++ b/rust/main/chains/hyperlane-sealevel/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "hyperlane-sealevel" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow.workspace = true +async-trait.workspace = true +base64.workspace = true +borsh.workspace = true +derive-new.workspace = true +jsonrpc-core.workspace = true +num-traits.workspace = true +serde.workspace = true +solana-account-decoder.workspace = true +solana-client.workspace = true +solana-sdk.workspace = true +solana-transaction-status.workspace = true +thiserror.workspace = true +tracing-futures.workspace = true +tracing.workspace = true +url.workspace = true + +account-utils = { path = "../../../sealevel/libraries/account-utils" } +hyperlane-core = { path = "../../hyperlane-core", features = [ + "solana", + "async", +] } +hyperlane-sealevel-interchain-security-module-interface = { path = "../../../sealevel/libraries/interchain-security-module-interface" } +hyperlane-sealevel-mailbox = { path = "../../../sealevel/programs/mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../../../sealevel/programs/hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-message-recipient-interface = { path = "../../../sealevel/libraries/message-recipient-interface" } +hyperlane-sealevel-multisig-ism-message-id = { path = "../../../sealevel/programs/ism/multisig-ism-message-id", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-validator-announce = { path = "../../../sealevel/programs/validator-announce", features = [ + "no-entrypoint", +] } +multisig-ism = { path = "../../../sealevel/libraries/multisig-ism" } +serializable-account-meta = { path = "../../../sealevel/libraries/serializable-account-meta" } diff --git a/rust/chains/hyperlane-sealevel/src/client.rs b/rust/main/chains/hyperlane-sealevel/src/client.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/client.rs rename to rust/main/chains/hyperlane-sealevel/src/client.rs diff --git a/rust/chains/hyperlane-sealevel/src/error.rs b/rust/main/chains/hyperlane-sealevel/src/error.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/error.rs rename to rust/main/chains/hyperlane-sealevel/src/error.rs diff --git a/rust/chains/hyperlane-sealevel/src/interchain_gas.rs b/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs similarity index 98% rename from rust/chains/hyperlane-sealevel/src/interchain_gas.rs rename to rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs index beebcb9db..8c0972c9a 100644 --- a/rust/chains/hyperlane-sealevel/src/interchain_gas.rs +++ b/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs @@ -245,6 +245,7 @@ impl SealevelInterchainGasPaymasterIndexer { #[async_trait] impl Indexer for SealevelInterchainGasPaymasterIndexer { + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue #[instrument(err, skip(self))] async fn fetch_logs_in_range( &self, @@ -271,6 +272,7 @@ impl Indexer for SealevelInterchainGasPaymasterIndexer { } #[instrument(level = "debug", err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { get_finalized_block_number(&self.rpc_client).await } @@ -279,6 +281,7 @@ impl Indexer for SealevelInterchainGasPaymasterIndexer { #[async_trait] impl SequenceAwareIndexer for SealevelInterchainGasPaymasterIndexer { #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn latest_sequence_count_and_tip(&self) -> ChainResult<(Option, u32)> { let program_data_account = self .rpc_client diff --git a/rust/chains/hyperlane-sealevel/src/interchain_security_module.rs b/rust/main/chains/hyperlane-sealevel/src/interchain_security_module.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/interchain_security_module.rs rename to rust/main/chains/hyperlane-sealevel/src/interchain_security_module.rs diff --git a/rust/chains/hyperlane-sealevel/src/lib.rs b/rust/main/chains/hyperlane-sealevel/src/lib.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/lib.rs rename to rust/main/chains/hyperlane-sealevel/src/lib.rs diff --git a/rust/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/mailbox.rs rename to rust/main/chains/hyperlane-sealevel/src/mailbox.rs diff --git a/rust/chains/hyperlane-sealevel/src/merkle_tree_hook.rs b/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs similarity index 94% rename from rust/chains/hyperlane-sealevel/src/merkle_tree_hook.rs rename to rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs index 8c1132add..3778627b2 100644 --- a/rust/chains/hyperlane-sealevel/src/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs @@ -16,6 +16,7 @@ use crate::{SealevelMailbox, SealevelMailboxIndexer}; #[async_trait] impl MerkleTreeHook for SealevelMailbox { #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn tree(&self, lag: Option) -> ChainResult { assert!( lag.is_none(), @@ -39,6 +40,7 @@ impl MerkleTreeHook for SealevelMailbox { } #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn latest_checkpoint(&self, lag: Option) -> ChainResult { assert!( lag.is_none(), @@ -67,6 +69,7 @@ impl MerkleTreeHook for SealevelMailbox { } #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn count(&self, _maybe_lag: Option) -> ChainResult { let tree = self.tree(_maybe_lag).await?; diff --git a/rust/chains/hyperlane-sealevel/src/multisig_ism.rs b/rust/main/chains/hyperlane-sealevel/src/multisig_ism.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/multisig_ism.rs rename to rust/main/chains/hyperlane-sealevel/src/multisig_ism.rs diff --git a/rust/chains/hyperlane-sealevel/src/provider.rs b/rust/main/chains/hyperlane-sealevel/src/provider.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/provider.rs rename to rust/main/chains/hyperlane-sealevel/src/provider.rs diff --git a/rust/chains/hyperlane-sealevel/src/trait_builder.rs b/rust/main/chains/hyperlane-sealevel/src/trait_builder.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/trait_builder.rs rename to rust/main/chains/hyperlane-sealevel/src/trait_builder.rs diff --git a/rust/chains/hyperlane-sealevel/src/utils.rs b/rust/main/chains/hyperlane-sealevel/src/utils.rs similarity index 100% rename from rust/chains/hyperlane-sealevel/src/utils.rs rename to rust/main/chains/hyperlane-sealevel/src/utils.rs diff --git a/rust/chains/hyperlane-sealevel/src/validator_announce.rs b/rust/main/chains/hyperlane-sealevel/src/validator_announce.rs similarity index 98% rename from rust/chains/hyperlane-sealevel/src/validator_announce.rs rename to rust/main/chains/hyperlane-sealevel/src/validator_announce.rs index 9d22eb68c..52b19495a 100644 --- a/rust/chains/hyperlane-sealevel/src/validator_announce.rs +++ b/rust/main/chains/hyperlane-sealevel/src/validator_announce.rs @@ -116,6 +116,7 @@ impl ValidatorAnnounce for SealevelValidatorAnnounce { } #[instrument(err, ret, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn announce(&self, _announcement: SignedType) -> ChainResult { warn!( "Announcing validator storage locations within the agents is not supported on Sealevel" diff --git a/rust/config/mainnet_config.json b/rust/main/config/mainnet_config.json similarity index 100% rename from rust/config/mainnet_config.json rename to rust/main/config/mainnet_config.json diff --git a/rust/config/test-sealevel-keys/test_deployer-account.json b/rust/main/config/test-sealevel-keys/test_deployer-account.json similarity index 100% rename from rust/config/test-sealevel-keys/test_deployer-account.json rename to rust/main/config/test-sealevel-keys/test_deployer-account.json diff --git a/rust/config/test-sealevel-keys/test_deployer-keypair.json b/rust/main/config/test-sealevel-keys/test_deployer-keypair.json similarity index 100% rename from rust/config/test-sealevel-keys/test_deployer-keypair.json rename to rust/main/config/test-sealevel-keys/test_deployer-keypair.json diff --git a/rust/config/test_sealevel_config.json b/rust/main/config/test_sealevel_config.json similarity index 100% rename from rust/config/test_sealevel_config.json rename to rust/main/config/test_sealevel_config.json diff --git a/rust/config/testnet_config.json b/rust/main/config/testnet_config.json similarity index 100% rename from rust/config/testnet_config.json rename to rust/main/config/testnet_config.json diff --git a/rust/ethers-prometheus/.gitignore b/rust/main/ethers-prometheus/.gitignore similarity index 100% rename from rust/ethers-prometheus/.gitignore rename to rust/main/ethers-prometheus/.gitignore diff --git a/rust/ethers-prometheus/Cargo.toml b/rust/main/ethers-prometheus/Cargo.toml similarity index 95% rename from rust/ethers-prometheus/Cargo.toml rename to rust/main/ethers-prometheus/Cargo.toml index 2f4344fa5..3d2e74d6d 100644 --- a/rust/ethers-prometheus/Cargo.toml +++ b/rust/main/ethers-prometheus/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "ethers-prometheus" documentation.workspace = true diff --git a/rust/ethers-prometheus/abis/Erc20.abi.json b/rust/main/ethers-prometheus/abis/Erc20.abi.json similarity index 100% rename from rust/ethers-prometheus/abis/Erc20.abi.json rename to rust/main/ethers-prometheus/abis/Erc20.abi.json diff --git a/rust/ethers-prometheus/build.rs b/rust/main/ethers-prometheus/build.rs similarity index 100% rename from rust/ethers-prometheus/build.rs rename to rust/main/ethers-prometheus/build.rs diff --git a/rust/ethers-prometheus/src/json_rpc_client.rs b/rust/main/ethers-prometheus/src/json_rpc_client.rs similarity index 100% rename from rust/ethers-prometheus/src/json_rpc_client.rs rename to rust/main/ethers-prometheus/src/json_rpc_client.rs diff --git a/rust/ethers-prometheus/src/lib.rs b/rust/main/ethers-prometheus/src/lib.rs similarity index 100% rename from rust/ethers-prometheus/src/lib.rs rename to rust/main/ethers-prometheus/src/lib.rs diff --git a/rust/ethers-prometheus/src/middleware/error.rs b/rust/main/ethers-prometheus/src/middleware/error.rs similarity index 100% rename from rust/ethers-prometheus/src/middleware/error.rs rename to rust/main/ethers-prometheus/src/middleware/error.rs diff --git a/rust/ethers-prometheus/src/middleware/mod.rs b/rust/main/ethers-prometheus/src/middleware/mod.rs similarity index 99% rename from rust/ethers-prometheus/src/middleware/mod.rs rename to rust/main/ethers-prometheus/src/middleware/mod.rs index 592e6a200..cb3fd16cf 100644 --- a/rust/ethers-prometheus/src/middleware/mod.rs +++ b/rust/main/ethers-prometheus/src/middleware/mod.rs @@ -335,10 +335,9 @@ impl Middleware for PrometheusMiddleware { .inc_by((Instant::now() - start).as_secs_f64()); } } - Ok(result?) } - + #[allow(clippy::redundant_closure)] // TODO: `rustc` 1.80.1 clippy issue async fn get_logs(&self, filter: &Filter) -> Result, Self::Error> { let start = Instant::now(); let result = self.inner.get_logs(filter).await; diff --git a/rust/helm/agent-common/Chart.yaml b/rust/main/helm/agent-common/Chart.yaml similarity index 100% rename from rust/helm/agent-common/Chart.yaml rename to rust/main/helm/agent-common/Chart.yaml diff --git a/rust/helm/agent-common/templates/_helpers.tpl b/rust/main/helm/agent-common/templates/_helpers.tpl similarity index 100% rename from rust/helm/agent-common/templates/_helpers.tpl rename to rust/main/helm/agent-common/templates/_helpers.tpl diff --git a/rust/helm/hyperlane-agent/.helmignore b/rust/main/helm/hyperlane-agent/.helmignore similarity index 100% rename from rust/helm/hyperlane-agent/.helmignore rename to rust/main/helm/hyperlane-agent/.helmignore diff --git a/rust/helm/hyperlane-agent/Chart.lock b/rust/main/helm/hyperlane-agent/Chart.lock similarity index 100% rename from rust/helm/hyperlane-agent/Chart.lock rename to rust/main/helm/hyperlane-agent/Chart.lock diff --git a/rust/helm/hyperlane-agent/Chart.yaml b/rust/main/helm/hyperlane-agent/Chart.yaml similarity index 100% rename from rust/helm/hyperlane-agent/Chart.yaml rename to rust/main/helm/hyperlane-agent/Chart.yaml diff --git a/rust/helm/hyperlane-agent/templates/NOTES.txt b/rust/main/helm/hyperlane-agent/templates/NOTES.txt similarity index 100% rename from rust/helm/hyperlane-agent/templates/NOTES.txt rename to rust/main/helm/hyperlane-agent/templates/NOTES.txt diff --git a/rust/helm/hyperlane-agent/templates/_helpers.tpl b/rust/main/helm/hyperlane-agent/templates/_helpers.tpl similarity index 100% rename from rust/helm/hyperlane-agent/templates/_helpers.tpl rename to rust/main/helm/hyperlane-agent/templates/_helpers.tpl diff --git a/rust/helm/hyperlane-agent/templates/configmap.yaml b/rust/main/helm/hyperlane-agent/templates/configmap.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/configmap.yaml rename to rust/main/helm/hyperlane-agent/templates/configmap.yaml diff --git a/rust/helm/hyperlane-agent/templates/external-secret.yaml b/rust/main/helm/hyperlane-agent/templates/external-secret.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/external-secret.yaml rename to rust/main/helm/hyperlane-agent/templates/external-secret.yaml diff --git a/rust/helm/hyperlane-agent/templates/relayer-external-secret.yaml b/rust/main/helm/hyperlane-agent/templates/relayer-external-secret.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/relayer-external-secret.yaml rename to rust/main/helm/hyperlane-agent/templates/relayer-external-secret.yaml diff --git a/rust/helm/hyperlane-agent/templates/relayer-statefulset.yaml b/rust/main/helm/hyperlane-agent/templates/relayer-statefulset.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/relayer-statefulset.yaml rename to rust/main/helm/hyperlane-agent/templates/relayer-statefulset.yaml diff --git a/rust/helm/hyperlane-agent/templates/scraper-external-secret.yaml b/rust/main/helm/hyperlane-agent/templates/scraper-external-secret.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/scraper-external-secret.yaml rename to rust/main/helm/hyperlane-agent/templates/scraper-external-secret.yaml diff --git a/rust/helm/hyperlane-agent/templates/scraper-statefulset.yaml b/rust/main/helm/hyperlane-agent/templates/scraper-statefulset.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/scraper-statefulset.yaml rename to rust/main/helm/hyperlane-agent/templates/scraper-statefulset.yaml diff --git a/rust/helm/hyperlane-agent/templates/serviceaccount.yaml b/rust/main/helm/hyperlane-agent/templates/serviceaccount.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/serviceaccount.yaml rename to rust/main/helm/hyperlane-agent/templates/serviceaccount.yaml diff --git a/rust/helm/hyperlane-agent/templates/validator-configmap.yaml b/rust/main/helm/hyperlane-agent/templates/validator-configmap.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/validator-configmap.yaml rename to rust/main/helm/hyperlane-agent/templates/validator-configmap.yaml diff --git a/rust/helm/hyperlane-agent/templates/validator-external-secret.yaml b/rust/main/helm/hyperlane-agent/templates/validator-external-secret.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/validator-external-secret.yaml rename to rust/main/helm/hyperlane-agent/templates/validator-external-secret.yaml diff --git a/rust/helm/hyperlane-agent/templates/validator-statefulset.yaml b/rust/main/helm/hyperlane-agent/templates/validator-statefulset.yaml similarity index 100% rename from rust/helm/hyperlane-agent/templates/validator-statefulset.yaml rename to rust/main/helm/hyperlane-agent/templates/validator-statefulset.yaml diff --git a/rust/helm/hyperlane-agent/values.yaml b/rust/main/helm/hyperlane-agent/values.yaml similarity index 100% rename from rust/helm/hyperlane-agent/values.yaml rename to rust/main/helm/hyperlane-agent/values.yaml diff --git a/rust/hyperlane-base/Cargo.toml b/rust/main/hyperlane-base/Cargo.toml similarity index 95% rename from rust/hyperlane-base/Cargo.toml rename to rust/main/hyperlane-base/Cargo.toml index 471815f69..5bfe50c6e 100644 --- a/rust/hyperlane-base/Cargo.toml +++ b/rust/main/hyperlane-base/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "hyperlane-base" documentation.workspace = true @@ -54,7 +52,7 @@ hyperlane-core = { path = "../hyperlane-core", features = ["agent", "float"] } hyperlane-ethereum = { path = "../chains/hyperlane-ethereum" } hyperlane-fuel = { path = "../chains/hyperlane-fuel" } hyperlane-sealevel = { path = "../chains/hyperlane-sealevel" } -hyperlane-cosmos = { path = "../chains/hyperlane-cosmos"} +hyperlane-cosmos = { path = "../chains/hyperlane-cosmos" } hyperlane-test = { path = "../hyperlane-test" } # dependency version is determined by etheres diff --git a/rust/hyperlane-base/build.rs b/rust/main/hyperlane-base/build.rs similarity index 100% rename from rust/hyperlane-base/build.rs rename to rust/main/hyperlane-base/build.rs diff --git a/rust/hyperlane-base/src/agent.rs b/rust/main/hyperlane-base/src/agent.rs similarity index 98% rename from rust/hyperlane-base/src/agent.rs rename to rust/main/hyperlane-base/src/agent.rs index 8bd696ccf..0ca9f4554 100644 --- a/rust/hyperlane-base/src/agent.rs +++ b/rust/main/hyperlane-base/src/agent.rs @@ -60,6 +60,7 @@ pub trait BaseAgent: Send + Sync + Debug { /// Call this from `main` to fully initialize and run the agent for its entire /// lifecycle. This assumes only a single agent is being run. This will /// initialize the metrics server and tracing as well. +#[allow(unexpected_cfgs)] // TODO: `rustc` 1.80.1 clippy issue pub async fn agent_main() -> Result<()> { if env::var("ONELINE_BACKTRACES") .map(|v| v.to_lowercase()) diff --git a/rust/hyperlane-base/src/contract_sync/broadcast.rs b/rust/main/hyperlane-base/src/contract_sync/broadcast.rs similarity index 100% rename from rust/hyperlane-base/src/contract_sync/broadcast.rs rename to rust/main/hyperlane-base/src/contract_sync/broadcast.rs diff --git a/rust/hyperlane-base/src/contract_sync/cursors/mod.rs b/rust/main/hyperlane-base/src/contract_sync/cursors/mod.rs similarity index 100% rename from rust/hyperlane-base/src/contract_sync/cursors/mod.rs rename to rust/main/hyperlane-base/src/contract_sync/cursors/mod.rs diff --git a/rust/hyperlane-base/src/contract_sync/cursors/rate_limited.rs b/rust/main/hyperlane-base/src/contract_sync/cursors/rate_limited.rs similarity index 100% rename from rust/hyperlane-base/src/contract_sync/cursors/rate_limited.rs rename to rust/main/hyperlane-base/src/contract_sync/cursors/rate_limited.rs diff --git a/rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/backward.rs b/rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/backward.rs similarity index 99% rename from rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/backward.rs rename to rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/backward.rs index 6a0f66a78..75c086c24 100644 --- a/rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/backward.rs +++ b/rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/backward.rs @@ -358,6 +358,7 @@ impl ContractSyncCursor /// The logs to ingest. If any logs are duplicated or their sequence is higher than the current indexing snapshot, /// they are filtered out. #[instrument(err, ret, skip(logs), fields(range=?range, logs=?logs.iter().map(|(log, _)| log.sequence).collect::>()))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn update( &mut self, logs: Vec<(Indexed, LogMeta)>, diff --git a/rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/forward.rs b/rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/forward.rs similarity index 99% rename from rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/forward.rs rename to rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/forward.rs index ae6629e95..4fcbbff8d 100644 --- a/rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/forward.rs +++ b/rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/forward.rs @@ -438,6 +438,7 @@ impl ContractSyncCursor /// This means that while gaps result in a rewind here, already known logs may be "fast forwarded" through, /// and the cursor won't actually end up re-indexing already known logs. #[instrument(err, ret, skip(logs), fields(range=?range, logs=?logs.iter().map(|(log, _)| log.sequence).collect::>()))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn update( &mut self, logs: Vec<(Indexed, LogMeta)>, diff --git a/rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/mod.rs b/rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/mod.rs similarity index 100% rename from rust/hyperlane-base/src/contract_sync/cursors/sequence_aware/mod.rs rename to rust/main/hyperlane-base/src/contract_sync/cursors/sequence_aware/mod.rs diff --git a/rust/hyperlane-base/src/contract_sync/eta_calculator.rs b/rust/main/hyperlane-base/src/contract_sync/eta_calculator.rs similarity index 100% rename from rust/hyperlane-base/src/contract_sync/eta_calculator.rs rename to rust/main/hyperlane-base/src/contract_sync/eta_calculator.rs diff --git a/rust/hyperlane-base/src/contract_sync/metrics.rs b/rust/main/hyperlane-base/src/contract_sync/metrics.rs similarity index 100% rename from rust/hyperlane-base/src/contract_sync/metrics.rs rename to rust/main/hyperlane-base/src/contract_sync/metrics.rs diff --git a/rust/hyperlane-base/src/contract_sync/mod.rs b/rust/main/hyperlane-base/src/contract_sync/mod.rs similarity index 100% rename from rust/hyperlane-base/src/contract_sync/mod.rs rename to rust/main/hyperlane-base/src/contract_sync/mod.rs diff --git a/rust/hyperlane-base/src/db/mod.rs b/rust/main/hyperlane-base/src/db/mod.rs similarity index 100% rename from rust/hyperlane-base/src/db/mod.rs rename to rust/main/hyperlane-base/src/db/mod.rs diff --git a/rust/hyperlane-base/src/db/rocks/hyperlane_db.rs b/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs similarity index 100% rename from rust/hyperlane-base/src/db/rocks/hyperlane_db.rs rename to rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs diff --git a/rust/hyperlane-base/src/db/rocks/iterator.rs b/rust/main/hyperlane-base/src/db/rocks/iterator.rs similarity index 100% rename from rust/hyperlane-base/src/db/rocks/iterator.rs rename to rust/main/hyperlane-base/src/db/rocks/iterator.rs diff --git a/rust/hyperlane-base/src/db/rocks/mod.rs b/rust/main/hyperlane-base/src/db/rocks/mod.rs similarity index 100% rename from rust/hyperlane-base/src/db/rocks/mod.rs rename to rust/main/hyperlane-base/src/db/rocks/mod.rs diff --git a/rust/hyperlane-base/src/db/rocks/storage_types.rs b/rust/main/hyperlane-base/src/db/rocks/storage_types.rs similarity index 100% rename from rust/hyperlane-base/src/db/rocks/storage_types.rs rename to rust/main/hyperlane-base/src/db/rocks/storage_types.rs diff --git a/rust/hyperlane-base/src/db/rocks/test_utils.rs b/rust/main/hyperlane-base/src/db/rocks/test_utils.rs similarity index 100% rename from rust/hyperlane-base/src/db/rocks/test_utils.rs rename to rust/main/hyperlane-base/src/db/rocks/test_utils.rs diff --git a/rust/hyperlane-base/src/db/rocks/typed_db.rs b/rust/main/hyperlane-base/src/db/rocks/typed_db.rs similarity index 100% rename from rust/hyperlane-base/src/db/rocks/typed_db.rs rename to rust/main/hyperlane-base/src/db/rocks/typed_db.rs diff --git a/rust/hyperlane-base/src/lib.rs b/rust/main/hyperlane-base/src/lib.rs similarity index 100% rename from rust/hyperlane-base/src/lib.rs rename to rust/main/hyperlane-base/src/lib.rs diff --git a/rust/hyperlane-base/src/metadata.rs b/rust/main/hyperlane-base/src/metadata.rs similarity index 100% rename from rust/hyperlane-base/src/metadata.rs rename to rust/main/hyperlane-base/src/metadata.rs diff --git a/rust/hyperlane-base/src/metrics/agent_metrics.rs b/rust/main/hyperlane-base/src/metrics/agent_metrics.rs similarity index 99% rename from rust/hyperlane-base/src/metrics/agent_metrics.rs rename to rust/main/hyperlane-base/src/metrics/agent_metrics.rs index 14e233629..4ece5b0e3 100644 --- a/rust/hyperlane-base/src/metrics/agent_metrics.rs +++ b/rust/main/hyperlane-base/src/metrics/agent_metrics.rs @@ -1,4 +1,5 @@ //! Metrics either related to the agents, or observed by them +#![allow(unexpected_cfgs)] // TODO: `rustc` 1.80.1 clippy issue use std::sync::Arc; use std::time::Duration; diff --git a/rust/hyperlane-base/src/metrics/core.rs b/rust/main/hyperlane-base/src/metrics/core.rs similarity index 100% rename from rust/hyperlane-base/src/metrics/core.rs rename to rust/main/hyperlane-base/src/metrics/core.rs diff --git a/rust/hyperlane-base/src/metrics/json_rpc_client.rs b/rust/main/hyperlane-base/src/metrics/json_rpc_client.rs similarity index 100% rename from rust/hyperlane-base/src/metrics/json_rpc_client.rs rename to rust/main/hyperlane-base/src/metrics/json_rpc_client.rs diff --git a/rust/hyperlane-base/src/metrics/mod.rs b/rust/main/hyperlane-base/src/metrics/mod.rs similarity index 100% rename from rust/hyperlane-base/src/metrics/mod.rs rename to rust/main/hyperlane-base/src/metrics/mod.rs diff --git a/rust/hyperlane-base/src/metrics/provider.rs b/rust/main/hyperlane-base/src/metrics/provider.rs similarity index 100% rename from rust/hyperlane-base/src/metrics/provider.rs rename to rust/main/hyperlane-base/src/metrics/provider.rs diff --git a/rust/hyperlane-base/src/oneline_eyre/handler.rs b/rust/main/hyperlane-base/src/oneline_eyre/handler.rs similarity index 100% rename from rust/hyperlane-base/src/oneline_eyre/handler.rs rename to rust/main/hyperlane-base/src/oneline_eyre/handler.rs diff --git a/rust/hyperlane-base/src/oneline_eyre/mod.rs b/rust/main/hyperlane-base/src/oneline_eyre/mod.rs similarity index 100% rename from rust/hyperlane-base/src/oneline_eyre/mod.rs rename to rust/main/hyperlane-base/src/oneline_eyre/mod.rs diff --git a/rust/hyperlane-base/src/server/base_server.rs b/rust/main/hyperlane-base/src/server/base_server.rs similarity index 100% rename from rust/hyperlane-base/src/server/base_server.rs rename to rust/main/hyperlane-base/src/server/base_server.rs diff --git a/rust/hyperlane-base/src/server/mod.rs b/rust/main/hyperlane-base/src/server/mod.rs similarity index 100% rename from rust/hyperlane-base/src/server/mod.rs rename to rust/main/hyperlane-base/src/server/mod.rs diff --git a/rust/hyperlane-base/src/settings/aws_credentials.rs b/rust/main/hyperlane-base/src/settings/aws_credentials.rs similarity index 94% rename from rust/hyperlane-base/src/settings/aws_credentials.rs rename to rust/main/hyperlane-base/src/settings/aws_credentials.rs index a86f6a1f2..8a35aa942 100644 --- a/rust/hyperlane-base/src/settings/aws_credentials.rs +++ b/rust/main/hyperlane-base/src/settings/aws_credentials.rs @@ -1,3 +1,6 @@ +#![allow(clippy::doc_markdown)] // TODO: `rustc` 1.80.1 clippy issue +#![allow(clippy::doc_lazy_continuation)] // TODO: `rustc` 1.80.1 clippy issue + use async_trait::async_trait; use rusoto_core::credential::{ AutoRefreshingProvider, AwsCredentials, CredentialsError, EnvironmentProvider, diff --git a/rust/hyperlane-base/src/settings/base.rs b/rust/main/hyperlane-base/src/settings/base.rs similarity index 100% rename from rust/hyperlane-base/src/settings/base.rs rename to rust/main/hyperlane-base/src/settings/base.rs diff --git a/rust/hyperlane-base/src/settings/chains.rs b/rust/main/hyperlane-base/src/settings/chains.rs similarity index 99% rename from rust/hyperlane-base/src/settings/chains.rs rename to rust/main/hyperlane-base/src/settings/chains.rs index b842d7225..34de1192a 100644 --- a/rust/hyperlane-base/src/settings/chains.rs +++ b/rust/main/hyperlane-base/src/settings/chains.rs @@ -210,6 +210,7 @@ impl ChainConf { ChainConnectionConf::Fuel(conf) => { let wallet = self.fuel_signer().await.context(ctx)?; hyperlane_fuel::FuelMailbox::new(conf, locator, wallet) + .await .map(|m| Box::new(m) as Box) .map_err(Into::into) } diff --git a/rust/hyperlane-base/src/settings/checkpoint_syncer.rs b/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs similarity index 100% rename from rust/hyperlane-base/src/settings/checkpoint_syncer.rs rename to rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs diff --git a/rust/hyperlane-base/src/settings/loader/arguments.rs b/rust/main/hyperlane-base/src/settings/loader/arguments.rs similarity index 100% rename from rust/hyperlane-base/src/settings/loader/arguments.rs rename to rust/main/hyperlane-base/src/settings/loader/arguments.rs diff --git a/rust/hyperlane-base/src/settings/loader/case_adapter.rs b/rust/main/hyperlane-base/src/settings/loader/case_adapter.rs similarity index 100% rename from rust/hyperlane-base/src/settings/loader/case_adapter.rs rename to rust/main/hyperlane-base/src/settings/loader/case_adapter.rs diff --git a/rust/hyperlane-base/src/settings/loader/environment.rs b/rust/main/hyperlane-base/src/settings/loader/environment.rs similarity index 100% rename from rust/hyperlane-base/src/settings/loader/environment.rs rename to rust/main/hyperlane-base/src/settings/loader/environment.rs diff --git a/rust/hyperlane-base/src/settings/loader/mod.rs b/rust/main/hyperlane-base/src/settings/loader/mod.rs similarity index 100% rename from rust/hyperlane-base/src/settings/loader/mod.rs rename to rust/main/hyperlane-base/src/settings/loader/mod.rs diff --git a/rust/hyperlane-base/src/settings/mod.rs b/rust/main/hyperlane-base/src/settings/mod.rs similarity index 100% rename from rust/hyperlane-base/src/settings/mod.rs rename to rust/main/hyperlane-base/src/settings/mod.rs diff --git a/rust/hyperlane-base/src/settings/parser/connection_parser.rs b/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs similarity index 98% rename from rust/hyperlane-base/src/settings/parser/connection_parser.rs rename to rust/main/hyperlane-base/src/settings/parser/connection_parser.rs index c7b105c2e..4bc6a01b7 100644 --- a/rust/hyperlane-base/src/settings/parser/connection_parser.rs +++ b/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs @@ -9,6 +9,7 @@ use crate::settings::ChainConnectionConf; use super::{parse_base_and_override_urls, parse_cosmos_gas_price, ValueParser}; +#[allow(clippy::question_mark)] // TODO: `rustc` 1.80.1 clippy issue pub fn build_ethereum_connection_conf( rpcs: &[Url], chain: &ValueParser, diff --git a/rust/hyperlane-base/src/settings/parser/json_value_parser.rs b/rust/main/hyperlane-base/src/settings/parser/json_value_parser.rs similarity index 99% rename from rust/hyperlane-base/src/settings/parser/json_value_parser.rs rename to rust/main/hyperlane-base/src/settings/parser/json_value_parser.rs index 61a881926..2f15e25d3 100644 --- a/rust/hyperlane-base/src/settings/parser/json_value_parser.rs +++ b/rust/main/hyperlane-base/src/settings/parser/json_value_parser.rs @@ -8,6 +8,7 @@ use itertools::Itertools; use serde::de::{DeserializeOwned, StdError}; use serde_json::Value; +#[allow(unused_imports)] // TODO: `rustc` 1.80.1 clippy issue pub use super::super::envs::*; /// A serde-json value config parsing utility. diff --git a/rust/hyperlane-base/src/settings/parser/mod.rs b/rust/main/hyperlane-base/src/settings/parser/mod.rs similarity index 100% rename from rust/hyperlane-base/src/settings/parser/mod.rs rename to rust/main/hyperlane-base/src/settings/parser/mod.rs diff --git a/rust/hyperlane-base/src/settings/signers.rs b/rust/main/hyperlane-base/src/settings/signers.rs similarity index 98% rename from rust/hyperlane-base/src/settings/signers.rs rename to rust/main/hyperlane-base/src/settings/signers.rs index d0642434f..042894c6b 100644 --- a/rust/hyperlane-base/src/settings/signers.rs +++ b/rust/main/hyperlane-base/src/settings/signers.rs @@ -101,7 +101,7 @@ impl ChainSigner for hyperlane_ethereum::Signers { impl BuildableWithSignerConf for fuels::prelude::WalletUnlocked { async fn build(conf: &SignerConf) -> Result { if let SignerConf::HexKey { key } = conf { - let key = fuels::signers::fuel_crypto::SecretKey::try_from(key.as_bytes()) + let key = fuels::crypto::SecretKey::try_from(key.as_bytes()) .context("Invalid fuel signer key")?; Ok(fuels::prelude::WalletUnlocked::new_from_private_key( key, None, diff --git a/rust/hyperlane-base/src/settings/trace/fmt.rs b/rust/main/hyperlane-base/src/settings/trace/fmt.rs similarity index 100% rename from rust/hyperlane-base/src/settings/trace/fmt.rs rename to rust/main/hyperlane-base/src/settings/trace/fmt.rs diff --git a/rust/hyperlane-base/src/settings/trace/mod.rs b/rust/main/hyperlane-base/src/settings/trace/mod.rs similarity index 100% rename from rust/hyperlane-base/src/settings/trace/mod.rs rename to rust/main/hyperlane-base/src/settings/trace/mod.rs diff --git a/rust/hyperlane-base/src/settings/trace/span_metrics.rs b/rust/main/hyperlane-base/src/settings/trace/span_metrics.rs similarity index 100% rename from rust/hyperlane-base/src/settings/trace/span_metrics.rs rename to rust/main/hyperlane-base/src/settings/trace/span_metrics.rs diff --git a/rust/hyperlane-base/src/traits/checkpoint_syncer.rs b/rust/main/hyperlane-base/src/traits/checkpoint_syncer.rs similarity index 100% rename from rust/hyperlane-base/src/traits/checkpoint_syncer.rs rename to rust/main/hyperlane-base/src/traits/checkpoint_syncer.rs diff --git a/rust/hyperlane-base/src/traits/mod.rs b/rust/main/hyperlane-base/src/traits/mod.rs similarity index 100% rename from rust/hyperlane-base/src/traits/mod.rs rename to rust/main/hyperlane-base/src/traits/mod.rs diff --git a/rust/hyperlane-base/src/types/gcs_storage.rs b/rust/main/hyperlane-base/src/types/gcs_storage.rs similarity index 100% rename from rust/hyperlane-base/src/types/gcs_storage.rs rename to rust/main/hyperlane-base/src/types/gcs_storage.rs diff --git a/rust/hyperlane-base/src/types/local_storage.rs b/rust/main/hyperlane-base/src/types/local_storage.rs similarity index 100% rename from rust/hyperlane-base/src/types/local_storage.rs rename to rust/main/hyperlane-base/src/types/local_storage.rs diff --git a/rust/hyperlane-base/src/types/mod.rs b/rust/main/hyperlane-base/src/types/mod.rs similarity index 100% rename from rust/hyperlane-base/src/types/mod.rs rename to rust/main/hyperlane-base/src/types/mod.rs diff --git a/rust/hyperlane-base/src/types/multisig.rs b/rust/main/hyperlane-base/src/types/multisig.rs similarity index 100% rename from rust/hyperlane-base/src/types/multisig.rs rename to rust/main/hyperlane-base/src/types/multisig.rs diff --git a/rust/hyperlane-base/src/types/s3_storage.rs b/rust/main/hyperlane-base/src/types/s3_storage.rs similarity index 100% rename from rust/hyperlane-base/src/types/s3_storage.rs rename to rust/main/hyperlane-base/src/types/s3_storage.rs diff --git a/rust/hyperlane-base/src/types/utils.rs b/rust/main/hyperlane-base/src/types/utils.rs similarity index 100% rename from rust/hyperlane-base/src/types/utils.rs rename to rust/main/hyperlane-base/src/types/utils.rs diff --git a/rust/hyperlane-base/tests/chain_config.rs b/rust/main/hyperlane-base/tests/chain_config.rs similarity index 100% rename from rust/hyperlane-base/tests/chain_config.rs rename to rust/main/hyperlane-base/tests/chain_config.rs diff --git a/rust/hyperlane-core/Cargo.toml b/rust/main/hyperlane-core/Cargo.toml similarity index 91% rename from rust/hyperlane-core/Cargo.toml rename to rust/main/hyperlane-core/Cargo.toml index 2bb5f46d8..d7591225c 100644 --- a/rust/hyperlane-core/Cargo.toml +++ b/rust/main/hyperlane-core/Cargo.toml @@ -44,7 +44,7 @@ tracing.workspace = true typetag.workspace = true primitive-types = { workspace = true, optional = true } solana-sdk = { workspace = true, optional = true } -tiny-keccak = { workspace = true, features = ["keccak"]} +tiny-keccak = { workspace = true, features = ["keccak"] } uint.workspace = true [dev-dependencies] @@ -56,6 +56,11 @@ float = [] test-utils = ["dep:config"] agent = ["ethers", "strum"] strum = ["dep:strum"] -ethers = ["dep:ethers-core", "dep:ethers-contract", "dep:ethers-providers", "dep:primitive-types"] +ethers = [ + "dep:ethers-core", + "dep:ethers-contract", + "dep:ethers-providers", + "dep:primitive-types", +] solana = ["dep:solana-sdk"] async = ["tokio", "futures"] diff --git a/rust/hyperlane-core/src/accumulator/incremental.rs b/rust/main/hyperlane-core/src/accumulator/incremental.rs similarity index 100% rename from rust/hyperlane-core/src/accumulator/incremental.rs rename to rust/main/hyperlane-core/src/accumulator/incremental.rs diff --git a/rust/hyperlane-core/src/accumulator/merkle.rs b/rust/main/hyperlane-core/src/accumulator/merkle.rs similarity index 100% rename from rust/hyperlane-core/src/accumulator/merkle.rs rename to rust/main/hyperlane-core/src/accumulator/merkle.rs diff --git a/rust/hyperlane-core/src/accumulator/mod.rs b/rust/main/hyperlane-core/src/accumulator/mod.rs similarity index 100% rename from rust/hyperlane-core/src/accumulator/mod.rs rename to rust/main/hyperlane-core/src/accumulator/mod.rs diff --git a/rust/hyperlane-core/src/accumulator/sparse.rs b/rust/main/hyperlane-core/src/accumulator/sparse.rs similarity index 100% rename from rust/hyperlane-core/src/accumulator/sparse.rs rename to rust/main/hyperlane-core/src/accumulator/sparse.rs diff --git a/rust/hyperlane-core/src/accumulator/zero_hashes.rs b/rust/main/hyperlane-core/src/accumulator/zero_hashes.rs similarity index 100% rename from rust/hyperlane-core/src/accumulator/zero_hashes.rs rename to rust/main/hyperlane-core/src/accumulator/zero_hashes.rs diff --git a/rust/hyperlane-core/src/chain.rs b/rust/main/hyperlane-core/src/chain.rs similarity index 100% rename from rust/hyperlane-core/src/chain.rs rename to rust/main/hyperlane-core/src/chain.rs diff --git a/rust/hyperlane-core/src/config/config_path.rs b/rust/main/hyperlane-core/src/config/config_path.rs similarity index 100% rename from rust/hyperlane-core/src/config/config_path.rs rename to rust/main/hyperlane-core/src/config/config_path.rs diff --git a/rust/hyperlane-core/src/config/mod.rs b/rust/main/hyperlane-core/src/config/mod.rs similarity index 100% rename from rust/hyperlane-core/src/config/mod.rs rename to rust/main/hyperlane-core/src/config/mod.rs diff --git a/rust/hyperlane-core/src/config/str_or_int.rs b/rust/main/hyperlane-core/src/config/str_or_int.rs similarity index 96% rename from rust/hyperlane-core/src/config/str_or_int.rs rename to rust/main/hyperlane-core/src/config/str_or_int.rs index 242d98336..b2c1acbec 100644 --- a/rust/hyperlane-core/src/config/str_or_int.rs +++ b/rust/main/hyperlane-core/src/config/str_or_int.rs @@ -91,6 +91,7 @@ impl TryFrom<&StrOrInt> for U256 { StrOrInt::Str(s) => s.parse().map_err(|_| { StrOrIntParseError::Other(format!("Unable to parse U256 string ({s})")) })?, + #[allow(clippy::unnecessary_fallible_conversions)] // TODO: `rustc` 1.80.1 clippy issue StrOrInt::Int(i) => (*i).try_into().map_err(|_| { StrOrIntParseError::Other(format!("Unable to parse integer as U256 ({i})")) })?, diff --git a/rust/hyperlane-core/src/config/trait_ext.rs b/rust/main/hyperlane-core/src/config/trait_ext.rs similarity index 100% rename from rust/hyperlane-core/src/config/trait_ext.rs rename to rust/main/hyperlane-core/src/config/trait_ext.rs diff --git a/rust/hyperlane-core/src/error.rs b/rust/main/hyperlane-core/src/error.rs similarity index 100% rename from rust/hyperlane-core/src/error.rs rename to rust/main/hyperlane-core/src/error.rs diff --git a/rust/hyperlane-core/src/lib.rs b/rust/main/hyperlane-core/src/lib.rs similarity index 95% rename from rust/hyperlane-core/src/lib.rs rename to rust/main/hyperlane-core/src/lib.rs index 610fa3d81..4c5200b0c 100644 --- a/rust/hyperlane-core/src/lib.rs +++ b/rust/main/hyperlane-core/src/lib.rs @@ -3,8 +3,8 @@ #![warn(missing_docs)] #![deny(unsafe_code)] +#![allow(unknown_lints)] // TODO: `rustc` 1.80.1 clippy issue #![forbid(where_clauses_object_safety)] - extern crate core; pub use chain::*; diff --git a/rust/hyperlane-core/src/metrics/agent.rs b/rust/main/hyperlane-core/src/metrics/agent.rs similarity index 100% rename from rust/hyperlane-core/src/metrics/agent.rs rename to rust/main/hyperlane-core/src/metrics/agent.rs diff --git a/rust/hyperlane-core/src/metrics/mod.rs b/rust/main/hyperlane-core/src/metrics/mod.rs similarity index 100% rename from rust/hyperlane-core/src/metrics/mod.rs rename to rust/main/hyperlane-core/src/metrics/mod.rs diff --git a/rust/hyperlane-core/src/rpc_clients/error.rs b/rust/main/hyperlane-core/src/rpc_clients/error.rs similarity index 100% rename from rust/hyperlane-core/src/rpc_clients/error.rs rename to rust/main/hyperlane-core/src/rpc_clients/error.rs diff --git a/rust/hyperlane-core/src/rpc_clients/fallback.rs b/rust/main/hyperlane-core/src/rpc_clients/fallback.rs similarity index 100% rename from rust/hyperlane-core/src/rpc_clients/fallback.rs rename to rust/main/hyperlane-core/src/rpc_clients/fallback.rs diff --git a/rust/hyperlane-core/src/rpc_clients/mod.rs b/rust/main/hyperlane-core/src/rpc_clients/mod.rs similarity index 100% rename from rust/hyperlane-core/src/rpc_clients/mod.rs rename to rust/main/hyperlane-core/src/rpc_clients/mod.rs diff --git a/rust/hyperlane-core/src/rpc_clients/retry.rs b/rust/main/hyperlane-core/src/rpc_clients/retry.rs similarity index 100% rename from rust/hyperlane-core/src/rpc_clients/retry.rs rename to rust/main/hyperlane-core/src/rpc_clients/retry.rs diff --git a/rust/hyperlane-core/src/test_output.rs b/rust/main/hyperlane-core/src/test_output.rs similarity index 100% rename from rust/hyperlane-core/src/test_output.rs rename to rust/main/hyperlane-core/src/test_output.rs diff --git a/rust/hyperlane-core/src/test_utils.rs b/rust/main/hyperlane-core/src/test_utils.rs similarity index 100% rename from rust/hyperlane-core/src/test_utils.rs rename to rust/main/hyperlane-core/src/test_utils.rs diff --git a/rust/hyperlane-core/src/traits/aggregation_ism.rs b/rust/main/hyperlane-core/src/traits/aggregation_ism.rs similarity index 100% rename from rust/hyperlane-core/src/traits/aggregation_ism.rs rename to rust/main/hyperlane-core/src/traits/aggregation_ism.rs diff --git a/rust/hyperlane-core/src/traits/ccip_read_ism.rs b/rust/main/hyperlane-core/src/traits/ccip_read_ism.rs similarity index 100% rename from rust/hyperlane-core/src/traits/ccip_read_ism.rs rename to rust/main/hyperlane-core/src/traits/ccip_read_ism.rs diff --git a/rust/hyperlane-core/src/traits/cursor.rs b/rust/main/hyperlane-core/src/traits/cursor.rs similarity index 100% rename from rust/hyperlane-core/src/traits/cursor.rs rename to rust/main/hyperlane-core/src/traits/cursor.rs diff --git a/rust/hyperlane-core/src/traits/db.rs b/rust/main/hyperlane-core/src/traits/db.rs similarity index 100% rename from rust/hyperlane-core/src/traits/db.rs rename to rust/main/hyperlane-core/src/traits/db.rs diff --git a/rust/hyperlane-core/src/traits/deployed.rs b/rust/main/hyperlane-core/src/traits/deployed.rs similarity index 100% rename from rust/hyperlane-core/src/traits/deployed.rs rename to rust/main/hyperlane-core/src/traits/deployed.rs diff --git a/rust/hyperlane-core/src/traits/encode.rs b/rust/main/hyperlane-core/src/traits/encode.rs similarity index 100% rename from rust/hyperlane-core/src/traits/encode.rs rename to rust/main/hyperlane-core/src/traits/encode.rs diff --git a/rust/hyperlane-core/src/traits/indexer.rs b/rust/main/hyperlane-core/src/traits/indexer.rs similarity index 100% rename from rust/hyperlane-core/src/traits/indexer.rs rename to rust/main/hyperlane-core/src/traits/indexer.rs diff --git a/rust/hyperlane-core/src/traits/interchain_gas.rs b/rust/main/hyperlane-core/src/traits/interchain_gas.rs similarity index 100% rename from rust/hyperlane-core/src/traits/interchain_gas.rs rename to rust/main/hyperlane-core/src/traits/interchain_gas.rs diff --git a/rust/hyperlane-core/src/traits/interchain_security_module.rs b/rust/main/hyperlane-core/src/traits/interchain_security_module.rs similarity index 100% rename from rust/hyperlane-core/src/traits/interchain_security_module.rs rename to rust/main/hyperlane-core/src/traits/interchain_security_module.rs diff --git a/rust/hyperlane-core/src/traits/mailbox.rs b/rust/main/hyperlane-core/src/traits/mailbox.rs similarity index 100% rename from rust/hyperlane-core/src/traits/mailbox.rs rename to rust/main/hyperlane-core/src/traits/mailbox.rs diff --git a/rust/hyperlane-core/src/traits/merkle_tree_hook.rs b/rust/main/hyperlane-core/src/traits/merkle_tree_hook.rs similarity index 100% rename from rust/hyperlane-core/src/traits/merkle_tree_hook.rs rename to rust/main/hyperlane-core/src/traits/merkle_tree_hook.rs diff --git a/rust/hyperlane-core/src/traits/mod.rs b/rust/main/hyperlane-core/src/traits/mod.rs similarity index 100% rename from rust/hyperlane-core/src/traits/mod.rs rename to rust/main/hyperlane-core/src/traits/mod.rs diff --git a/rust/hyperlane-core/src/traits/multisig_ism.rs b/rust/main/hyperlane-core/src/traits/multisig_ism.rs similarity index 100% rename from rust/hyperlane-core/src/traits/multisig_ism.rs rename to rust/main/hyperlane-core/src/traits/multisig_ism.rs diff --git a/rust/hyperlane-core/src/traits/pending_operation.rs b/rust/main/hyperlane-core/src/traits/pending_operation.rs similarity index 100% rename from rust/hyperlane-core/src/traits/pending_operation.rs rename to rust/main/hyperlane-core/src/traits/pending_operation.rs diff --git a/rust/hyperlane-core/src/traits/provider.rs b/rust/main/hyperlane-core/src/traits/provider.rs similarity index 100% rename from rust/hyperlane-core/src/traits/provider.rs rename to rust/main/hyperlane-core/src/traits/provider.rs diff --git a/rust/hyperlane-core/src/traits/routing_ism.rs b/rust/main/hyperlane-core/src/traits/routing_ism.rs similarity index 100% rename from rust/hyperlane-core/src/traits/routing_ism.rs rename to rust/main/hyperlane-core/src/traits/routing_ism.rs diff --git a/rust/hyperlane-core/src/traits/signing.rs b/rust/main/hyperlane-core/src/traits/signing.rs similarity index 100% rename from rust/hyperlane-core/src/traits/signing.rs rename to rust/main/hyperlane-core/src/traits/signing.rs diff --git a/rust/hyperlane-core/src/traits/validator_announce.rs b/rust/main/hyperlane-core/src/traits/validator_announce.rs similarity index 100% rename from rust/hyperlane-core/src/traits/validator_announce.rs rename to rust/main/hyperlane-core/src/traits/validator_announce.rs diff --git a/rust/hyperlane-core/src/types/announcement.rs b/rust/main/hyperlane-core/src/types/announcement.rs similarity index 100% rename from rust/hyperlane-core/src/types/announcement.rs rename to rust/main/hyperlane-core/src/types/announcement.rs diff --git a/rust/hyperlane-core/src/types/chain_data.rs b/rust/main/hyperlane-core/src/types/chain_data.rs similarity index 100% rename from rust/hyperlane-core/src/types/chain_data.rs rename to rust/main/hyperlane-core/src/types/chain_data.rs diff --git a/rust/hyperlane-core/src/types/checkpoint.rs b/rust/main/hyperlane-core/src/types/checkpoint.rs similarity index 100% rename from rust/hyperlane-core/src/types/checkpoint.rs rename to rust/main/hyperlane-core/src/types/checkpoint.rs diff --git a/rust/hyperlane-core/src/types/identifiers.rs b/rust/main/hyperlane-core/src/types/identifiers.rs similarity index 100% rename from rust/hyperlane-core/src/types/identifiers.rs rename to rust/main/hyperlane-core/src/types/identifiers.rs diff --git a/rust/hyperlane-core/src/types/indexing.rs b/rust/main/hyperlane-core/src/types/indexing.rs similarity index 100% rename from rust/hyperlane-core/src/types/indexing.rs rename to rust/main/hyperlane-core/src/types/indexing.rs diff --git a/rust/hyperlane-core/src/types/log_metadata.rs b/rust/main/hyperlane-core/src/types/log_metadata.rs similarity index 96% rename from rust/hyperlane-core/src/types/log_metadata.rs rename to rust/main/hyperlane-core/src/types/log_metadata.rs index e85824dab..3953ec1b2 100644 --- a/rust/hyperlane-core/src/types/log_metadata.rs +++ b/rust/main/hyperlane-core/src/types/log_metadata.rs @@ -53,6 +53,7 @@ impl From<&EthersLogMeta> for LogMeta { } // note: this ordering assumes both logs are part of the same blockchain. +#[allow(clippy::non_canonical_partial_ord_impl)] // TODO: `rustc` 1.80.1 clippy issue impl PartialOrd for LogMeta { fn partial_cmp(&self, other: &Self) -> Option { Some(match self.block_number.cmp(&other.block_number) { diff --git a/rust/hyperlane-core/src/types/merkle_tree.rs b/rust/main/hyperlane-core/src/types/merkle_tree.rs similarity index 100% rename from rust/hyperlane-core/src/types/merkle_tree.rs rename to rust/main/hyperlane-core/src/types/merkle_tree.rs diff --git a/rust/hyperlane-core/src/types/message.rs b/rust/main/hyperlane-core/src/types/message.rs similarity index 99% rename from rust/hyperlane-core/src/types/message.rs rename to rust/main/hyperlane-core/src/types/message.rs index 727fa6eb9..576e1eb48 100644 --- a/rust/hyperlane-core/src/types/message.rs +++ b/rust/main/hyperlane-core/src/types/message.rs @@ -97,7 +97,7 @@ impl From<&RawHyperlaneMessage> for HyperlaneMessage { let sender: [u8; 32] = m[9..41].try_into().unwrap(); let destination: [u8; 4] = m[41..45].try_into().unwrap(); let recipient: [u8; 32] = m[45..77].try_into().unwrap(); - let body = m[77..].try_into().unwrap(); + let body = m[77..].into(); Self { version, nonce: u32::from_be_bytes(nonce), diff --git a/rust/hyperlane-core/src/types/mod.rs b/rust/main/hyperlane-core/src/types/mod.rs similarity index 100% rename from rust/hyperlane-core/src/types/mod.rs rename to rust/main/hyperlane-core/src/types/mod.rs diff --git a/rust/hyperlane-core/src/types/primitive_types.rs b/rust/main/hyperlane-core/src/types/primitive_types.rs similarity index 99% rename from rust/hyperlane-core/src/types/primitive_types.rs rename to rust/main/hyperlane-core/src/types/primitive_types.rs index c5636b3b9..648119cdd 100644 --- a/rust/hyperlane-core/src/types/primitive_types.rs +++ b/rust/main/hyperlane-core/src/types/primitive_types.rs @@ -44,7 +44,7 @@ construct_uint! { mod fixed_hashes { // we can't change how they made the macro, so ignore the lint - #![allow(clippy::incorrect_clone_impl_on_copy_type)] + #![allow(clippy::non_canonical_clone_impl)] use borsh::{BorshDeserialize, BorshSerialize}; use fixed_hash::construct_fixed_hash; diff --git a/rust/hyperlane-core/src/types/serialize.rs b/rust/main/hyperlane-core/src/types/serialize.rs similarity index 99% rename from rust/hyperlane-core/src/types/serialize.rs rename to rust/main/hyperlane-core/src/types/serialize.rs index 9ffb69994..73558e10c 100644 --- a/rust/hyperlane-core/src/types/serialize.rs +++ b/rust/main/hyperlane-core/src/types/serialize.rs @@ -1,4 +1,6 @@ #![allow(unused)] +#![allow(unexpected_cfgs)] // TODO: `rustc` 1.80.1 clippy issue + // Based on https://github.com/paritytech/parity-common/blob/7194def73feb7d97644303f1a6ddbab29bbb799f/primitive-types/impls/serde/src/serialize.rs // Copyright 2020 Parity Technologies diff --git a/rust/hyperlane-core/src/types/transaction.rs b/rust/main/hyperlane-core/src/types/transaction.rs similarity index 100% rename from rust/hyperlane-core/src/types/transaction.rs rename to rust/main/hyperlane-core/src/types/transaction.rs diff --git a/rust/hyperlane-core/src/utils.rs b/rust/main/hyperlane-core/src/utils.rs similarity index 100% rename from rust/hyperlane-core/src/utils.rs rename to rust/main/hyperlane-core/src/utils.rs diff --git a/rust/hyperlane-test/Cargo.toml b/rust/main/hyperlane-test/Cargo.toml similarity index 87% rename from rust/hyperlane-test/Cargo.toml rename to rust/main/hyperlane-test/Cargo.toml index cbf4b2cdc..300fa91d5 100644 --- a/rust/hyperlane-test/Cargo.toml +++ b/rust/main/hyperlane-test/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "hyperlane-test" documentation.workspace = true diff --git a/rust/hyperlane-test/src/lib.rs b/rust/main/hyperlane-test/src/lib.rs similarity index 77% rename from rust/hyperlane-test/src/lib.rs rename to rust/main/hyperlane-test/src/lib.rs index d86c53cc9..aa76ffae5 100644 --- a/rust/hyperlane-test/src/lib.rs +++ b/rust/main/hyperlane-test/src/lib.rs @@ -2,6 +2,7 @@ #![forbid(unsafe_code)] #![cfg_attr(test, warn(missing_docs))] +#![allow(unknown_lints)] // TODO: `rustc` 1.80.1 clippy issue #![forbid(where_clauses_object_safety)] /// Mock contracts diff --git a/rust/hyperlane-test/src/mocks/mailbox.rs b/rust/main/hyperlane-test/src/mocks/mailbox.rs similarity index 100% rename from rust/hyperlane-test/src/mocks/mailbox.rs rename to rust/main/hyperlane-test/src/mocks/mailbox.rs diff --git a/rust/hyperlane-test/src/mocks/mod.rs b/rust/main/hyperlane-test/src/mocks/mod.rs similarity index 100% rename from rust/hyperlane-test/src/mocks/mod.rs rename to rust/main/hyperlane-test/src/mocks/mod.rs diff --git a/rust/hyperlane-test/src/mocks/validator_announce.rs b/rust/main/hyperlane-test/src/mocks/validator_announce.rs similarity index 100% rename from rust/hyperlane-test/src/mocks/validator_announce.rs rename to rust/main/hyperlane-test/src/mocks/validator_announce.rs diff --git a/rust/main/rust-toolchain b/rust/main/rust-toolchain new file mode 100644 index 000000000..7f466bd2d --- /dev/null +++ b/rust/main/rust-toolchain @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.80.1" +profile = "default" diff --git a/rust/terraform/.gitignore b/rust/main/terraform/.gitignore similarity index 100% rename from rust/terraform/.gitignore rename to rust/main/terraform/.gitignore diff --git a/rust/terraform/README.md b/rust/main/terraform/README.md similarity index 100% rename from rust/terraform/README.md rename to rust/main/terraform/README.md diff --git a/rust/terraform/globals.tf b/rust/main/terraform/globals.tf similarity index 100% rename from rust/terraform/globals.tf rename to rust/main/terraform/globals.tf diff --git a/rust/terraform/main.tf b/rust/main/terraform/main.tf similarity index 100% rename from rust/terraform/main.tf rename to rust/main/terraform/main.tf diff --git a/rust/terraform/modules/efs/main.tf b/rust/main/terraform/modules/efs/main.tf similarity index 100% rename from rust/terraform/modules/efs/main.tf rename to rust/main/terraform/modules/efs/main.tf diff --git a/rust/terraform/modules/efs/outputs.tf b/rust/main/terraform/modules/efs/outputs.tf similarity index 100% rename from rust/terraform/modules/efs/outputs.tf rename to rust/main/terraform/modules/efs/outputs.tf diff --git a/rust/terraform/modules/efs/variables.tf b/rust/main/terraform/modules/efs/variables.tf similarity index 100% rename from rust/terraform/modules/efs/variables.tf rename to rust/main/terraform/modules/efs/variables.tf diff --git a/rust/terraform/modules/iam_kms/main.tf b/rust/main/terraform/modules/iam_kms/main.tf similarity index 100% rename from rust/terraform/modules/iam_kms/main.tf rename to rust/main/terraform/modules/iam_kms/main.tf diff --git a/rust/terraform/modules/iam_kms/outputs.tf b/rust/main/terraform/modules/iam_kms/outputs.tf similarity index 100% rename from rust/terraform/modules/iam_kms/outputs.tf rename to rust/main/terraform/modules/iam_kms/outputs.tf diff --git a/rust/terraform/modules/iam_kms/variables.tf b/rust/main/terraform/modules/iam_kms/variables.tf similarity index 100% rename from rust/terraform/modules/iam_kms/variables.tf rename to rust/main/terraform/modules/iam_kms/variables.tf diff --git a/rust/terraform/modules/s3/main.tf b/rust/main/terraform/modules/s3/main.tf similarity index 100% rename from rust/terraform/modules/s3/main.tf rename to rust/main/terraform/modules/s3/main.tf diff --git a/rust/terraform/modules/s3/outputs.tf b/rust/main/terraform/modules/s3/outputs.tf similarity index 100% rename from rust/terraform/modules/s3/outputs.tf rename to rust/main/terraform/modules/s3/outputs.tf diff --git a/rust/terraform/modules/s3/variables.tf b/rust/main/terraform/modules/s3/variables.tf similarity index 100% rename from rust/terraform/modules/s3/variables.tf rename to rust/main/terraform/modules/s3/variables.tf diff --git a/rust/terraform/modules/validator/main.tf b/rust/main/terraform/modules/validator/main.tf similarity index 100% rename from rust/terraform/modules/validator/main.tf rename to rust/main/terraform/modules/validator/main.tf diff --git a/rust/terraform/modules/validator/outputs.tf b/rust/main/terraform/modules/validator/outputs.tf similarity index 100% rename from rust/terraform/modules/validator/outputs.tf rename to rust/main/terraform/modules/validator/outputs.tf diff --git a/rust/terraform/modules/validator/variables.tf b/rust/main/terraform/modules/validator/variables.tf similarity index 100% rename from rust/terraform/modules/validator/variables.tf rename to rust/main/terraform/modules/validator/variables.tf diff --git a/rust/terraform/outputs.tf b/rust/main/terraform/outputs.tf similarity index 100% rename from rust/terraform/outputs.tf rename to rust/main/terraform/outputs.tf diff --git a/rust/terraform/variables.tf b/rust/main/terraform/variables.tf similarity index 100% rename from rust/terraform/variables.tf rename to rust/main/terraform/variables.tf diff --git a/rust/utils/abigen/Cargo.toml b/rust/main/utils/abigen/Cargo.toml similarity index 92% rename from rust/utils/abigen/Cargo.toml rename to rust/main/utils/abigen/Cargo.toml index beb601469..1f28d161e 100644 --- a/rust/utils/abigen/Cargo.toml +++ b/rust/main/utils/abigen/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "abigen" documentation.workspace = true diff --git a/rust/utils/abigen/src/lib.rs b/rust/main/utils/abigen/src/lib.rs similarity index 94% rename from rust/utils/abigen/src/lib.rs rename to rust/main/utils/abigen/src/lib.rs index b4b7970fd..3fe21a55b 100644 --- a/rust/utils/abigen/src/lib.rs +++ b/rust/main/utils/abigen/src/lib.rs @@ -104,12 +104,14 @@ pub fn generate_bindings( } #[cfg(feature = "fuels")] if build_type == BuildType::Fuels { + let abi = + fuels_code_gen::Abi::load_from(contract_path.as_ref()).expect("could not load abi"); let tokens = fuels_code_gen::Abigen::generate( - vec![fuels_code_gen::AbigenTarget { - name: contract_name.into(), - abi: abi_source.into(), - program_type: ProgramType::Contract, - }], + vec![fuels_code_gen::AbigenTarget::new( + contract_name.into(), + abi, + ProgramType::Contract, + )], false, ) .expect("could not generate bindings") diff --git a/rust/utils/backtrace-oneline/Cargo.toml b/rust/main/utils/backtrace-oneline/Cargo.toml similarity index 71% rename from rust/utils/backtrace-oneline/Cargo.toml rename to rust/main/utils/backtrace-oneline/Cargo.toml index 7da1749bb..18e96f2b8 100644 --- a/rust/utils/backtrace-oneline/Cargo.toml +++ b/rust/main/utils/backtrace-oneline/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "backtrace-oneline" version = "0.1.0" @@ -9,4 +7,4 @@ publish.workspace = true [dependencies] backtrace.workspace = true -derive-new.workspace = true \ No newline at end of file +derive-new.workspace = true diff --git a/rust/utils/backtrace-oneline/src/lib.rs b/rust/main/utils/backtrace-oneline/src/lib.rs similarity index 100% rename from rust/utils/backtrace-oneline/src/lib.rs rename to rust/main/utils/backtrace-oneline/src/lib.rs diff --git a/rust/utils/hex/Cargo.toml b/rust/main/utils/hex/Cargo.toml similarity index 78% rename from rust/utils/hex/Cargo.toml rename to rust/main/utils/hex/Cargo.toml index 0d1584a9f..9159b9e5d 100644 --- a/rust/utils/hex/Cargo.toml +++ b/rust/main/utils/hex/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "hex" version = "0.1.0" diff --git a/rust/utils/hex/src/lib.rs b/rust/main/utils/hex/src/lib.rs similarity index 100% rename from rust/utils/hex/src/lib.rs rename to rust/main/utils/hex/src/lib.rs diff --git a/rust/utils/run-locally/Cargo.toml b/rust/main/utils/run-locally/Cargo.toml similarity index 87% rename from rust/utils/run-locally/Cargo.toml rename to rust/main/utils/run-locally/Cargo.toml index 06a2b5cdd..9dedae9ce 100644 --- a/rust/utils/run-locally/Cargo.toml +++ b/rust/main/utils/run-locally/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["workspace-inheritance"] - [package] name = "run-locally" documentation.workspace = true @@ -11,8 +9,8 @@ version.workspace = true [dependencies] hyperlane-base = { path = "../../hyperlane-base" } -hyperlane-core = { path = "../../hyperlane-core", features = ["float"]} -hyperlane-cosmos = { path = "../../chains/hyperlane-cosmos"} +hyperlane-core = { path = "../../hyperlane-core", features = ["float"] } +hyperlane-cosmos = { path = "../../chains/hyperlane-cosmos" } toml_edit.workspace = true k256.workspace = true jobserver.workspace = true @@ -35,7 +33,7 @@ ureq = { workspace = true, default-features = false } which.workspace = true macro_rules_attribute.workspace = true regex.workspace = true -relayer = { path = "../../agents/relayer"} +relayer = { path = "../../agents/relayer" } hyperlane-cosmwasm-interface.workspace = true cosmwasm-schema.workspace = true @@ -44,4 +42,4 @@ anyhow = { workspace = true } vergen = { version = "8.3.2", features = ["build", "git", "gitcl"] } [features] -cosmos = [] \ No newline at end of file +cosmos = [] diff --git a/rust/utils/run-locally/build.rs b/rust/main/utils/run-locally/build.rs similarity index 100% rename from rust/utils/run-locally/build.rs rename to rust/main/utils/run-locally/build.rs diff --git a/rust/utils/run-locally/src/config.rs b/rust/main/utils/run-locally/src/config.rs similarity index 100% rename from rust/utils/run-locally/src/config.rs rename to rust/main/utils/run-locally/src/config.rs diff --git a/rust/utils/run-locally/src/cosmos/cli.rs b/rust/main/utils/run-locally/src/cosmos/cli.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/cli.rs rename to rust/main/utils/run-locally/src/cosmos/cli.rs diff --git a/rust/utils/run-locally/src/cosmos/crypto.rs b/rust/main/utils/run-locally/src/cosmos/crypto.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/crypto.rs rename to rust/main/utils/run-locally/src/cosmos/crypto.rs diff --git a/rust/utils/run-locally/src/cosmos/deploy.rs b/rust/main/utils/run-locally/src/cosmos/deploy.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/deploy.rs rename to rust/main/utils/run-locally/src/cosmos/deploy.rs diff --git a/rust/utils/run-locally/src/cosmos/link.rs b/rust/main/utils/run-locally/src/cosmos/link.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/link.rs rename to rust/main/utils/run-locally/src/cosmos/link.rs diff --git a/rust/utils/run-locally/src/cosmos/mod.rs b/rust/main/utils/run-locally/src/cosmos/mod.rs similarity index 99% rename from rust/utils/run-locally/src/cosmos/mod.rs rename to rust/main/utils/run-locally/src/cosmos/mod.rs index 7ce697cb6..9dc68950c 100644 --- a/rust/utils/run-locally/src/cosmos/mod.rs +++ b/rust/main/utils/run-locally/src/cosmos/mod.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] // TODO: `rustc` 1.80.1 clippy issue + use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use std::thread::sleep; @@ -309,6 +311,7 @@ fn launch_cosmos_relayer( } #[apply(as_task)] +#[allow(clippy::let_and_return)] // TODO: `rustc` 1.80.1 clippy issue fn launch_cosmos_scraper( agent_config_path: String, chains: Vec, diff --git a/rust/utils/run-locally/src/cosmos/rpc.rs b/rust/main/utils/run-locally/src/cosmos/rpc.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/rpc.rs rename to rust/main/utils/run-locally/src/cosmos/rpc.rs diff --git a/rust/utils/run-locally/src/cosmos/source.rs b/rust/main/utils/run-locally/src/cosmos/source.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/source.rs rename to rust/main/utils/run-locally/src/cosmos/source.rs diff --git a/rust/utils/run-locally/src/cosmos/types.rs b/rust/main/utils/run-locally/src/cosmos/types.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/types.rs rename to rust/main/utils/run-locally/src/cosmos/types.rs diff --git a/rust/utils/run-locally/src/cosmos/utils.rs b/rust/main/utils/run-locally/src/cosmos/utils.rs similarity index 100% rename from rust/utils/run-locally/src/cosmos/utils.rs rename to rust/main/utils/run-locally/src/cosmos/utils.rs diff --git a/rust/utils/run-locally/src/ethereum/mod.rs b/rust/main/utils/run-locally/src/ethereum/mod.rs similarity index 100% rename from rust/utils/run-locally/src/ethereum/mod.rs rename to rust/main/utils/run-locally/src/ethereum/mod.rs diff --git a/rust/utils/run-locally/src/ethereum/multicall.rs b/rust/main/utils/run-locally/src/ethereum/multicall.rs similarity index 100% rename from rust/utils/run-locally/src/ethereum/multicall.rs rename to rust/main/utils/run-locally/src/ethereum/multicall.rs diff --git a/rust/utils/run-locally/src/invariants.rs b/rust/main/utils/run-locally/src/invariants.rs similarity index 100% rename from rust/utils/run-locally/src/invariants.rs rename to rust/main/utils/run-locally/src/invariants.rs diff --git a/rust/utils/run-locally/src/invariants/common.rs b/rust/main/utils/run-locally/src/invariants/common.rs similarity index 100% rename from rust/utils/run-locally/src/invariants/common.rs rename to rust/main/utils/run-locally/src/invariants/common.rs diff --git a/rust/utils/run-locally/src/invariants/post_startup_invariants.rs b/rust/main/utils/run-locally/src/invariants/post_startup_invariants.rs similarity index 100% rename from rust/utils/run-locally/src/invariants/post_startup_invariants.rs rename to rust/main/utils/run-locally/src/invariants/post_startup_invariants.rs diff --git a/rust/utils/run-locally/src/invariants/termination_invariants.rs b/rust/main/utils/run-locally/src/invariants/termination_invariants.rs similarity index 99% rename from rust/utils/run-locally/src/invariants/termination_invariants.rs rename to rust/main/utils/run-locally/src/invariants/termination_invariants.rs index a1c3e6316..db3dae380 100644 --- a/rust/utils/run-locally/src/invariants/termination_invariants.rs +++ b/rust/main/utils/run-locally/src/invariants/termination_invariants.rs @@ -14,6 +14,7 @@ use crate::{fetch_metric, AGENT_LOGGING_DIR, ZERO_MERKLE_INSERTION_KATHY_MESSAGE /// Use the metrics to check if the relayer queues are empty and the expected /// number of messages have been sent. +#[allow(clippy::unnecessary_get_then_check)] // TODO: `rustc` 1.80.1 clippy issue pub fn termination_invariants_met( config: &Config, starting_relayer_balance: f64, diff --git a/rust/utils/run-locally/src/logging.rs b/rust/main/utils/run-locally/src/logging.rs similarity index 100% rename from rust/utils/run-locally/src/logging.rs rename to rust/main/utils/run-locally/src/logging.rs diff --git a/rust/utils/run-locally/src/main.rs b/rust/main/utils/run-locally/src/main.rs similarity index 96% rename from rust/utils/run-locally/src/main.rs rename to rust/main/utils/run-locally/src/main.rs index 7cfbce96c..13c8e4ab1 100644 --- a/rust/utils/run-locally/src/main.rs +++ b/rust/main/utils/run-locally/src/main.rs @@ -1,3 +1,5 @@ +#![allow(clippy::doc_lazy_continuation)] // TODO: `rustc` 1.80.1 clippy issue + //! Run this from the hyperlane-monorepo/rust directory using `cargo run -r -p //! run-locally`. //! @@ -86,8 +88,9 @@ const SEALEVEL_VALIDATOR_KEYS: &[&str] = &[ ]; const AGENT_BIN_PATH: &str = "target/debug"; -const INFRA_PATH: &str = "../typescript/infra"; -const MONOREPO_ROOT_PATH: &str = "../"; +const SOLANA_AGNET_BIN_PATH: &str = "../sealevel/target/debug/"; +const INFRA_PATH: &str = "../../typescript/infra"; +const MONOREPO_ROOT_PATH: &str = "../../"; const ZERO_MERKLE_INSERTION_KATHY_MESSAGES: u32 = 10; @@ -317,19 +320,13 @@ fn main() -> ExitCode { // this task takes a long time in the CI so run it in parallel log!("Building rust..."); - let build_rust = Program::new("cargo") + let build_main = Program::new("cargo") .cmd("build") .arg("features", "test-utils memory-profiling") .arg("bin", "relayer") .arg("bin", "validator") .arg("bin", "scraper") - .arg("bin", "init-db"); - let build_rust = if config.sealevel_enabled { - build_rust.arg("bin", "hyperlane-sealevel-client") - } else { - build_rust - }; - let build_rust = build_rust + .arg("bin", "init-db") .filter_logs(|l| !l.contains("workspace-inheritance")) .run(); @@ -346,7 +343,16 @@ fn main() -> ExitCode { .spawn("SQL", None); state.push_agent(postgres); - build_rust.join(); + build_main.join(); + if config.sealevel_enabled { + Program::new("cargo") + .working_dir("../sealevel") + .cmd("build") + .arg("bin", "hyperlane-sealevel-client") + .filter_logs(|l| !l.contains("workspace-inheritance")) + .run() + .join(); + } let solana_ledger_dir = tempdir().unwrap(); let solana_config_path = if let Some((solana_program_path, solana_path)) = solana_paths.clone() diff --git a/rust/utils/run-locally/src/metrics.rs b/rust/main/utils/run-locally/src/metrics.rs similarity index 100% rename from rust/utils/run-locally/src/metrics.rs rename to rust/main/utils/run-locally/src/metrics.rs diff --git a/rust/utils/run-locally/src/program.rs b/rust/main/utils/run-locally/src/program.rs similarity index 100% rename from rust/utils/run-locally/src/program.rs rename to rust/main/utils/run-locally/src/program.rs diff --git a/rust/utils/run-locally/src/solana.rs b/rust/main/utils/run-locally/src/solana.rs similarity index 92% rename from rust/utils/run-locally/src/solana.rs rename to rust/main/utils/run-locally/src/solana.rs index 0ccca4f64..e3c8956b7 100644 --- a/rust/utils/run-locally/src/solana.rs +++ b/rust/main/utils/run-locally/src/solana.rs @@ -11,7 +11,7 @@ use tempfile::{tempdir, NamedTempFile}; use crate::logging::log; use crate::program::Program; use crate::utils::{as_task, concat_path, AgentHandles, ArbitraryData, TaskHandle}; -use crate::AGENT_BIN_PATH; +use crate::SOLANA_AGNET_BIN_PATH; /// The Solana CLI tool version to download and use. const SOLANA_CLI_VERSION: &str = "1.14.20"; @@ -48,12 +48,13 @@ const SOLANA_HYPERLANE_PROGRAMS: &[&str] = &[ "hyperlane-sealevel-igp", ]; -const SOLANA_KEYPAIR: &str = "config/test-sealevel-keys/test_deployer-keypair.json"; -const SOLANA_DEPLOYER_ACCOUNT: &str = "config/test-sealevel-keys/test_deployer-account.json"; +const SOLANA_KEYPAIR: &str = "../main/config/test-sealevel-keys/test_deployer-keypair.json"; +const SOLANA_DEPLOYER_ACCOUNT: &str = + "../main/config/test-sealevel-keys/test_deployer-account.json"; const SOLANA_WARPROUTE_TOKEN_CONFIG_FILE: &str = - "sealevel/environments/local-e2e/warp-routes/testwarproute/token-config.json"; -const SOLANA_CHAIN_CONFIG_FILE: &str = "sealevel/environments/local-e2e/chain-config.json"; -const SOLANA_ENVS_DIR: &str = "sealevel/environments"; + "../sealevel/environments/local-e2e/warp-routes/testwarproute/token-config.json"; +const SOLANA_CHAIN_CONFIG_FILE: &str = "../sealevel/environments/local-e2e/chain-config.json"; +const SOLANA_ENVS_DIR: &str = "../sealevel/environments"; const SOLANA_ENV_NAME: &str = "local-e2e"; @@ -66,7 +67,7 @@ const SOLANA_REMOTE_CHAIN_ID: &str = "13376"; pub const SOLANA_CHECKPOINT_LOCATION: &str = "/tmp/test_sealevel_checkpoints_0x70997970c51812dc3a010c7d01b50e0d17dc79c8"; -const SOLANA_OVERHEAD_CONFIG_FILE: &str = "sealevel/environments/local-e2e/overheads.json"; +const SOLANA_OVERHEAD_CONFIG_FILE: &str = "../sealevel/environments/local-e2e/overheads.json"; // Install the CLI tools and return the path to the bin dir. #[apply(as_task)] @@ -159,7 +160,7 @@ pub fn build_solana_programs(solana_cli_tools_path: PathBuf) -> PathBuf { for &path in SOLANA_HYPERLANE_PROGRAMS { build_sbf .clone() - .working_dir(concat_path("sealevel/programs", path)) + .working_dir(concat_path("../sealevel/programs", path)) .run() .join(); } @@ -282,6 +283,7 @@ pub fn start_solana_test_validator( } #[apply(as_task)] +#[allow(clippy::get_first)] // TODO: `rustc` 1.80.1 clippy issue pub fn initiate_solana_hyperlane_transfer( solana_cli_tools_path: PathBuf, solana_config_path: PathBuf, @@ -359,13 +361,18 @@ pub fn solana_termination_invariants_met( .join("\n") .contains("Message delivered") } - fn sealevel_client(solana_cli_tools_path: &Path, solana_config_path: &Path) -> Program { - Program::new(concat_path(AGENT_BIN_PATH, "hyperlane-sealevel-client")) - .env("PATH", updated_path(solana_cli_tools_path)) - .env("RUST_BACKTRACE", "1") - .arg("config", solana_config_path.to_str().unwrap()) - .arg("keypair", SOLANA_KEYPAIR) + Program::new(concat_path( + SOLANA_AGNET_BIN_PATH, + "hyperlane-sealevel-client", + )) + .env("PATH", updated_path(solana_cli_tools_path)) + .env("RUST_BACKTRACE", "1") + .arg("config", solana_config_path.to_str().unwrap()) + .arg( + "keypair", + "config/test-sealevel-keys/test_deployer-keypair.json", + ) } fn updated_path(solana_cli_tools_path: &Path) -> String { diff --git a/rust/utils/run-locally/src/utils.rs b/rust/main/utils/run-locally/src/utils.rs similarity index 100% rename from rust/utils/run-locally/src/utils.rs rename to rust/main/utils/run-locally/src/utils.rs diff --git a/rust-toolchain b/rust/rust-toolchain similarity index 100% rename from rust-toolchain rename to rust/rust-toolchain diff --git a/rust/sealevel/.cargo/config.toml b/rust/sealevel/.cargo/config.toml new file mode 100644 index 000000000..bff29e6e1 --- /dev/null +++ b/rust/sealevel/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["--cfg", "tokio_unstable"] diff --git a/rust/sealevel/.vscode/extensions.json b/rust/sealevel/.vscode/extensions.json new file mode 100644 index 000000000..c8e7623ea --- /dev/null +++ b/rust/sealevel/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "rust-lang.rust-analyzer", + "tamasfe.even-better-toml", + "rust-lang.rust-analyzer", + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [] +} diff --git a/rust/sealevel/.vscode/settings.json b/rust/sealevel/.vscode/settings.json new file mode 100644 index 000000000..785253018 --- /dev/null +++ b/rust/sealevel/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.exclude": { + "target": true, + }, +} diff --git a/rust/sealevel/Cargo.lock b/rust/sealevel/Cargo.lock new file mode 100644 index 000000000..80489fde2 --- /dev/null +++ b/rust/sealevel/Cargo.lock @@ -0,0 +1,7093 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "access-control" +version = "0.1.0" +dependencies = [ + "solana-program", +] + +[[package]] +name = "account-utils" +version = "0.1.0" +dependencies = [ + "borsh", + "solana-program", + "spl-type-length-value", +] + +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array 0.14.7", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" + +[[package]] +name = "arrayref" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "async-compression" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-mutex" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-rwlock" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261803dcc39ba9e72760ba6e16d0199b1eef9fc44e81bffabbebb9f5aea3906c" +dependencies = [ + "async-mutex", + "event-listener", +] + +[[package]] +name = "async-trait" +version = "0.1.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "auto_impl" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base58" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" + +[[package]] +name = "base58check" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee2fe4c9a0c84515f136aaae2466744a721af6d63339c18689d9e995d74d99b" +dependencies = [ + "base58", + "sha2 0.8.2", +] + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1" + +[[package]] +name = "bigdecimal" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d712318a27c7150326677b321a5fa91b55f6d9034ffd67f20319e147d40cee" +dependencies = [ + "autocfg", + "libm", + "num-bigint 0.4.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "bitvec" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" +dependencies = [ + "either", + "radium 0.3.0", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium 0.7.0", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake3" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding 0.1.5", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding 0.2.1", + "generic-array 0.14.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2 1.0.86", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "brotli" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "git+https://github.com/fitzgen/bumpalo?tag=3.14.0#c610d5adc54b9428465d72c4666c305df04c792a" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "bytemuck" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +dependencies = [ + "serde", +] + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "caps" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" +dependencies = [ + "libc", + "thiserror", +] + +[[package]] +name = "cargo-platform" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "chrono-humanize" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799627e6b4d27827a814e837b9d8a504832086081806d45b1afa34dc982b023b" +dependencies = [ + "chrono", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap 0.11.0", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_lex 0.2.4", + "indexmap 1.9.3", + "once_cell", + "strsim 0.10.0", + "termcolor", + "textwrap 0.16.1", +] + +[[package]] +name = "clap" +version = "4.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80932e03c33999b9235edb8655bc9df3204adc9887c2f95b50cb1deb9fd54253" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c0db58c659eef1c73e444d298c27322a1b52f6927d2ad470c0c0f96fa7b8fa" +dependencies = [ + "anstream", + "anstyle", + "clap_lex 0.6.0", + "strsim 0.10.0", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck 0.4.1", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "coins-bip32" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634c509653de24b439672164bbf56f5f582a2ab0e313d3b0f6af0b7345cf2560" +dependencies = [ + "bincode", + "bs58 0.4.0", + "coins-core", + "digest 0.10.7", + "getrandom 0.2.15", + "hmac 0.12.1", + "k256", + "lazy_static", + "serde", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "coins-bip39" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a11892bcac83b4c6e95ab84b5b06c76d9d70ad73548dd07418269c5c7977171" +dependencies = [ + "bitvec 0.17.4", + "coins-bip32", + "getrandom 0.2.15", + "hex", + "hmac 0.12.1", + "pbkdf2 0.11.0", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "coins-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94090a6663f224feae66ab01e41a2555a8296ee07b5f20dab8888bdefc9f617" +dependencies = [ + "base58check", + "base64 0.12.3", + "bech32", + "blake2", + "digest 0.10.7", + "generic-array 0.14.7", + "hex", + "ripemd", + "serde", + "serde_derive", + "sha2 0.10.8", + "sha3 0.10.8", + "thiserror", +] + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.2" +source = "git+https://github.com/Eclipse-Laboratories-Inc/curve25519-dalek?branch=v3.2.2-relax-zeroize#5154e5d02be0d9a7486dde86d67ff0327511c717" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "dashmap" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +dependencies = [ + "cfg-if", + "num_cpus", + "rayon", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid 0.7.1", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid 0.9.6", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint 0.4.6", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derivation-path" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" + +[[package]] +name = "derive-new" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "dialoguer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" +dependencies = [ + "console", + "shell-words", + "tempfile", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "dir-diff" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ad16bf5f84253b50d6557681c58c3ab67c47c77d39fed9aeb56e947290bd10" +dependencies = [ + "walkdir", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "eager" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ecdsa-signature" +version = "0.1.0" +dependencies = [ + "getrandom 0.2.15", + "hyperlane-core", + "solana-program", + "thiserror", +] + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "git+https://github.com/Eclipse-Laboratories-Inc/ed25519-dalek?branch=main#7529d65506147b6cb24ca6d8f4fc062cac33b395" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek-bip32" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" +dependencies = [ + "derivation-path", + "ed25519-dalek", + "hmac 0.12.1", + "sha2 0.10.8", +] + +[[package]] +name = "educe" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0042ff8246a363dbe77d2ceedb073339e85a804b9a47636c6e016a9a32c05f" +dependencies = [ + "enum-ordinalize", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der 0.6.1", + "digest 0.10.7", + "ff", + "generic-array 0.14.7", + "group", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-iterator" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2953d1df47ac0eb70086ccabf0275aa8da8591a28bd358ee2b52bd9f9e3ff9e9" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8958699f9359f0b04e691a13850d48b7de329138023876d07cbd024c2c820598" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "enum-ordinalize" +version = "3.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "eth-keystore" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" +dependencies = [ + "aes", + "ctr", + "digest 0.10.7", + "hex", + "hmac 0.12.1", + "pbkdf2 0.11.0", + "rand 0.8.5", + "scrypt", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3 0.10.8", + "thiserror", + "uuid", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3 0.10.8", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "ethers" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "ethers-addressbook", + "ethers-contract", + "ethers-core", + "ethers-etherscan", + "ethers-middleware", + "ethers-providers", + "ethers-signers", +] + +[[package]] +name = "ethers-addressbook" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "ethers-core", + "once_cell", + "serde", + "serde_json", +] + +[[package]] +name = "ethers-contract" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "ethers-contract-abigen", + "ethers-contract-derive", + "ethers-core", + "ethers-providers", + "futures-util", + "hex", + "once_cell", + "pin-project", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "ethers-contract-abigen" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "Inflector", + "cfg-if", + "dunce", + "ethers-core", + "eyre", + "getrandom 0.2.15", + "hex", + "proc-macro2 1.0.86", + "quote 1.0.37", + "regex", + "reqwest", + "serde", + "serde_json", + "syn 1.0.109", + "toml", + "url", + "walkdir", +] + +[[package]] +name = "ethers-contract-derive" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "ethers-contract-abigen", + "ethers-core", + "hex", + "proc-macro2 1.0.86", + "quote 1.0.37", + "serde_json", + "syn 1.0.109", +] + +[[package]] +name = "ethers-core" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "arrayvec", + "bytes", + "cargo_metadata", + "chrono", + "convert_case 0.6.0", + "elliptic-curve", + "ethabi", + "generic-array 0.14.7", + "hex", + "k256", + "once_cell", + "open-fastrlp", + "proc-macro2 1.0.86", + "rand 0.8.5", + "rlp", + "rlp-derive", + "serde", + "serde_json", + "strum 0.24.1", + "syn 1.0.109", + "thiserror", + "tiny-keccak", + "unicode-xid 0.2.5", +] + +[[package]] +name = "ethers-etherscan" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "ethers-core", + "getrandom 0.2.15", + "reqwest", + "semver", + "serde", + "serde-aux", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "ethers-middleware" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "async-trait", + "auto_impl 0.5.0", + "ethers-contract", + "ethers-core", + "ethers-etherscan", + "ethers-providers", + "ethers-signers", + "futures-locks", + "futures-util", + "instant", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "url", +] + +[[package]] +name = "ethers-providers" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "async-trait", + "auto_impl 1.2.0", + "base64 0.13.1", + "ethers-core", + "futures-core", + "futures-timer", + "futures-util", + "getrandom 0.2.15", + "hashers", + "hex", + "http", + "once_cell", + "parking_lot 0.11.2", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-timer", + "web-sys", + "ws_stream_wasm", +] + +[[package]] +name = "ethers-signers" +version = "1.0.2" +source = "git+https://github.com/hyperlane-xyz/ethers-rs?tag=2024-04-25#361b69b9561e11eb3cf8000a51de1985e2571785" +dependencies = [ + "async-trait", + "coins-bip32", + "coins-bip39", + "elliptic-curve", + "eth-keystore", + "ethers-core", + "hex", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "eyre" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane#3c2a89084ccfc27b82fda29007b4e27215a75cb1" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "flate2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-locks" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" +dependencies = [ + "futures-channel", + "futures-task", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "goblin" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.5.0", + "slab", + "tokio", + "tokio-util 0.7.12", + "tracing", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashers" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +dependencies = [ + "fxhash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "histogram" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.7", + "hmac 0.8.1", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.7", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyperlane-core" +version = "0.1.0" +dependencies = [ + "async-rwlock", + "async-trait", + "auto_impl 1.2.0", + "bigdecimal", + "borsh", + "bs58 0.5.1", + "bytes", + "convert_case 0.6.0", + "derive-new", + "derive_more", + "eyre", + "fixed-hash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.2.15", + "hex", + "itertools 0.12.1", + "num 0.4.3", + "num-derive 0.4.2", + "num-traits", + "serde", + "serde_json", + "sha3 0.10.8", + "strum 0.26.3", + "thiserror", + "tiny-keccak", + "tracing", + "typetag", + "uint", +] + +[[package]] +name = "hyperlane-sealevel-client" +version = "0.1.0" +dependencies = [ + "account-utils", + "bincode", + "borsh", + "bs58 0.5.1", + "clap 4.4.17", + "ethers", + "hex", + "hyperlane-core", + "hyperlane-sealevel-connection-client", + "hyperlane-sealevel-hello-world", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-multisig-ism-message-id", + "hyperlane-sealevel-token", + "hyperlane-sealevel-token-collateral", + "hyperlane-sealevel-token-lib", + "hyperlane-sealevel-token-native", + "hyperlane-sealevel-validator-announce", + "pretty_env_logger", + "serde", + "serde_json", + "solana-clap-utils", + "solana-cli-config", + "solana-client", + "solana-program", + "solana-sdk", + "solana-transaction-status", +] + +[[package]] +name = "hyperlane-sealevel-connection-client" +version = "0.1.0" +dependencies = [ + "access-control", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-mailbox", + "solana-program", +] + +[[package]] +name = "hyperlane-sealevel-hello-world" +version = "0.1.0" +dependencies = [ + "access-control", + "account-utils", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-connection-client", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "hyperlane-test-utils", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-noop", +] + +[[package]] +name = "hyperlane-sealevel-igp" +version = "0.1.0" +dependencies = [ + "access-control", + "account-utils", + "borsh", + "getrandom 0.2.15", + "hyperlane-core", + "num-derive 0.4.2", + "num-traits", + "serde", + "serializable-account-meta", + "solana-program", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-igp-test" +version = "0.1.0" +dependencies = [ + "access-control", + "account-utils", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-igp", + "hyperlane-test-utils", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", +] + +[[package]] +name = "hyperlane-sealevel-interchain-security-module-interface" +version = "0.1.0" +dependencies = [ + "borsh", + "solana-program", + "spl-type-length-value", +] + +[[package]] +name = "hyperlane-sealevel-mailbox" +version = "0.1.0" +dependencies = [ + "access-control", + "account-utils", + "base64 0.21.7", + "blake3", + "borsh", + "getrandom 0.2.15", + "hyperlane-core", + "hyperlane-sealevel-interchain-security-module-interface", + "hyperlane-sealevel-message-recipient-interface", + "itertools 0.13.0", + "log", + "num-derive 0.4.2", + "num-traits", + "proc-macro-crate 1.2.1", + "serde", + "serializable-account-meta", + "solana-program", + "spl-noop", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-mailbox-test" +version = "0.1.0" +dependencies = [ + "access-control", + "account-utils", + "base64 0.21.7", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-interchain-security-module-interface", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "hyperlane-sealevel-test-ism", + "hyperlane-sealevel-test-send-receiver", + "hyperlane-test-utils", + "itertools 0.13.0", + "log", + "num-derive 0.4.2", + "num-traits", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-noop", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-message-recipient-interface" +version = "0.1.0" +dependencies = [ + "borsh", + "getrandom 0.2.15", + "hyperlane-core", + "solana-program", + "spl-type-length-value", +] + +[[package]] +name = "hyperlane-sealevel-multisig-ism-message-id" +version = "0.1.0" +dependencies = [ + "access-control", + "account-utils", + "borsh", + "ecdsa-signature", + "hex", + "hyperlane-core", + "hyperlane-sealevel-interchain-security-module-interface", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-multisig-ism-message-id", + "hyperlane-test-utils", + "multisig-ism", + "num-derive 0.4.2", + "num-traits", + "rand 0.8.5", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-test-ism" +version = "0.1.0" +dependencies = [ + "account-utils", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-interchain-security-module-interface", + "hyperlane-sealevel-mailbox", + "hyperlane-test-transaction-utils", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", +] + +[[package]] +name = "hyperlane-sealevel-test-send-receiver" +version = "0.1.0" +dependencies = [ + "account-utils", + "borsh", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "hyperlane-test-utils", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-noop", +] + +[[package]] +name = "hyperlane-sealevel-token" +version = "0.1.0" +dependencies = [ + "account-utils", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-connection-client", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "hyperlane-sealevel-test-ism", + "hyperlane-sealevel-token-lib", + "hyperlane-test-utils", + "num-derive 0.4.2", + "num-traits", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-associated-token-account", + "spl-noop", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-token-collateral" +version = "0.1.0" +dependencies = [ + "account-utils", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-connection-client", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "hyperlane-sealevel-test-ism", + "hyperlane-sealevel-token-lib", + "hyperlane-test-utils", + "num-derive 0.4.2", + "num-traits", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-associated-token-account", + "spl-noop", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-token-lib" +version = "0.1.0" +dependencies = [ + "access-control", + "account-utils", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-connection-client", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "num-derive 0.4.2", + "num-traits", + "serializable-account-meta", + "solana-program", + "spl-associated-token-account", + "spl-noop", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-token-native" +version = "0.1.0" +dependencies = [ + "account-utils", + "borsh", + "hyperlane-core", + "hyperlane-sealevel-connection-client", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "hyperlane-sealevel-test-ism", + "hyperlane-sealevel-token-lib", + "hyperlane-test-utils", + "num-derive 0.4.2", + "num-traits", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-noop", + "tarpc", + "thiserror", +] + +[[package]] +name = "hyperlane-sealevel-validator-announce" +version = "0.1.0" +dependencies = [ + "account-utils", + "borsh", + "ecdsa-signature", + "hex", + "hyperlane-core", + "hyperlane-sealevel-mailbox", + "hyperlane-test-utils", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "hyperlane-test-transaction-utils" +version = "0.1.0" +dependencies = [ + "solana-program", + "solana-program-test", + "solana-sdk", +] + +[[package]] +name = "hyperlane-test-utils" +version = "0.1.0" +dependencies = [ + "borsh", + "hyperlane-core", + "hyperlane-sealevel-igp", + "hyperlane-sealevel-interchain-security-module-interface", + "hyperlane-sealevel-mailbox", + "hyperlane-sealevel-message-recipient-interface", + "hyperlane-sealevel-test-ism", + "hyperlane-test-transaction-utils", + "serializable-account-meta", + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-noop", + "spl-token-2022", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane#3c2a89084ccfc27b82fda29007b4e27215a75cb1" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane#3c2a89084ccfc27b82fda29007b4e27215a75cb1" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane#3c2a89084ccfc27b82fda29007b4e27215a75cb1" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "index_list" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e6ba961c14e98151cd6416dd3685efe786a94c38bc1a535c06ceff0a1600813" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "indicatif" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b" +dependencies = [ + "console", + "lazy_static", + "number_prefix", + "regex", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "inventory" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2 0.10.8", + "sha3 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.5.3", +] + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +dependencies = [ + "hashbrown 0.12.3", +] + +[[package]] +name = "lz4" +version = "1.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958b4caa893816eea05507c20cfe47574a43d9a697138a7872990bba8a0ece68" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109de74d5d2353660401699a4174a4ff23fcc649caf553df71933c7fb45ad868" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "modular-bitfield" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" +dependencies = [ + "modular-bitfield-impl", + "static_assertions", +] + +[[package]] +name = "modular-bitfield-impl" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "multisig-ism" +version = "0.1.0" +dependencies = [ + "borsh", + "ecdsa-signature", + "hex", + "hyperlane-core", + "solana-program", + "spl-type-length-value", + "thiserror", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex 0.2.4", + "num-integer", + "num-iter", + "num-rational 0.2.4", + "num-traits", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint 0.4.6", + "num-complex 0.4.6", + "num-integer", + "num-iter", + "num-rational 0.4.2", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint 0.4.6", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.9", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.2.1", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate 1.2.1", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl 1.2.0", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "opentelemetry" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "js-sys", + "lazy_static", + "percent-encoding", + "pin-project", + "rand 0.8.5", + "thiserror", +] + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "ouroboros" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1358bd1558bd2a083fed428ffeda486fbfb323e698cdda7794259d592ca72db" +dependencies = [ + "aliasable", + "ouroboros_macro", +] + +[[package]] +name = "ouroboros_macro" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" +dependencies = [ + "Inflector", + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec 1.0.1", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.3", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", + "hmac 0.12.1", + "password-hash", + "sha2 0.10.8", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "percentage" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" +dependencies = [ + "num 0.2.1", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der 0.5.1", + "spki 0.5.4", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug 0.3.1", + "universal-hash", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger 0.10.2", + "log", +] + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane#3c2a89084ccfc27b82fda29007b4e27215a75cb1" +dependencies = [ + "fixed-hash 0.8.0 (git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane)", + "impl-codec 0.6.0 (git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane)", + "impl-rlp 0.3.0 (git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane)", + "impl-serde 0.4.0 (git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane)", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +dependencies = [ + "once_cell", + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qstring" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "quinn" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b435e71d9bfa0d8889927231970c51fb89c58fa63bffcab117c9c7a41e5ef8f" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "fxhash", + "quinn-proto", + "quinn-udp", + "rustls 0.20.9", + "thiserror", + "tokio", + "tracing", + "webpki", +] + +[[package]] +name = "quinn-proto" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fce546b9688f767a57530652488420d419a8b1f44a478b451c3d1ab6d992a55" +dependencies = [ + "bytes", + "fxhash", + "rand 0.8.5", + "ring 0.16.20", + "rustls 0.20.9", + "rustls-native-certs", + "rustls-pemfile 0.2.1", + "slab", + "thiserror", + "tinyvec", + "tracing", + "webpki", +] + +[[package]] +name = "quinn-udp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07946277141531aea269befd949ed16b2c85a780ba1043244eda0969e538e54" +dependencies = [ + "futures-util", + "libc", + "quinn-proto", + "socket2 0.4.10", + "tokio", + "tracing", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2 1.0.86", +] + +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rcgen" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" +dependencies = [ + "pem", + "ring 0.16.20", + "time", + "yasna", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "async-compression", + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util 0.7.12", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.4", + "winreg", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac 0.12.1", + "zeroize", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "git+https://github.com/hyperlane-xyz/parity-common.git?branch=hyperlane#3c2a89084ccfc27b82fda29007b4e27215a75cb1" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "rpassword" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956" +dependencies = [ + "libc", + "serde", + "serde_json", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.38.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct", + "webpki", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring 0.17.8", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "scrypt" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" +dependencies = [ + "hmac 0.12.1", + "pbkdf2 0.11.0", + "salsa20", + "sha2 0.10.8", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der 0.6.1", + "generic-array 0.14.7", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-aux" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d2e8bfba469d06512e11e3311d4d051a4a387a5b42d010404fecf3200321c95" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap 1.9.3", + "ryu", + "serde", + "yaml-rust", +] + +[[package]] +name = "serializable-account-meta" +version = "0.1.0" +dependencies = [ + "borsh", + "solana-program", +] + +[[package]] +name = "sha-1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.1", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.1", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "solana-account-decoder" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "Inflector", + "base64 0.13.1", + "bincode", + "bs58 0.4.0", + "bv", + "lazy_static", + "serde", + "serde_derive", + "serde_json", + "solana-address-lookup-table-program", + "solana-config-program", + "solana-sdk", + "solana-vote-program", + "spl-token", + "spl-token-2022", + "thiserror", + "zstd", +] + +[[package]] +name = "solana-address-lookup-table-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "bytemuck", + "log", + "num-derive 0.3.3", + "num-traits", + "rustc_version", + "serde", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-program", + "solana-program-runtime", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-banks-client" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "borsh", + "futures", + "solana-banks-interface", + "solana-program", + "solana-sdk", + "tarpc", + "thiserror", + "tokio", + "tokio-serde", +] + +[[package]] +name = "solana-banks-interface" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "serde", + "solana-sdk", + "tarpc", +] + +[[package]] +name = "solana-banks-server" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "crossbeam-channel", + "futures", + "solana-banks-interface", + "solana-client", + "solana-runtime", + "solana-sdk", + "solana-send-transaction-service", + "tarpc", + "tokio", + "tokio-serde", + "tokio-stream", +] + +[[package]] +name = "solana-bpf-loader-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "byteorder", + "libsecp256k1", + "log", + "solana-measure", + "solana-metrics", + "solana-program-runtime", + "solana-sdk", + "solana-zk-token-sdk", + "solana_rbpf", + "thiserror", +] + +[[package]] +name = "solana-bucket-map" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "log", + "memmap2", + "modular-bitfield", + "rand 0.7.3", + "solana-measure", + "solana-sdk", + "tempfile", +] + +[[package]] +name = "solana-clap-utils" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "chrono", + "clap 2.34.0", + "rpassword", + "solana-perf", + "solana-remote-wallet", + "solana-sdk", + "thiserror", + "tiny-bip39", + "uriparse", + "url", +] + +[[package]] +name = "solana-cli-config" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "dirs-next", + "lazy_static", + "serde", + "serde_derive", + "serde_yaml", + "solana-clap-utils", + "solana-sdk", + "url", +] + +[[package]] +name = "solana-client" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "async-mutex", + "async-trait", + "base64 0.13.1", + "bincode", + "bs58 0.4.0", + "bytes", + "clap 2.34.0", + "crossbeam-channel", + "enum_dispatch", + "futures", + "futures-util", + "indexmap 1.9.3", + "indicatif", + "itertools 0.10.5", + "jsonrpc-core", + "lazy_static", + "log", + "quinn", + "quinn-proto", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rayon", + "reqwest", + "rustls 0.20.9", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-clap-utils", + "solana-faucet", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-sdk", + "solana-streamer", + "solana-transaction-status", + "solana-version", + "solana-vote-program", + "spl-token-2022", + "thiserror", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tungstenite", + "url", +] + +[[package]] +name = "solana-compute-budget-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "solana-program-runtime", + "solana-sdk", +] + +[[package]] +name = "solana-config-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "chrono", + "serde", + "serde_derive", + "solana-program-runtime", + "solana-sdk", +] + +[[package]] +name = "solana-faucet" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "byteorder", + "clap 2.34.0", + "crossbeam-channel", + "log", + "serde", + "serde_derive", + "solana-clap-utils", + "solana-cli-config", + "solana-logger", + "solana-metrics", + "solana-sdk", + "solana-version", + "spl-memo 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror", + "tokio", +] + +[[package]] +name = "solana-frozen-abi" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "ahash", + "blake3", + "block-buffer 0.9.0", + "bs58 0.4.0", + "bv", + "byteorder", + "cc", + "either", + "generic-array 0.14.7", + "getrandom 0.1.16", + "hashbrown 0.12.3", + "im", + "lazy_static", + "log", + "memmap2", + "once_cell", + "rand_core 0.6.4", + "rustc_version", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "solana-frozen-abi-macro", + "subtle", + "thiserror", +] + +[[package]] +name = "solana-frozen-abi-macro" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "solana-logger" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "env_logger 0.9.3", + "lazy_static", + "log", +] + +[[package]] +name = "solana-measure" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "log", + "solana-sdk", +] + +[[package]] +name = "solana-metrics" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "crossbeam-channel", + "gethostname", + "lazy_static", + "log", + "reqwest", + "solana-sdk", +] + +[[package]] +name = "solana-net-utils" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "clap 3.2.25", + "crossbeam-channel", + "log", + "nix", + "rand 0.7.3", + "serde", + "serde_derive", + "socket2 0.4.10", + "solana-logger", + "solana-sdk", + "solana-version", + "tokio", + "url", +] + +[[package]] +name = "solana-perf" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "ahash", + "bincode", + "bv", + "caps", + "curve25519-dalek", + "dlopen", + "dlopen_derive", + "fnv", + "lazy_static", + "libc", + "log", + "nix", + "rand 0.7.3", + "rayon", + "serde", + "solana-metrics", + "solana-rayon-threadlimit", + "solana-sdk", + "solana-vote-program", +] + +[[package]] +name = "solana-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "base64 0.13.1", + "bincode", + "bitflags 1.3.2", + "blake3", + "borsh", + "borsh-derive", + "bs58 0.4.0", + "bv", + "bytemuck", + "cc", + "console_error_panic_hook", + "console_log", + "curve25519-dalek", + "getrandom 0.2.15", + "itertools 0.10.5", + "js-sys", + "lazy_static", + "libc", + "libsecp256k1", + "log", + "memoffset", + "num-derive 0.3.3", + "num-traits", + "parking_lot 0.12.3", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "sha3 0.10.8", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk-macro", + "thiserror", + "tiny-bip39", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-program-runtime" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "base64 0.13.1", + "bincode", + "eager", + "enum-iterator", + "itertools 0.10.5", + "libc", + "libloading", + "log", + "num-derive 0.3.3", + "num-traits", + "rand 0.7.3", + "rustc_version", + "serde", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-measure", + "solana-metrics", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-program-test" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "assert_matches", + "async-trait", + "base64 0.13.1", + "bincode", + "chrono-humanize", + "log", + "serde", + "solana-banks-client", + "solana-banks-server", + "solana-bpf-loader-program", + "solana-logger", + "solana-program-runtime", + "solana-runtime", + "solana-sdk", + "solana-vote-program", + "thiserror", + "tokio", +] + +[[package]] +name = "solana-rayon-threadlimit" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "lazy_static", + "num_cpus", +] + +[[package]] +name = "solana-remote-wallet" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "console", + "dialoguer", + "log", + "num-derive 0.3.3", + "num-traits", + "parking_lot 0.12.3", + "qstring", + "semver", + "solana-sdk", + "thiserror", + "uriparse", +] + +[[package]] +name = "solana-runtime" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "arrayref", + "bincode", + "blake3", + "bv", + "bytemuck", + "byteorder", + "bzip2", + "crossbeam-channel", + "dashmap", + "dir-diff", + "flate2", + "fnv", + "im", + "index_list", + "itertools 0.10.5", + "lazy_static", + "log", + "lru", + "lz4", + "memmap2", + "num-derive 0.3.3", + "num-traits", + "num_cpus", + "once_cell", + "ouroboros", + "rand 0.7.3", + "rayon", + "regex", + "rustc_version", + "serde", + "serde_derive", + "solana-address-lookup-table-program", + "solana-bucket-map", + "solana-compute-budget-program", + "solana-config-program", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-measure", + "solana-metrics", + "solana-program-runtime", + "solana-rayon-threadlimit", + "solana-sdk", + "solana-stake-program", + "solana-vote-program", + "solana-zk-token-proof-program", + "solana-zk-token-sdk", + "strum 0.24.1", + "strum_macros 0.24.3", + "symlink", + "tar", + "tempfile", + "thiserror", + "zstd", +] + +[[package]] +name = "solana-sdk" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "assert_matches", + "base64 0.13.1", + "bincode", + "bitflags 1.3.2", + "borsh", + "bs58 0.4.0", + "bytemuck", + "byteorder", + "chrono", + "derivation-path", + "digest 0.10.7", + "ed25519-dalek", + "ed25519-dalek-bip32", + "generic-array 0.14.7", + "hmac 0.12.1", + "itertools 0.10.5", + "js-sys", + "lazy_static", + "libsecp256k1", + "log", + "memmap2", + "num-derive 0.3.3", + "num-traits", + "pbkdf2 0.11.0", + "qstring", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "sha3 0.10.8", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-logger", + "solana-program", + "solana-sdk-macro", + "thiserror", + "uriparse", + "wasm-bindgen", +] + +[[package]] +name = "solana-sdk-macro" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bs58 0.4.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "solana-send-transaction-service" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "crossbeam-channel", + "log", + "solana-client", + "solana-measure", + "solana-metrics", + "solana-runtime", + "solana-sdk", +] + +[[package]] +name = "solana-stake-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "log", + "num-derive 0.3.3", + "num-traits", + "rustc_version", + "serde", + "serde_derive", + "solana-config-program", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-metrics", + "solana-program-runtime", + "solana-sdk", + "solana-vote-program", + "thiserror", +] + +[[package]] +name = "solana-streamer" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "crossbeam-channel", + "futures-util", + "histogram", + "indexmap 1.9.3", + "itertools 0.10.5", + "libc", + "log", + "nix", + "pem", + "percentage", + "pkcs8 0.8.0", + "quinn", + "rand 0.7.3", + "rcgen", + "rustls 0.20.9", + "solana-metrics", + "solana-perf", + "solana-sdk", + "thiserror", + "tokio", + "x509-parser", +] + +[[package]] +name = "solana-transaction-status" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "Inflector", + "base64 0.13.1", + "bincode", + "borsh", + "bs58 0.4.0", + "lazy_static", + "log", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-address-lookup-table-program", + "solana-measure", + "solana-metrics", + "solana-sdk", + "solana-vote-program", + "spl-associated-token-account", + "spl-memo 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "solana-version" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "log", + "rustc_version", + "semver", + "serde", + "serde_derive", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk", +] + +[[package]] +name = "solana-vote-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bincode", + "log", + "num-derive 0.3.3", + "num-traits", + "rustc_version", + "serde", + "serde_derive", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-metrics", + "solana-program-runtime", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-zk-token-proof-program" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "bytemuck", + "getrandom 0.1.16", + "num-derive 0.3.3", + "num-traits", + "solana-program-runtime", + "solana-sdk", + "solana-zk-token-sdk", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "1.14.13" +source = "git+https://github.com/hyperlane-xyz/solana.git?tag=hyperlane-1.14.13-2023-07-04#62a6421cab862c77b9ac7a8d93f54f8b5b223af7" +dependencies = [ + "aes-gcm-siv", + "arrayref", + "base64 0.13.1", + "bincode", + "bytemuck", + "byteorder", + "cipher", + "curve25519-dalek", + "getrandom 0.1.16", + "itertools 0.10.5", + "lazy_static", + "merlin", + "num-derive 0.3.3", + "num-traits", + "rand 0.7.3", + "serde", + "serde_json", + "sha3 0.9.1", + "solana-program", + "solana-sdk", + "subtle", + "thiserror", + "zeroize", +] + +[[package]] +name = "solana_rbpf" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80a28c5dfe7e8af38daa39d6561c8e8b9ed7a2f900951ebe7362ad6348d36c73" +dependencies = [ + "byteorder", + "combine", + "goblin", + "hash32", + "libc", + "log", + "rand 0.8.5", + "rustc-demangle", + "scroll", + "thiserror", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der 0.5.1", +] + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + +[[package]] +name = "spl-associated-token-account" +version = "1.1.2" +source = "git+https://github.com/hyperlane-xyz/solana-program-library.git?branch=hyperlane#5de3c060c276afb4e767111b3b42fbbf4a81d83f" +dependencies = [ + "assert_matches", + "borsh", + "num-derive 0.3.3", + "num-traits", + "solana-program", + "spl-token", + "spl-token-2022", + "thiserror", +] + +[[package]] +name = "spl-memo" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" +dependencies = [ + "solana-program", +] + +[[package]] +name = "spl-memo" +version = "3.0.1" +source = "git+https://github.com/hyperlane-xyz/solana-program-library.git?branch=hyperlane#5de3c060c276afb4e767111b3b42fbbf4a81d83f" +dependencies = [ + "solana-program", +] + +[[package]] +name = "spl-noop" +version = "0.1.3" +source = "git+https://github.com/hyperlane-xyz/solana-program-library.git?branch=hyperlane#5de3c060c276afb4e767111b3b42fbbf4a81d83f" +dependencies = [ + "solana-program", +] + +[[package]] +name = "spl-token" +version = "3.5.0" +source = "git+https://github.com/hyperlane-xyz/solana-program-library.git?branch=hyperlane#5de3c060c276afb4e767111b3b42fbbf4a81d83f" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.3.3", + "num-traits", + "num_enum 0.5.11", + "solana-program", + "thiserror", +] + +[[package]] +name = "spl-token-2022" +version = "0.5.0" +source = "git+https://github.com/hyperlane-xyz/solana-program-library.git?branch=hyperlane#5de3c060c276afb4e767111b3b42fbbf4a81d83f" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.3.3", + "num-traits", + "num_enum 0.5.11", + "solana-program", + "solana-zk-token-sdk", + "spl-memo 3.0.1 (git+https://github.com/hyperlane-xyz/solana-program-library.git?branch=hyperlane)", + "spl-token", + "thiserror", +] + +[[package]] +name = "spl-type-length-value" +version = "0.1.0" +source = "git+https://github.com/hyperlane-xyz/solana-program-library.git?branch=hyperlane#5de3c060c276afb4e767111b3b42fbbf4a81d83f" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.3.3", + "num-traits", + "num_enum 0.6.1", + "solana-program", + "thiserror", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros 0.24.3", +] + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck 0.4.1", + "proc-macro2 1.0.86", + "quote 1.0.37", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "rustversion", + "syn 2.0.77", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "symlink" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", + "unicode-xid 0.2.5", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tar" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tarpc" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38a012bed6fb9681d3bf71ffaa4f88f3b4b9ed3198cda6e4c8462d24d4bb80" +dependencies = [ + "anyhow", + "fnv", + "futures", + "humantime", + "opentelemetry", + "pin-project", + "rand 0.8.5", + "serde", + "static_assertions", + "tarpc-plugins", + "thiserror", + "tokio", + "tokio-serde", + "tokio-util 0.6.10", + "tracing", + "tracing-opentelemetry", +] + +[[package]] +name = "tarpc-plugins" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +dependencies = [ + "anyhow", + "hmac 0.8.1", + "once_cell", + "pbkdf2 0.4.0", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot 0.12.3", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.7", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.9", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-serde" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911a61637386b789af998ee23f50aa30d5fd7edcec8d6d3dedae5e5815205466" +dependencies = [ + "bincode", + "bytes", + "educe", + "futures-core", + "futures-sink", + "pin-project", + "serde", + "serde_json", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +dependencies = [ + "futures-util", + "log", + "rustls 0.20.9", + "tokio", + "tokio-rustls 0.23.4", + "tungstenite", + "webpki", + "webpki-roots 0.22.6", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "slab", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap 2.5.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-opentelemetry" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbbe89715c1dbbb790059e2565353978564924ee85017b5fff365c872ff6721f" +dependencies = [ + "once_cell", + "opentelemetry", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +dependencies = [ + "base64 0.13.1", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand 0.8.5", + "rustls 0.20.9", + "sha-1", + "thiserror", + "url", + "utf-8", + "webpki", + "webpki-roots 0.22.6", +] + +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "typetag" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba3b6e86ffe0054b2c44f2d86407388b933b16cb0a70eea3929420db1d9bbe" +dependencies = [ + "erased-serde", + "inventory", + "once_cell", + "serde", + "typetag-impl", +] + +[[package]] +name = "typetag-impl" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70b20a22c42c8f1cd23ce5e34f165d4d37038f5b663ad20fb6adbdf029172483" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "uriparse" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" +dependencies = [ + "fnv", + "lazy_static", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.15", + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote 1.0.37", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version", + "send_wrapper", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs", + "base64 0.13.1", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "xattr" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +dependencies = [ + "libc", + "linux-raw-sys", + "rustix", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/rust/Cargo.toml b/rust/sealevel/Cargo.toml similarity index 78% rename from rust/Cargo.toml rename to rust/sealevel/Cargo.toml index e449b1936..5887dc8d1 100644 --- a/rust/Cargo.toml +++ b/rust/sealevel/Cargo.toml @@ -1,50 +1,35 @@ [workspace] members = [ - "agents/relayer", - "agents/scraper", - "agents/validator", - "chains/hyperlane-cosmos", - "chains/hyperlane-ethereum", - "chains/hyperlane-fuel", - "chains/hyperlane-sealevel", - "ethers-prometheus", - "hyperlane-base", - "hyperlane-core", - "hyperlane-test", - "sealevel/client", - "sealevel/libraries/access-control", - "sealevel/libraries/account-utils", - "sealevel/libraries/ecdsa-signature", - "sealevel/libraries/hyperlane-sealevel-connection-client", - "sealevel/libraries/hyperlane-sealevel-token", - "sealevel/libraries/interchain-security-module-interface", - "sealevel/libraries/message-recipient-interface", - "sealevel/libraries/multisig-ism", - "sealevel/libraries/serializable-account-meta", - "sealevel/libraries/test-transaction-utils", - "sealevel/libraries/test-utils", - "sealevel/programs/hyperlane-sealevel-igp", - "sealevel/programs/hyperlane-sealevel-igp-test", - "sealevel/programs/hyperlane-sealevel-token", - "sealevel/programs/hyperlane-sealevel-token-collateral", - "sealevel/programs/hyperlane-sealevel-token-native", - "sealevel/programs/ism/multisig-ism-message-id", - "sealevel/programs/ism/test-ism", - "sealevel/programs/mailbox", - "sealevel/programs/mailbox-test", - "sealevel/programs/test-send-receiver", - "sealevel/programs/validator-announce", - "utils/abigen", - "utils/backtrace-oneline", - "utils/hex", - "utils/run-locally", + "client", + "libraries/access-control", + "libraries/account-utils", + "libraries/ecdsa-signature", + "libraries/hyperlane-sealevel-connection-client", + "libraries/hyperlane-sealevel-token", + "libraries/interchain-security-module-interface", + "libraries/message-recipient-interface", + "libraries/multisig-ism", + "libraries/serializable-account-meta", + "libraries/test-transaction-utils", + "libraries/test-utils", + "programs/hyperlane-sealevel-igp", + "programs/hyperlane-sealevel-igp-test", + "programs/hyperlane-sealevel-token", + "programs/hyperlane-sealevel-token-collateral", + "programs/hyperlane-sealevel-token-native", + "programs/ism/multisig-ism-message-id", + "programs/ism/test-ism", + "programs/mailbox", + "programs/mailbox-test", + "programs/test-send-receiver", + "programs/validator-announce", ] [workspace.package] documentation = "https://docs.hyperlane.xyz" edition = "2021" homepage = "https://hyperlane.xyz" -license-file = "../LICENSE.md" +license-file = "../../LICENSE.md" publish = false version = "0.1.0" @@ -67,25 +52,12 @@ color-eyre = "0.6" config = "0.13.3" console-subscriber = "0.2.0" convert_case = "0.6" -cosmrs = { version = "0.14", default-features = false, features = [ - "cosmwasm", - "rpc", - "tokio", - "grpc", -] } -cosmwasm-std = "*" crunchy = "0.2" ctrlc = "3.2" curve25519-dalek = { version = "~3.2", features = ["serde"] } derive-new = "0.5" -derive_builder = "0.12" -derive_more = "0.99" -dhat = "0.3.3" -ed25519-dalek = "~1.0" eyre = "=0.6.8" fixed-hash = "0.8.0" -fuels = "0.38" -fuels-code-gen = "0.38" futures = "0.3" futures-util = "0.3" generic-array = { version = "0.14", features = ["serde", "more_lengths"] } @@ -94,10 +66,6 @@ bech32 = "0.9.1" elliptic-curve = "0.12.3" getrandom = { version = "0.2", features = ["js"] } hex = "0.4.3" -http = "*" -hyper = "0.14" -hyper-tls = "0.5.0" -hyperlane-cosmwasm-interface = "=0.0.6-rc6" injective-protobuf = "0.2.2" injective-std = "0.1.5" itertools = "*" @@ -168,8 +136,6 @@ static_assertions = "1.1" strum = "0.26.2" strum_macros = "0.26.2" tempfile = "3.3" -tendermint = "0.32.2" -tendermint-rpc = { version = "0.32.0", features = ["http-client", "tokio"] } thiserror = "1.0" time = "0.3" tiny-keccak = "2.0.2" @@ -190,10 +156,8 @@ url = "2.3" walkdir = "2" warp = "0.3" which = "4.3" -ya-gcp = { version = "0.11.3", features = ["storage"] } +ya-gcp = { version = "0.11.1", features = ["storage"] } -## TODO: remove this -cosmwasm-schema = "1.2.7" [profile.release.package.access-control] overflow-checks = true @@ -272,11 +236,6 @@ features = ["legacy"] git = "https://github.com/hyperlane-xyz/ethers-rs" tag = "2024-04-25" -[workspace.dependencies.ethers-core] -features = [] -git = "https://github.com/hyperlane-xyz/ethers-rs" -tag = "2024-04-25" - [workspace.dependencies.ethers-providers] features = [] git = "https://github.com/hyperlane-xyz/ethers-rs" @@ -287,6 +246,11 @@ features = ["aws"] git = "https://github.com/hyperlane-xyz/ethers-rs" tag = "2024-04-25" +[patch.crates-io.bumpalo] +git = "https://github.com/fitzgen/bumpalo" +tag = "3.14.0" +version = "=3.14.0" + [patch.crates-io.curve25519-dalek] branch = "v3.2.2-relax-zeroize" git = "https://github.com/Eclipse-Laboratories-Inc/curve25519-dalek" @@ -391,13 +355,3 @@ version = "=0.5.0" version = "=0.1.0" git = "https://github.com/hyperlane-xyz/solana-program-library.git" branch = "hyperlane" - -[patch.crates-io.tendermint] -branch = "trevor/0.32.2-fork" -git = "https://github.com/hyperlane-xyz/tendermint-rs.git" -version = "=0.32.2" - -[patch.crates-io.tendermint-rpc] -branch = "trevor/0.32.2-fork" -git = "https://github.com/hyperlane-xyz/tendermint-rs.git" -version = "=0.32.2" diff --git a/rust/sealevel/client/Cargo.toml b/rust/sealevel/client/Cargo.toml index 95ba0650a..b799093ae 100644 --- a/rust/sealevel/client/Cargo.toml +++ b/rust/sealevel/client/Cargo.toml @@ -23,14 +23,30 @@ solana-sdk.workspace = true solana-transaction-status.workspace = true account-utils = { path = "../libraries/account-utils" } -hyperlane-core = { path = "../../hyperlane-core" } +hyperlane-core = { path = "../../main/hyperlane-core" } hyperlane-sealevel-connection-client = { path = "../libraries/hyperlane-sealevel-connection-client" } -hyperlane-sealevel-mailbox = { path = "../programs/mailbox", features = ["no-entrypoint", "serde"] } -hyperlane-sealevel-multisig-ism-message-id = { path = "../programs/ism/multisig-ism-message-id", features = ["no-entrypoint"] } -hyperlane-sealevel-token = { path = "../programs/hyperlane-sealevel-token", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../programs/hyperlane-sealevel-igp", features = ["no-entrypoint", "serde"] } -hyperlane-sealevel-token-collateral = { path = "../programs/hyperlane-sealevel-token-collateral", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../programs/mailbox", features = [ + "no-entrypoint", + "serde", +] } +hyperlane-sealevel-multisig-ism-message-id = { path = "../programs/ism/multisig-ism-message-id", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-token = { path = "../programs/hyperlane-sealevel-token", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../programs/hyperlane-sealevel-igp", features = [ + "no-entrypoint", + "serde", +] } +hyperlane-sealevel-token-collateral = { path = "../programs/hyperlane-sealevel-token-collateral", features = [ + "no-entrypoint", +] } hyperlane-sealevel-token-lib = { path = "../libraries/hyperlane-sealevel-token" } -hyperlane-sealevel-token-native = { path = "../programs/hyperlane-sealevel-token-native", features = ["no-entrypoint"] } -hyperlane-sealevel-validator-announce = { path = "../programs/validator-announce", features = ["no-entrypoint"] } -hyperlane-sealevel-hello-world = { path = "../programs/helloworld" } \ No newline at end of file +hyperlane-sealevel-token-native = { path = "../programs/hyperlane-sealevel-token-native", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-validator-announce = { path = "../programs/validator-announce", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-hello-world = { path = "../programs/helloworld" } diff --git a/rust/sealevel/client/src/warp_route.rs b/rust/sealevel/client/src/warp_route.rs index e40adfa57..723b1b592 100644 --- a/rust/sealevel/client/src/warp_route.rs +++ b/rust/sealevel/client/src/warp_route.rs @@ -294,6 +294,7 @@ impl RouterDeployer for WarpRouteDeployer { "--fee-payer", ctx.payer_keypair_path(), ]); + println!("running command: {:?}", cmd); let status = cmd .stdout(Stdio::inherit()) diff --git a/rust/sealevel/libraries/account-utils/src/lib.rs b/rust/sealevel/libraries/account-utils/src/lib.rs index c312ab1e7..697075691 100644 --- a/rust/sealevel/libraries/account-utils/src/lib.rs +++ b/rust/sealevel/libraries/account-utils/src/lib.rs @@ -128,6 +128,7 @@ where data_len }; + #[allow(unexpected_cfgs)] // TODO: `rustc` 1.80.1 issue if cfg!(target_os = "solana") { account.realloc(data_len + realloc_increment, false)?; } else { diff --git a/rust/sealevel/libraries/ecdsa-signature/Cargo.toml b/rust/sealevel/libraries/ecdsa-signature/Cargo.toml index 845bd745c..11b25b0da 100644 --- a/rust/sealevel/libraries/ecdsa-signature/Cargo.toml +++ b/rust/sealevel/libraries/ecdsa-signature/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" solana-program.workspace = true thiserror.workspace = true -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } # Required to allow dependencies `getrandom` but to preserve determinism required by programs, see # https://github.com/solana-foundation/developer-content/blob/main/docs/programs/lang-rust.md#depending-on-rand getrandom = { workspace = true, features = ["custom"] } diff --git a/rust/sealevel/libraries/hyperlane-sealevel-connection-client/Cargo.toml b/rust/sealevel/libraries/hyperlane-sealevel-connection-client/Cargo.toml index 0a8cc148a..8c7f0001c 100644 --- a/rust/sealevel/libraries/hyperlane-sealevel-connection-client/Cargo.toml +++ b/rust/sealevel/libraries/hyperlane-sealevel-connection-client/Cargo.toml @@ -10,9 +10,13 @@ borsh.workspace = true solana-program.workspace = true access-control = { path = "../access-control" } -hyperlane-core = { path = "../../../hyperlane-core" } -hyperlane-sealevel-mailbox = { path = "../../programs/mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../../programs/hyperlane-sealevel-igp", features = ["no-entrypoint"] } +hyperlane-core = { path = "../../../main/hyperlane-core" } +hyperlane-sealevel-mailbox = { path = "../../programs/mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../../programs/hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } [dev-dependencies] diff --git a/rust/sealevel/libraries/hyperlane-sealevel-token/Cargo.toml b/rust/sealevel/libraries/hyperlane-sealevel-token/Cargo.toml index d7e6c12b0..4394567be 100644 --- a/rust/sealevel/libraries/hyperlane-sealevel-token/Cargo.toml +++ b/rust/sealevel/libraries/hyperlane-sealevel-token/Cargo.toml @@ -14,14 +14,18 @@ thiserror.workspace = true spl-associated-token-account.workspace = true spl-noop.workspace = true spl-token.workspace = true -spl-token-2022.workspace = true # FIXME Should we actually use 2022 here or try normal token program? +spl-token-2022.workspace = true # FIXME Should we actually use 2022 here or try normal token program? access-control = { path = "../access-control" } account-utils = { path = "../account-utils" } -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } hyperlane-sealevel-connection-client = { path = "../hyperlane-sealevel-connection-client" } -hyperlane-sealevel-mailbox = { path = "../../programs/mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../../programs/hyperlane-sealevel-igp", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../../programs/mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../../programs/hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } hyperlane-sealevel-message-recipient-interface = { path = "../message-recipient-interface" } serializable-account-meta = { path = "../serializable-account-meta" } @@ -29,4 +33,3 @@ serializable-account-meta = { path = "../serializable-account-meta" } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/libraries/interchain-security-module-interface/Cargo.toml b/rust/sealevel/libraries/interchain-security-module-interface/Cargo.toml index 7b215d63c..350cf2e4c 100644 --- a/rust/sealevel/libraries/interchain-security-module-interface/Cargo.toml +++ b/rust/sealevel/libraries/interchain-security-module-interface/Cargo.toml @@ -12,4 +12,3 @@ spl-type-length-value.workspace = true [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/libraries/message-recipient-interface/Cargo.toml b/rust/sealevel/libraries/message-recipient-interface/Cargo.toml index ebb48ea00..7f9468cb8 100644 --- a/rust/sealevel/libraries/message-recipient-interface/Cargo.toml +++ b/rust/sealevel/libraries/message-recipient-interface/Cargo.toml @@ -10,11 +10,10 @@ borsh.workspace = true solana-program.workspace = true spl-type-length-value.workspace = true -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } # Required to allow dependencies `getrandom` but to preserve determinism required by programs, see # https://github.com/solana-foundation/developer-content/blob/main/docs/programs/lang-rust.md#depending-on-rand getrandom = { workspace = true, features = ["custom"] } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/libraries/multisig-ism/Cargo.toml b/rust/sealevel/libraries/multisig-ism/Cargo.toml index 1116acbbd..963db7a31 100644 --- a/rust/sealevel/libraries/multisig-ism/Cargo.toml +++ b/rust/sealevel/libraries/multisig-ism/Cargo.toml @@ -15,7 +15,7 @@ solana-program.workspace = true spl-type-length-value.workspace = true thiserror.workspace = true -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } ecdsa-signature = { path = "../ecdsa-signature" } [dev-dependencies] @@ -23,4 +23,3 @@ hex.workspace = true [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/libraries/serializable-account-meta/Cargo.toml b/rust/sealevel/libraries/serializable-account-meta/Cargo.toml index 6762a952e..cab84fe37 100644 --- a/rust/sealevel/libraries/serializable-account-meta/Cargo.toml +++ b/rust/sealevel/libraries/serializable-account-meta/Cargo.toml @@ -11,4 +11,3 @@ solana-program.workspace = true [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/libraries/test-transaction-utils/Cargo.toml b/rust/sealevel/libraries/test-transaction-utils/Cargo.toml index 2f9cc5634..418c7c38f 100644 --- a/rust/sealevel/libraries/test-transaction-utils/Cargo.toml +++ b/rust/sealevel/libraries/test-transaction-utils/Cargo.toml @@ -12,4 +12,3 @@ solana-sdk.workspace = true [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/libraries/test-utils/Cargo.toml b/rust/sealevel/libraries/test-utils/Cargo.toml index 3654a1327..4197771e7 100644 --- a/rust/sealevel/libraries/test-utils/Cargo.toml +++ b/rust/sealevel/libraries/test-utils/Cargo.toml @@ -13,15 +13,20 @@ solana-sdk.workspace = true spl-noop.workspace = true spl-token-2022.workspace = true -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } hyperlane-sealevel-interchain-security-module-interface = { path = "../interchain-security-module-interface" } -hyperlane-sealevel-mailbox = { path = "../../programs/mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../../programs/hyperlane-sealevel-igp", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../../programs/mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../../programs/hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } hyperlane-sealevel-message-recipient-interface = { path = "../message-recipient-interface" } -hyperlane-sealevel-test-ism = { path = "../../programs/ism/test-ism", features = ["test-client"] } +hyperlane-sealevel-test-ism = { path = "../../programs/ism/test-ism", features = [ + "test-client", +] } hyperlane-test-transaction-utils = { path = "../test-transaction-utils" } serializable-account-meta = { path = "../serializable-account-meta" } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/helloworld/Cargo.toml b/rust/sealevel/programs/helloworld/Cargo.toml index b0cbf2eaf..7aa1fd699 100644 --- a/rust/sealevel/programs/helloworld/Cargo.toml +++ b/rust/sealevel/programs/helloworld/Cargo.toml @@ -7,7 +7,12 @@ edition = "2021" [features] no-entrypoint = [] -test-client = ["dep:solana-program-test", "dep:solana-sdk", "dep:hyperlane-test-utils", "dep:spl-noop"] +test-client = [ + "dep:solana-program-test", + "dep:solana-sdk", + "dep:hyperlane-test-utils", + "dep:spl-noop", +] [dependencies] borsh.workspace = true @@ -18,9 +23,13 @@ spl-noop = { workspace = true, optional = true } access-control = { path = "../../libraries/access-control" } account-utils = { path = "../../libraries/account-utils" } -hyperlane-core = { path = "../../../hyperlane-core" } -hyperlane-sealevel-mailbox = { path = "../mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = ["no-entrypoint"] } +hyperlane-core = { path = "../../../main/hyperlane-core" } +hyperlane-sealevel-mailbox = { path = "../mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } hyperlane-sealevel-connection-client = { path = "../../libraries/hyperlane-sealevel-connection-client" } hyperlane-sealevel-message-recipient-interface = { path = "../../libraries/message-recipient-interface" } hyperlane-test-utils = { path = "../../libraries/test-utils", optional = true } diff --git a/rust/sealevel/programs/hyperlane-sealevel-igp-test/Cargo.toml b/rust/sealevel/programs/hyperlane-sealevel-igp-test/Cargo.toml index bbc603f9e..b636c2692 100644 --- a/rust/sealevel/programs/hyperlane-sealevel-igp-test/Cargo.toml +++ b/rust/sealevel/programs/hyperlane-sealevel-igp-test/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" edition = "2021" [dev-dependencies] -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } access-control = { path = "../../libraries/access-control" } account-utils = { path = "../../libraries/account-utils" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } @@ -17,4 +17,3 @@ hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp" } solana-program-test.workspace = true solana-sdk.workspace = true hyperlane-test-utils = { path = "../../libraries/test-utils" } - diff --git a/rust/sealevel/programs/hyperlane-sealevel-igp/Cargo.toml b/rust/sealevel/programs/hyperlane-sealevel-igp/Cargo.toml index 2bd41043c..256b21d76 100644 --- a/rust/sealevel/programs/hyperlane-sealevel-igp/Cargo.toml +++ b/rust/sealevel/programs/hyperlane-sealevel-igp/Cargo.toml @@ -11,7 +11,7 @@ no-spl-noop = [] serde = ["dep:serde"] [dependencies] -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } access-control = { path = "../../libraries/access-control" } account-utils = { path = "../../libraries/account-utils" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } @@ -27,4 +27,3 @@ serde = { workspace = true, optional = true } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/hyperlane-sealevel-token-collateral/Cargo.toml b/rust/sealevel/programs/hyperlane-sealevel-token-collateral/Cargo.toml index d6378080b..c1fcf83ab 100644 --- a/rust/sealevel/programs/hyperlane-sealevel-token-collateral/Cargo.toml +++ b/rust/sealevel/programs/hyperlane-sealevel-token-collateral/Cargo.toml @@ -15,15 +15,19 @@ num-traits.workspace = true solana-program.workspace = true spl-associated-token-account.workspace = true spl-noop.workspace = true -spl-token-2022.workspace = true # FIXME Should we actually use 2022 here or try normal token program? +spl-token-2022.workspace = true # FIXME Should we actually use 2022 here or try normal token program? spl-token.workspace = true thiserror.workspace = true account-utils = { path = "../../libraries/account-utils" } -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } hyperlane-sealevel-connection-client = { path = "../../libraries/hyperlane-sealevel-connection-client" } -hyperlane-sealevel-mailbox = { path = "../mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } hyperlane-sealevel-message-recipient-interface = { path = "../../libraries/message-recipient-interface" } hyperlane-sealevel-token-lib = { path = "../../libraries/hyperlane-sealevel-token" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } @@ -33,8 +37,9 @@ solana-program-test.workspace = true solana-sdk.workspace = true hyperlane-test-utils = { path = "../../libraries/test-utils" } -hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = ["no-entrypoint"] } +hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = [ + "no-entrypoint", +] } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/hyperlane-sealevel-token-native/Cargo.toml b/rust/sealevel/programs/hyperlane-sealevel-token-native/Cargo.toml index 25f4777c9..84475f598 100644 --- a/rust/sealevel/programs/hyperlane-sealevel-token-native/Cargo.toml +++ b/rust/sealevel/programs/hyperlane-sealevel-token-native/Cargo.toml @@ -17,10 +17,14 @@ spl-noop.workspace = true thiserror.workspace = true account-utils = { path = "../../libraries/account-utils" } -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } hyperlane-sealevel-connection-client = { path = "../../libraries/hyperlane-sealevel-connection-client" } -hyperlane-sealevel-mailbox = { path = "../mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } hyperlane-sealevel-message-recipient-interface = { path = "../../libraries/message-recipient-interface" } hyperlane-sealevel-token-lib = { path = "../../libraries/hyperlane-sealevel-token" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } @@ -30,11 +34,12 @@ solana-program-test.workspace = true solana-sdk.workspace = true hyperlane-test-utils = { path = "../../libraries/test-utils" } -hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = ["no-entrypoint"] } +hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = [ + "no-entrypoint", +] } # Unfortunately required for some functions in `solana-program-test`, and is not # re-exported tarpc = "~0.29" [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/hyperlane-sealevel-token/Cargo.toml b/rust/sealevel/programs/hyperlane-sealevel-token/Cargo.toml index 5ddd28ed0..93f0e807b 100644 --- a/rust/sealevel/programs/hyperlane-sealevel-token/Cargo.toml +++ b/rust/sealevel/programs/hyperlane-sealevel-token/Cargo.toml @@ -20,10 +20,14 @@ spl-token.workspace = true thiserror.workspace = true account-utils = { path = "../../libraries/account-utils" } -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } hyperlane-sealevel-connection-client = { path = "../../libraries/hyperlane-sealevel-connection-client" } -hyperlane-sealevel-mailbox = { path = "../mailbox", features = ["no-entrypoint"] } -hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../mailbox", features = [ + "no-entrypoint", +] } +hyperlane-sealevel-igp = { path = "../hyperlane-sealevel-igp", features = [ + "no-entrypoint", +] } hyperlane-sealevel-message-recipient-interface = { path = "../../libraries/message-recipient-interface" } hyperlane-sealevel-token-lib = { path = "../../libraries/hyperlane-sealevel-token" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } @@ -33,8 +37,9 @@ solana-program-test.workspace = true solana-sdk.workspace = true hyperlane-test-utils = { path = "../../libraries/test-utils" } -hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = ["no-entrypoint"] } +hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = [ + "no-entrypoint", +] } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/hyperlane-sealevel-token/src/lib.rs b/rust/sealevel/programs/hyperlane-sealevel-token/src/lib.rs index 69bcde823..b08a06f9f 100644 --- a/rust/sealevel/programs/hyperlane-sealevel-token/src/lib.rs +++ b/rust/sealevel/programs/hyperlane-sealevel-token/src/lib.rs @@ -1,5 +1,5 @@ //! Hyperlane Token program for synthetic tokens. - +#![allow(unexpected_cfgs)] // TODO: `rustc` 1.80.1 clippy issue #![deny(warnings)] #![deny(missing_docs)] #![deny(unsafe_code)] diff --git a/rust/sealevel/programs/ism/multisig-ism-message-id/Cargo.toml b/rust/sealevel/programs/ism/multisig-ism-message-id/Cargo.toml index ea0fde75c..531367521 100644 --- a/rust/sealevel/programs/ism/multisig-ism-message-id/Cargo.toml +++ b/rust/sealevel/programs/ism/multisig-ism-message-id/Cargo.toml @@ -18,16 +18,20 @@ thiserror.workspace = true access-control = { path = "../../../libraries/access-control" } account-utils = { path = "../../../libraries/account-utils" } ecdsa-signature = { path = "../../../libraries/ecdsa-signature" } -hyperlane-core = { path = "../../../../hyperlane-core" } +hyperlane-core = { path = "../../../../main/hyperlane-core" } hyperlane-sealevel-interchain-security-module-interface = { path = "../../../libraries/interchain-security-module-interface" } -hyperlane-sealevel-mailbox = { path = "../../mailbox", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../../mailbox", features = [ + "no-entrypoint", +] } multisig-ism = { path = "../../../libraries/multisig-ism" } serializable-account-meta = { path = "../../../libraries/serializable-account-meta" } [dev-dependencies] hyperlane-sealevel-multisig-ism-message-id = { path = "../multisig-ism-message-id" } hyperlane-test-utils = { path = "../../../libraries/test-utils" } -multisig-ism = { path = "../../../libraries/multisig-ism", features = ["test-data"] } +multisig-ism = { path = "../../../libraries/multisig-ism", features = [ + "test-data", +] } solana-program-test.workspace = true solana-sdk.workspace = true hex.workspace = true @@ -37,4 +41,3 @@ rand = "0.8.5" [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/ism/test-ism/Cargo.toml b/rust/sealevel/programs/ism/test-ism/Cargo.toml index 69fe299cb..113fdede3 100644 --- a/rust/sealevel/programs/ism/test-ism/Cargo.toml +++ b/rust/sealevel/programs/ism/test-ism/Cargo.toml @@ -7,7 +7,11 @@ edition = "2021" [features] no-entrypoint = [] -test-client = ["dep:solana-program-test", "dep:solana-sdk", "dep:hyperlane-test-transaction-utils"] +test-client = [ + "dep:solana-program-test", + "dep:solana-sdk", + "dep:hyperlane-test-transaction-utils", +] [dependencies] borsh.workspace = true @@ -16,12 +20,13 @@ solana-program-test = { workspace = true, optional = true } solana-sdk = { workspace = true, optional = true } account-utils = { path = "../../../libraries/account-utils" } -hyperlane-core = { path = "../../../../hyperlane-core" } +hyperlane-core = { path = "../../../../main/hyperlane-core" } hyperlane-sealevel-interchain-security-module-interface = { path = "../../../libraries/interchain-security-module-interface" } -hyperlane-sealevel-mailbox = { path = "../../mailbox", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../../mailbox", features = [ + "no-entrypoint", +] } serializable-account-meta = { path = "../../../libraries/serializable-account-meta" } hyperlane-test-transaction-utils = { path = "../../../libraries/test-transaction-utils", optional = true } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/mailbox-test/Cargo.toml b/rust/sealevel/programs/mailbox-test/Cargo.toml index a166b6c68..a48891f06 100644 --- a/rust/sealevel/programs/mailbox-test/Cargo.toml +++ b/rust/sealevel/programs/mailbox-test/Cargo.toml @@ -23,15 +23,18 @@ thiserror.workspace = true access-control = { path = "../../libraries/access-control" } account-utils = { path = "../../libraries/account-utils" } -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } hyperlane-sealevel-interchain-security-module-interface = { path = "../../libraries/interchain-security-module-interface" } hyperlane-sealevel-mailbox = { path = "../mailbox" } hyperlane-sealevel-message-recipient-interface = { path = "../../libraries/message-recipient-interface" } -hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = ["test-client"] } -hyperlane-sealevel-test-send-receiver = { path = "../test-send-receiver", features = ["test-client"] } +hyperlane-sealevel-test-ism = { path = "../ism/test-ism", features = [ + "test-client", +] } +hyperlane-sealevel-test-send-receiver = { path = "../test-send-receiver", features = [ + "test-client", +] } hyperlane-test-utils = { path = "../../libraries/test-utils" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/mailbox/Cargo.toml b/rust/sealevel/programs/mailbox/Cargo.toml index 8b5f14d1c..6ca7bc9e2 100644 --- a/rust/sealevel/programs/mailbox/Cargo.toml +++ b/rust/sealevel/programs/mailbox/Cargo.toml @@ -22,11 +22,11 @@ spl-noop.workspace = true getrandom = { workspace = true, features = ["custom"] } proc-macro-crate = "~1.2.1" # TODO: remove this dependency once solana supports rust >=1.64 -blake3 = "=1.4.0" # TODO: update once solana supports rust >= 1.66 +blake3 = "=1.4.0" # TODO: update once solana supports rust >= 1.66 access-control = { path = "../../libraries/access-control" } account-utils = { path = "../../libraries/account-utils" } -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-core = { path = "../../../main/hyperlane-core" } hyperlane-sealevel-interchain-security-module-interface = { path = "../../libraries/interchain-security-module-interface" } hyperlane-sealevel-message-recipient-interface = { path = "../../libraries/message-recipient-interface" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } @@ -39,4 +39,3 @@ log.workspace = true [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/test-send-receiver/Cargo.toml b/rust/sealevel/programs/test-send-receiver/Cargo.toml index 9bfcb3015..785080d87 100644 --- a/rust/sealevel/programs/test-send-receiver/Cargo.toml +++ b/rust/sealevel/programs/test-send-receiver/Cargo.toml @@ -7,7 +7,12 @@ edition = "2021" [features] no-entrypoint = [] -test-client = ["dep:solana-program-test", "dep:solana-sdk", "dep:hyperlane-test-utils", "dep:spl-noop"] +test-client = [ + "dep:solana-program-test", + "dep:solana-sdk", + "dep:hyperlane-test-utils", + "dep:spl-noop", +] [dependencies] borsh.workspace = true @@ -17,11 +22,12 @@ solana-sdk = { workspace = true, optional = true } spl-noop = { workspace = true, optional = true } account-utils = { path = "../../libraries/account-utils" } -hyperlane-sealevel-mailbox = { path = "../mailbox", features = ["no-entrypoint"] } +hyperlane-sealevel-mailbox = { path = "../mailbox", features = [ + "no-entrypoint", +] } hyperlane-sealevel-message-recipient-interface = { path = "../../libraries/message-recipient-interface" } hyperlane-test-utils = { path = "../../libraries/test-utils", optional = true } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/programs/validator-announce/Cargo.toml b/rust/sealevel/programs/validator-announce/Cargo.toml index 50bea99e6..d50834933 100644 --- a/rust/sealevel/programs/validator-announce/Cargo.toml +++ b/rust/sealevel/programs/validator-announce/Cargo.toml @@ -15,16 +15,17 @@ thiserror.workspace = true account-utils = { path = "../../libraries/account-utils" } ecdsa-signature = { path = "../../libraries/ecdsa-signature" } -hyperlane-sealevel-mailbox = { path = "../mailbox", features = ["no-entrypoint"] } -hyperlane-core = { path = "../../../hyperlane-core" } +hyperlane-sealevel-mailbox = { path = "../mailbox", features = [ + "no-entrypoint", +] } +hyperlane-core = { path = "../../../main/hyperlane-core" } serializable-account-meta = { path = "../../libraries/serializable-account-meta" } [dev-dependencies] hex.workspace = true solana-program-test.workspace = true solana-sdk.workspace = true -hyperlane-test-utils ={ path = "../../libraries/test-utils" } +hyperlane-test-utils = { path = "../../libraries/test-utils" } [lib] crate-type = ["cdylib", "lib"] - diff --git a/rust/sealevel/rust-toolchain b/rust/sealevel/rust-toolchain new file mode 100644 index 000000000..83e24cc56 --- /dev/null +++ b/rust/sealevel/rust-toolchain @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.72.1" +profile = "default" diff --git a/typescript/infra/scripts/agent-utils.ts b/typescript/infra/scripts/agent-utils.ts index d7ee700a5..74d37d457 100644 --- a/typescript/infra/scripts/agent-utils.ts +++ b/typescript/infra/scripts/agent-utils.ts @@ -530,7 +530,7 @@ export function writeAddresses( } export function getAgentConfigDirectory() { - return path.join('../../', 'rust', 'config'); + return path.join('../../', 'rust', 'main', 'config'); } export function getAgentConfigJsonPath(environment: AgentEnvironment) { diff --git a/typescript/infra/src/agents/index.ts b/typescript/infra/src/agents/index.ts index 533e1407a..ee0da5889 100644 --- a/typescript/infra/src/agents/index.ts +++ b/typescript/infra/src/agents/index.ts @@ -35,7 +35,7 @@ import { AgentGCPKey } from './gcp.js'; const HELM_CHART_PATH = join( getInfraPath(), - '/../../rust/helm/hyperlane-agent/', + '/../../rust/main/helm/hyperlane-agent/', ); if (!fs.existsSync(HELM_CHART_PATH + 'Chart.yaml')) From 1ab8751afbf98d52c10eaddd2ef49427109d16df Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 12 Sep 2024 18:00:08 +0100 Subject: [PATCH 021/224] fix: docker agent build (#4481) fix: docker agent build - update image from 1.72.1 -> 1.80.1 drive-by: update more `rust/` --> `rust/main/` drive-by: consolidate e2e non-cosmwasm cache, multiple cache steps per job can get in the way of each other --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .gitattributes | 2 +- .github/workflows/agent-release-artifacts.yml | 18 +++++++++--------- .github/workflows/test.yml | 14 ++------------ .husky/pre-commit | 7 +++++-- rust/Dockerfile | 9 ++------- rust/README.md | 2 +- .../hyperlane-base/src/settings/loader/mod.rs | 2 +- rust/main/hyperlane-base/tests/chain_config.rs | 2 +- rust/main/utils/run-locally/src/cosmos/mod.rs | 2 +- solidity/update_abis.sh | 4 ++-- .../scripts/funding/fund-keys-from-deployer.ts | 2 +- typescript/infra/src/config/agent/agent.ts | 6 +++--- typescript/infra/src/config/agent/relayer.ts | 4 ++-- typescript/sdk/src/ism/metadata/aggregation.ts | 2 +- 14 files changed, 32 insertions(+), 44 deletions(-) diff --git a/.gitattributes b/.gitattributes index d061a18bd..eb647bb3b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ typescript/sdk/src/cw-types/*.types.ts linguist-generated=true -rust/chains/hyperlane-ethereum/abis/*.abi.json linguist-generated=true +rust/main/chains/hyperlane-ethereum/abis/*.abi.json linguist-generated=true solidity/contracts/interfaces/avs/*.sol linguist-vendored=true solidity/contracts/avs/ECDSA*.sol linguist-vendored=true diff --git a/.github/workflows/agent-release-artifacts.yml b/.github/workflows/agent-release-artifacts.yml index b1218dc54..b2a190f7e 100644 --- a/.github/workflows/agent-release-artifacts.yml +++ b/.github/workflows/agent-release-artifacts.yml @@ -65,23 +65,23 @@ jobs: target: ${{ matrix.TARGET }} - name: setup target run: rustup target add ${{ matrix.TARGET }} - working-directory: ./rust + working-directory: ./rust/main - name: build run: cargo build --release --target ${{ matrix.TARGET }} --bin relayer --bin scraper --bin validator - working-directory: ./rust + working-directory: ./rust/main - name: make executable if: ${{ matrix.OS == 'larger-runner' || matrix.OS == 'macos-latest' }} run: chmod ug+x,-w relayer scraper validator - working-directory: rust/target/${{ matrix.TARGET }}/release + working-directory: rust/main/target/${{ matrix.TARGET }}/release - name: upload binaries uses: actions/upload-artifact@v4 with: name: ${{ matrix.TARGET }}-${{ needs.prepare.outputs.tag_sha }}-${{ needs.prepare.outputs.tag_date }} path: | - rust/target/${{ matrix.TARGET }}/release/relayer - rust/target/${{ matrix.TARGET }}/release/relayer.exe - rust/target/${{ matrix.TARGET }}/release/scraper - rust/target/${{ matrix.TARGET }}/release/scraper.exe - rust/target/${{ matrix.TARGET }}/release/validator - rust/target/${{ matrix.TARGET }}/release/validator.exe + rust/main/target/${{ matrix.TARGET }}/release/relayer + rust/main/target/${{ matrix.TARGET }}/release/relayer.exe + rust/main/target/${{ matrix.TARGET }}/release/scraper + rust/main/target/${{ matrix.TARGET }}/release/scraper.exe + rust/main/target/${{ matrix.TARGET }}/release/validator + rust/main/target/${{ matrix.TARGET }}/release/validator.exe if-no-files-found: error diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b927d734f..ff0a6ddcc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -172,23 +172,13 @@ jobs: - name: rust cache uses: Swatinem/rust-cache@v2 with: - prefix-key: 'v2-rust-main' + prefix-key: 'v2-rust-e2e' shared-key: ${{ matrix.e2e-type }} cache-provider: 'buildjet' save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} workspaces: | ./rust/main - - - name: rust cache - uses: Swatinem/rust-cache@v2 - if: matrix.e2e-type == 'non-cosmwasm' - with: - prefix-key: 'v2-rust-sealevel' - shared-key: ${{ matrix.e2e-type }} - cache-provider: 'buildjet' - save-if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }} - workspaces: | - ./rust/sealevel + ${{ matrix.e2e-type == 'non-cosmwasm' && './rust/sealevel' || '' }} - name: Free disk space run: | diff --git a/.husky/pre-commit b/.husky/pre-commit index 8eb8e9c84..9edc7156e 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -7,6 +7,9 @@ echo "📝 If you haven't yet, please add a changeset for your changes via 'yarn # if any *.rs files have changed if git diff --staged --exit-code --name-only | grep -q -E ".*\.rs$"; then - echo "Running cargo fmt pre-commit hook" - cargo fmt --all --check --manifest-path rust/Cargo.toml + echo "Running cargo fmt pre-commit hook for rust/main" + cargo fmt --all --check --manifest-path rust/main/Cargo.toml + + echo "Running cargo fmt pre-commit hook for rust/sealevel" + cargo fmt --all --check --manifest-path rust/sealevel/Cargo.toml fi diff --git a/rust/Dockerfile b/rust/Dockerfile index ed8c17d5b..156144ab9 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:experimental -FROM rust:1.72.1 as builder +FROM rust:1.80.1 as builder WORKDIR /usr/src # 1a: Prepare for static linking @@ -23,18 +23,13 @@ COPY rust/main/utils rust/main/utils COPY rust/sealevel rust/sealevel COPY rust/main/Cargo.toml rust/main/. -COPY rust/main/Cargo.toml rust/main/. -COPY rust/sealevel/Cargo.lock rust/sealevel/. -COPY rust/sealevel/Cargo.lock rust/sealevel/. +COPY rust/main/Cargo.lock rust/main/. WORKDIR /usr/src/rust/main # Build binaries RUN \ - --mount=id=cargo,type=cache,sharing=locked,target=/usr/src/target \ - --mount=id=cargo-home-registry,type=cache,sharing=locked,target=/usr/local/cargo/registry \ - --mount=id=cargo-home-git,type=cache,sharing=locked,target=/usr/local/cargo/git \ RUSTFLAGS="--cfg tokio_unstable" cargo build --release --bin validator --bin relayer --bin scraper && \ mkdir -p /release && \ cp /usr/src/rust/main/target/release/validator /release && \ diff --git a/rust/README.md b/rust/README.md index 0dcba6e26..22bf8b54e 100644 --- a/rust/README.md +++ b/rust/README.md @@ -117,7 +117,7 @@ cd rust ### Deploy Procedure -The contract addresses of each deploy can be found in `rust/config`. The agents will +The contract addresses of each deploy can be found in `rust/main/config`. The agents will automatically pull in all configs in this directory. When agents are deployed to point at a new environment, they cease to point at diff --git a/rust/main/hyperlane-base/src/settings/loader/mod.rs b/rust/main/hyperlane-base/src/settings/loader/mod.rs index 028649273..f4a81bf5d 100644 --- a/rust/main/hyperlane-base/src/settings/loader/mod.rs +++ b/rust/main/hyperlane-base/src/settings/loader/mod.rs @@ -27,7 +27,7 @@ where let mut base_config_sources = vec![]; let mut builder = Config::builder(); - // Always load the default config files (`rust/config/*.json`) + // Always load the default config files (`rust/main/config/*.json`) for entry in PathBuf::from("./config") .read_dir() .context("Failed to open config directory") diff --git a/rust/main/hyperlane-base/tests/chain_config.rs b/rust/main/hyperlane-base/tests/chain_config.rs index 7e59b2360..f0695820c 100644 --- a/rust/main/hyperlane-base/tests/chain_config.rs +++ b/rust/main/hyperlane-base/tests/chain_config.rs @@ -6,7 +6,7 @@ use hyperlane_base::settings::{parser::RawAgentConf, Settings}; use hyperlane_core::{config::*, KnownHyperlaneDomain}; use walkdir::WalkDir; -/// Relative path to the `hyperlane-monorepo/rust/config/` +/// Relative path to the `hyperlane-monorepo/rust/main/config/` /// directory, which is where the agent's config files /// currently live. const AGENT_CONFIG_PATH_ROOT: &str = "../config"; diff --git a/rust/main/utils/run-locally/src/cosmos/mod.rs b/rust/main/utils/run-locally/src/cosmos/mod.rs index 9dc68950c..83a56786b 100644 --- a/rust/main/utils/run-locally/src/cosmos/mod.rs +++ b/rust/main/utils/run-locally/src/cosmos/mod.rs @@ -581,7 +581,7 @@ fn run_locally() { postgres, }; - // Mostly copy-pasta from `rust/utils/run-locally/src/main.rs` + // Mostly copy-pasta from `rust/main/utils/run-locally/src/main.rs` // TODO: refactor to share code let loop_start = Instant::now(); let mut failure_occurred = false; diff --git a/solidity/update_abis.sh b/solidity/update_abis.sh index 94e95ed98..1095eb95c 100755 --- a/solidity/update_abis.sh +++ b/solidity/update_abis.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh # Must be ran from the `solidity` directory @@ -6,7 +6,7 @@ copy() { # Optionally allow path to be passed in, and extract the contract name # as the string following the last instance of `/` CONTRACT_NAME="${1##*/}" - jq .abi < artifacts/contracts/"$1".sol/"$CONTRACT_NAME".json > ../rust/chains/hyperlane-ethereum/abis/"$CONTRACT_NAME".abi.json + jq .abi < artifacts/contracts/"$1".sol/"$CONTRACT_NAME".json > ../rust/main/chains/hyperlane-ethereum/abis/"$CONTRACT_NAME".abi.json } copy interfaces/IMailbox && \ diff --git a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts index b27bf6904..9a0cce0c0 100644 --- a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts +++ b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts @@ -72,7 +72,7 @@ const constMetricLabels = { const metricsRegister = new Registry(); const walletBalanceGauge = new Gauge({ - // Mirror the rust/ethers-prometheus `wallet_balance` gauge metric. + // Mirror the rust/main/ethers-prometheus `wallet_balance` gauge metric. name: 'hyperlane_wallet_balance', help: 'Current balance of eth and other tokens in the `tokens` map for the wallet addresses in the `wallets` set', registers: [metricsRegister], diff --git a/typescript/infra/src/config/agent/agent.ts b/typescript/infra/src/config/agent/agent.ts index 69ec265d7..e9ff6f3e4 100644 --- a/typescript/infra/src/config/agent/agent.ts +++ b/typescript/infra/src/config/agent/agent.ts @@ -30,7 +30,7 @@ export type DeepPartial = T extends object } : T; -// See rust/helm/values.yaml for the full list of options and their defaults. +// See rust/main/helm/values.yaml for the full list of options and their defaults. // This is the root object in the values file. export interface HelmRootAgentValues { image: HelmImageValues; @@ -38,7 +38,7 @@ export interface HelmRootAgentValues { nameOverride?: string; } -// See rust/helm/values.yaml for the full list of options and their defaults. +// See rust/main/helm/values.yaml for the full list of options and their defaults. // This is at `.hyperlane` in the values file. interface HelmHyperlaneValues { runEnv: DeployEnvironment; @@ -54,7 +54,7 @@ interface HelmHyperlaneValues { scraper?: HelmScraperValues; } -// See rust/helm/values.yaml for the full list of options and their defaults. +// See rust/main/helm/values.yaml for the full list of options and their defaults. // This is at `.hyperlane.chains` in the values file. export interface HelmAgentChainOverride extends DeepPartial { diff --git a/typescript/infra/src/config/agent/relayer.ts b/typescript/infra/src/config/agent/relayer.ts index f9d4bac73..aebcac245 100644 --- a/typescript/infra/src/config/agent/relayer.ts +++ b/typescript/infra/src/config/agent/relayer.ts @@ -51,14 +51,14 @@ export interface BaseRelayerConfig { // Full relayer-specific agent config for a single chain export type RelayerConfig = Omit; -// See rust/helm/values.yaml for the full list of options and their defaults. +// See rust/main/helm/values.yaml for the full list of options and their defaults. // This is at `.hyperlane.relayer` in the values file. export interface HelmRelayerValues extends HelmStatefulSetValues { aws: boolean; config?: RelayerConfig; } -// See rust/helm/values.yaml for the full list of options and their defaults. +// See rust/main/helm/values.yaml for the full list of options and their defaults. // This is at `.hyperlane.relayerChains` in the values file. export interface HelmRelayerChainValues { name: string; diff --git a/typescript/sdk/src/ism/metadata/aggregation.ts b/typescript/sdk/src/ism/metadata/aggregation.ts index 52f725219..cdf20cd71 100644 --- a/typescript/sdk/src/ism/metadata/aggregation.ts +++ b/typescript/sdk/src/ism/metadata/aggregation.ts @@ -26,7 +26,7 @@ export interface AggregationMetadata { const RANGE_SIZE = 4; -// adapted from rust/agents/relayer/src/msg/metadata/aggregation.rs +// adapted from rust/main/agents/relayer/src/msg/metadata/aggregation.rs export class AggregationMetadataBuilder implements MetadataBuilder { protected logger = rootLogger.child({ module: 'AggregationIsmMetadataBuilder', From 0e2f94ba104254072f117d926619002145c0d5c3 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Fri, 13 Sep 2024 06:56:08 -0400 Subject: [PATCH 022/224] feat: Add github proxy (#4418) ### Description This PR adds github-proxy CloudFlare Worker project which will attach an api key to github requests to increase read capacity. It is mostly a passthrough proxy that has a simple allowlist. This project is created and deployed using CloudFlare's [cloudflare create CLI](https://developers.cloudflare.com/workers/get-started/guide/) It is deployed using `yarn deploy` (aka wrangler) ### Drive-by changes - `yarn up chai@4.5.0` - `yarn up typescript@5.5.2` - `yarn up yaml@2.4.5` ### Related issues Fixes: https://github.com/hyperlane-xyz/hyperlane-registry/issues/163 ### Backward compatibility Yes ### Testing Manual/Unit Tests - Use a script to ddos github, then try cli command `hyperlane warp read` - Unit tests for the Worker, and GithubRegistry changes --- .changeset/famous-ants-tan.md | 5 + Dockerfile | 1 + solidity/package.json | 2 +- typescript/cli/cli.ts | 2 + typescript/cli/package.json | 8 +- typescript/cli/src/commands/options.ts | 7 + typescript/cli/src/consts.ts | 1 + typescript/cli/src/context/context.ts | 23 +- typescript/cli/src/context/types.ts | 1 + typescript/cli/src/tests/commands/core.ts | 1 - typescript/cli/src/tests/commands/warp.ts | 3 - .../cli/src/tests/warp-read.e2e-test.ts | 54 + typescript/github-proxy/.dev.vars.example | 1 + typescript/github-proxy/.gitignore | 172 +++ typescript/github-proxy/package.json | 35 + typescript/github-proxy/src/errors.ts | 1 + typescript/github-proxy/src/index.ts | 26 + typescript/github-proxy/test/index.spec.ts | 34 + typescript/github-proxy/test/tsconfig.json | 11 + typescript/github-proxy/tsconfig.json | 15 + typescript/github-proxy/vitest.config.ts | 11 + .../github-proxy/worker-configuration.d.ts | 6 + typescript/github-proxy/wrangler.toml | 24 + typescript/helloworld/package.json | 4 +- typescript/infra/package.json | 6 +- typescript/sdk/package.json | 4 +- typescript/utils/package.json | 4 +- typescript/widgets/package.json | 2 +- yarn.lock | 1292 ++++++++++++++++- 29 files changed, 1658 insertions(+), 98 deletions(-) create mode 100644 .changeset/famous-ants-tan.md create mode 100644 typescript/cli/src/tests/warp-read.e2e-test.ts create mode 100644 typescript/github-proxy/.dev.vars.example create mode 100644 typescript/github-proxy/.gitignore create mode 100644 typescript/github-proxy/package.json create mode 100644 typescript/github-proxy/src/errors.ts create mode 100644 typescript/github-proxy/src/index.ts create mode 100644 typescript/github-proxy/test/index.spec.ts create mode 100644 typescript/github-proxy/test/tsconfig.json create mode 100644 typescript/github-proxy/tsconfig.json create mode 100644 typescript/github-proxy/vitest.config.ts create mode 100644 typescript/github-proxy/worker-configuration.d.ts create mode 100644 typescript/github-proxy/wrangler.toml diff --git a/.changeset/famous-ants-tan.md b/.changeset/famous-ants-tan.md new file mode 100644 index 000000000..5bc059463 --- /dev/null +++ b/.changeset/famous-ants-tan.md @@ -0,0 +1,5 @@ +--- +'github-proxy': major +--- + +Add github proxy to reduce github API load diff --git a/Dockerfile b/Dockerfile index 5dcd5686a..6a6af6c32 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,7 @@ COPY typescript/cli/package.json ./typescript/cli/ COPY typescript/infra/package.json ./typescript/infra/ COPY typescript/ccip-server/package.json ./typescript/ccip-server/ COPY typescript/widgets/package.json ./typescript/widgets/ +COPY typescript/github-proxy/package.json ./typescript/github-proxy/ COPY solidity/package.json ./solidity/ RUN yarn install && yarn cache clean diff --git a/solidity/package.json b/solidity/package.json index cc55e943b..2b74b1d4d 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -19,7 +19,7 @@ "@typechain/ethers-v6": "^0.5.1", "@typechain/hardhat": "^9.1.0", "@types/node": "^18.14.5", - "chai": "^4.3.6", + "chai": "4.5.0", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.2", "hardhat": "^2.22.2", diff --git a/typescript/cli/cli.ts b/typescript/cli/cli.ts index d122f293d..77be0b86f 100644 --- a/typescript/cli/cli.ts +++ b/typescript/cli/cli.ts @@ -12,6 +12,7 @@ import { deployCommand } from './src/commands/deploy.js'; import { hookCommand } from './src/commands/hook.js'; import { ismCommand } from './src/commands/ism.js'; import { + disableProxyCommandOption, keyCommandOption, logFormatCommandOption, logLevelCommandOption, @@ -46,6 +47,7 @@ try { .option('registry', registryUriCommandOption) .option('overrides', overrideRegistryUriCommandOption) .option('key', keyCommandOption) + .option('disableProxy', disableProxyCommandOption) .option('yes', skipConfirmationOption) .global(['log', 'verbosity', 'registry', 'overrides', 'yes']) .middleware([ diff --git a/typescript/cli/package.json b/typescript/cli/package.json index b95502542..6725dddd1 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -5,7 +5,7 @@ "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", - "@hyperlane-xyz/registry": "2.5.0", + "@hyperlane-xyz/registry": "4.0.0", "@hyperlane-xyz/sdk": "5.1.0", "@hyperlane-xyz/utils": "5.1.0", "@inquirer/prompts": "^3.0.0", @@ -16,7 +16,7 @@ "latest-version": "^8.0.0", "terminal-link": "^3.0.0", "tsx": "^4.7.1", - "yaml": "^2.4.1", + "yaml": "2.4.5", "yargs": "^17.7.2", "zod": "^3.21.2", "zod-validation-error": "^3.3.0", @@ -30,12 +30,12 @@ "@types/yargs": "^17.0.24", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", - "chai": "^4.3.6", + "chai": "4.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "mocha": "^10.2.0", "prettier": "^2.8.8", - "typescript": "^5.1.6" + "typescript": "5.3.3" }, "scripts": { "hyperlane": "node ./dist/cli.js", diff --git a/typescript/cli/src/commands/options.ts b/typescript/cli/src/commands/options.ts index 7b772b601..a251445be 100644 --- a/typescript/cli/src/commands/options.ts +++ b/typescript/cli/src/commands/options.ts @@ -54,6 +54,13 @@ export const keyCommandOption: Options = { defaultDescription: 'process.env.HYP_KEY', }; +export const disableProxyCommandOption: Options = { + type: 'boolean', + description: + 'Disable routing of Github API requests through the Hyperlane registry proxy.', + default: false, +}; + /* Command-specific options */ export const coreTargetsCommandOption: Options = { diff --git a/typescript/cli/src/consts.ts b/typescript/cli/src/consts.ts index 37bada31d..674f7dd15 100644 --- a/typescript/cli/src/consts.ts +++ b/typescript/cli/src/consts.ts @@ -2,3 +2,4 @@ export const MINIMUM_CORE_DEPLOY_GAS = (1e8).toString(); export const MINIMUM_WARP_DEPLOY_GAS = (6e8).toString(); // Rough calculation through deployments to testnets with 2x buffer export const MINIMUM_TEST_SEND_GAS = (3e5).toString(); export const MINIMUM_AVS_GAS = (3e6).toString(); +export const PROXY_DEPLOYED_URL = 'https://proxy.hyperlane.xyz'; diff --git a/typescript/cli/src/context/context.ts b/typescript/cli/src/context/context.ts index fb50d37bb..d96c8a22b 100644 --- a/typescript/cli/src/context/context.ts +++ b/typescript/cli/src/context/context.ts @@ -2,6 +2,7 @@ import { confirm } from '@inquirer/prompts'; import { ethers } from 'ethers'; import { + DEFAULT_GITHUB_REGISTRY, GithubRegistry, IRegistry, MergedRegistry, @@ -16,6 +17,7 @@ import { import { isHttpsUrl, isNullish, rootLogger } from '@hyperlane-xyz/utils'; import { isSignCommand } from '../commands/signCommands.js'; +import { PROXY_DEPLOYED_URL } from '../consts.js'; import { forkNetworkToMultiProvider, verifyAnvil } from '../deploy/dry-run.js'; import { logBlue } from '../logger.js'; import { runSingleChainSelectionStep } from '../utils/chains.js'; @@ -37,6 +39,7 @@ export async function contextMiddleware(argv: Record) { key: argv.key, fromAddress: argv.fromAddress, requiresKey, + disableProxy: argv.disableProxy, skipConfirmation: argv.yes, }; if (!isDryRun && settings.fromAddress) @@ -59,8 +62,9 @@ export async function getContext({ key, requiresKey, skipConfirmation, + disableProxy = false, }: ContextSettings): Promise { - const registry = getRegistry(registryUri, registryOverrideUri); + const registry = getRegistry(registryUri, registryOverrideUri, !disableProxy); let signer: ethers.Wallet | undefined = undefined; if (key || requiresKey) { @@ -89,10 +93,11 @@ export async function getDryRunContext( key, fromAddress, skipConfirmation, + disableProxy = false, }: ContextSettings, chain?: ChainName, ): Promise { - const registry = getRegistry(registryUri, registryOverrideUri); + const registry = getRegistry(registryUri, registryOverrideUri, !disableProxy); const chainMetadata = await registry.getMetadata(); if (!chain) { @@ -137,6 +142,7 @@ export async function getDryRunContext( function getRegistry( primaryRegistryUri: string, overrideRegistryUri: string, + enableProxy: boolean, ): IRegistry { const logger = rootLogger.child({ module: 'MergedRegistry' }); const registries = [primaryRegistryUri, overrideRegistryUri] @@ -145,7 +151,14 @@ function getRegistry( .map((uri, index) => { const childLogger = logger.child({ uri, index }); if (isHttpsUrl(uri)) { - return new GithubRegistry({ uri, logger: childLogger }); + return new GithubRegistry({ + uri, + logger: childLogger, + proxyUrl: + enableProxy && isCanonicalRepoUrl(uri) + ? PROXY_DEPLOYED_URL + : undefined, + }); } else { return new FileSystemRegistry({ uri, @@ -159,6 +172,10 @@ function getRegistry( }); } +function isCanonicalRepoUrl(url: string) { + return url === DEFAULT_GITHUB_REGISTRY; +} + /** * Retrieves a new MultiProvider based on all known chain metadata & custom user chains * @param customChains Custom chains specified by the user diff --git a/typescript/cli/src/context/types.ts b/typescript/cli/src/context/types.ts index 80f3121fb..6c3a17c5f 100644 --- a/typescript/cli/src/context/types.ts +++ b/typescript/cli/src/context/types.ts @@ -14,6 +14,7 @@ export interface ContextSettings { key?: string; fromAddress?: string; requiresKey?: boolean; + disableProxy?: boolean; skipConfirmation?: boolean; } diff --git a/typescript/cli/src/tests/commands/core.ts b/typescript/cli/src/tests/commands/core.ts index a0924514c..b28dbafd2 100644 --- a/typescript/cli/src/tests/commands/core.ts +++ b/typescript/cli/src/tests/commands/core.ts @@ -11,7 +11,6 @@ export async function hyperlaneCoreDeploy( ) { return $`yarn workspace @hyperlane-xyz/cli run hyperlane core deploy \ --registry ${REGISTRY_PATH} \ - --overrides " " \ --config ${coreInputPath} \ --chain ${chain} \ --key ${ANVIL_KEY} \ diff --git a/typescript/cli/src/tests/commands/warp.ts b/typescript/cli/src/tests/commands/warp.ts index fe7e7a509..905778433 100644 --- a/typescript/cli/src/tests/commands/warp.ts +++ b/typescript/cli/src/tests/commands/warp.ts @@ -14,7 +14,6 @@ $.verbose = true; export async function hyperlaneWarpDeploy(warpCorePath: string) { return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp deploy \ --registry ${REGISTRY_PATH} \ - --overrides " " \ --config ${warpCorePath} \ --key ${ANVIL_KEY} \ --verbosity debug \ @@ -30,7 +29,6 @@ export async function hyperlaneWarpApply( ) { return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp apply \ --registry ${REGISTRY_PATH} \ - --overrides " " \ --config ${warpDeployPath} \ --warp ${warpCorePath} \ --key ${ANVIL_KEY} \ @@ -45,7 +43,6 @@ export async function hyperlaneWarpRead( ) { return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp read \ --registry ${REGISTRY_PATH} \ - --overrides " " \ --address ${warpAddress} \ --chain ${chain} \ --key ${ANVIL_KEY} \ diff --git a/typescript/cli/src/tests/warp-read.e2e-test.ts b/typescript/cli/src/tests/warp-read.e2e-test.ts new file mode 100644 index 000000000..1cbf336d5 --- /dev/null +++ b/typescript/cli/src/tests/warp-read.e2e-test.ts @@ -0,0 +1,54 @@ +import { expect } from 'chai'; + +import { WarpRouteDeployConfig } from '@hyperlane-xyz/sdk'; + +import { readYamlOrJson, writeYamlOrJson } from '../utils/files.js'; + +import { + ANVIL_KEY, + REGISTRY_PATH, + deployOrUseExistingCore, +} from './commands/helpers.js'; +import { hyperlaneWarpDeploy, readWarpConfig } from './commands/warp.js'; + +const CHAIN_NAME_2 = 'anvil2'; + +const EXAMPLES_PATH = './examples'; +const CORE_CONFIG_PATH = `${EXAMPLES_PATH}/core-config.yaml`; +const WARP_CONFIG_PATH_EXAMPLE = `${EXAMPLES_PATH}/warp-route-deployment.yaml`; + +const TEMP_PATH = '/tmp'; // /temp gets removed at the end of all-test.sh +const WARP_CONFIG_PATH_2 = `${TEMP_PATH}/anvil2/warp-route-deployment-anvil2.yaml`; +const WARP_CORE_CONFIG_PATH_2 = `${REGISTRY_PATH}/deployments/warp_routes/ETH/anvil2-config.yaml`; + +const TEST_TIMEOUT = 60_000; // Long timeout since these tests can take a while +describe('WarpRead e2e tests', async function () { + let anvil2Config: WarpRouteDeployConfig; + this.timeout(TEST_TIMEOUT); + before(async function () { + await deployOrUseExistingCore(CHAIN_NAME_2, CORE_CONFIG_PATH, ANVIL_KEY); + + // Create a new warp config using the example + const exampleWarpConfig: WarpRouteDeployConfig = readYamlOrJson( + WARP_CONFIG_PATH_EXAMPLE, + ); + anvil2Config = { anvil2: { ...exampleWarpConfig.anvil1 } }; + writeYamlOrJson(WARP_CONFIG_PATH_2, anvil2Config); + }); + + beforeEach(async function () { + await hyperlaneWarpDeploy(WARP_CONFIG_PATH_2); + }); + + it('should be able to read a warp route', async function () { + const warpConfigPath = `${TEMP_PATH}/warp-route-deployment-2.yaml`; + const warpConfig = await readWarpConfig( + CHAIN_NAME_2, + WARP_CORE_CONFIG_PATH_2, + warpConfigPath, + ); + expect(warpConfig[CHAIN_NAME_2].type).to.be.equal( + anvil2Config[CHAIN_NAME_2].type, + ); + }); +}); diff --git a/typescript/github-proxy/.dev.vars.example b/typescript/github-proxy/.dev.vars.example new file mode 100644 index 000000000..9cedf2571 --- /dev/null +++ b/typescript/github-proxy/.dev.vars.example @@ -0,0 +1 @@ +GITHUB_API_KEY= diff --git a/typescript/github-proxy/.gitignore b/typescript/github-proxy/.gitignore new file mode 100644 index 000000000..3b0fe33c4 --- /dev/null +++ b/typescript/github-proxy/.gitignore @@ -0,0 +1,172 @@ +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +\*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +\*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +\*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +\*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.cache +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +.cache/ + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp +.cache + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.\* + +# wrangler project + +.dev.vars +.wrangler/ diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json new file mode 100644 index 000000000..c46453777 --- /dev/null +++ b/typescript/github-proxy/package.json @@ -0,0 +1,35 @@ +{ + "name": "@hyperlane-xyz/github-proxy", + "description": "Github proxy that adds the API key to requests", + "version": "5.1.0", + "scripts": { + "deploy": "wrangler deploy", + "deploy:staging": "wrangler deploy --env staging", + "deploy:key": "wrangler secret put GITHUB_API_KEY", + "dev": "wrangler dev", + "start": "wrangler dev", + "test": "vitest", + "prettier": "prettier --write ./src ./test", + "cf-typegen": "wrangler types" + }, + "type": "module", + "homepage": "https://www.hyperlane.xyz", + "repository": "https://github.com/hyperlane-xyz/hyperlane-monorepo", + "keywords": [ + "Hyperlane", + "Github", + "Proxy", + "Typescript" + ], + "license": "Apache-2.0", + "devDependencies": { + "@cloudflare/vitest-pool-workers": "^0.4.5", + "@cloudflare/workers-types": "^4.20240821.1", + "@faker-js/faker": "^8.4.1", + "chai": "4.5.0", + "prettier": "^2.8.8", + "typescript": "5.3.3", + "vitest": "1.4.0", + "wrangler": "^3.74.0" + } +} diff --git a/typescript/github-proxy/src/errors.ts b/typescript/github-proxy/src/errors.ts new file mode 100644 index 000000000..7cfa31744 --- /dev/null +++ b/typescript/github-proxy/src/errors.ts @@ -0,0 +1 @@ +export const DISALLOWED_URL_MSG = 'Origin not allowed'; diff --git a/typescript/github-proxy/src/index.ts b/typescript/github-proxy/src/index.ts new file mode 100644 index 000000000..500c96426 --- /dev/null +++ b/typescript/github-proxy/src/index.ts @@ -0,0 +1,26 @@ +import { DISALLOWED_URL_MSG } from './errors.js'; + +const GITHUB_API_ALLOWLIST = [ + '/repos/hyperlane-xyz/hyperlane-registry/git/trees/main', +]; +const GITPUB_API_HOST = 'https://api.github.com'; +export default { + async fetch(request, env, _ctx): Promise { + const apiUrlPath = new URL(request.url).pathname; + const isAllowed = GITHUB_API_ALLOWLIST.includes(apiUrlPath); + if (!isAllowed) { + return new Response(DISALLOWED_URL_MSG, { status: 401 }); + } + + const apiUrl = new URL(`${GITPUB_API_HOST}${apiUrlPath}`); + return fetch(apiUrl, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'User-Agent': 'Hyperlane-Github-Proxy', + 'X-GitHub-Api-Version': '2022-11-28', + Authorization: `Bearer ${env.GITHUB_API_KEY}`, + }, + }); + }, +} satisfies ExportedHandler; diff --git a/typescript/github-proxy/test/index.spec.ts b/typescript/github-proxy/test/index.spec.ts new file mode 100644 index 000000000..6178c391e --- /dev/null +++ b/typescript/github-proxy/test/index.spec.ts @@ -0,0 +1,34 @@ +import { faker } from '@faker-js/faker'; +import { SELF } from 'cloudflare:test'; +import { describe, expect, it } from 'vitest'; + +import { DISALLOWED_URL_MSG } from '../src/errors.js'; + +describe('Hello World worker', () => { + it('returns empty response if pathname provided is not a valid api url', async () => { + const results = await SELF.fetch('https://example.com/favicon.ico'); + + expect(results.status).toBe(401); + expect(await results.text()).toBe(DISALLOWED_URL_MSG); + }); + + it('returns empty response if origin is not on allowlist', async () => { + const results = await SELF.fetch( + 'https://example.com/repos/custom-hyperlane-xyz/hyperlane-registry/git/trees/main?recursive=true', + ); + + expect(results.status).toBe(401); + expect(await results.text()).toBe(DISALLOWED_URL_MSG); + }); + + it('returns empty response if origin is not on allowlist (with faker 200 tests)', async () => { + for (let i = 0; i < 200; i++) { + const results = await SELF.fetch( + `https://example.com/${faker.internet.url}`, + ); + + expect(results.status).toBe(401); + expect(await results.text()).toBe(DISALLOWED_URL_MSG); + } + }); +}); diff --git a/typescript/github-proxy/test/tsconfig.json b/typescript/github-proxy/test/tsconfig.json new file mode 100644 index 000000000..509425ffe --- /dev/null +++ b/typescript/github-proxy/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "types": [ + "@cloudflare/workers-types/experimental", + "@cloudflare/vitest-pool-workers" + ] + }, + "include": ["./**/*.ts", "../src/env.d.ts"], + "exclude": [] +} diff --git a/typescript/github-proxy/tsconfig.json b/typescript/github-proxy/tsconfig.json new file mode 100644 index 000000000..b124d4ab8 --- /dev/null +++ b/typescript/github-proxy/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "types": [ + "@cloudflare/workers-types" + ] /* Specify type package names to be included without being referenced in a source file. */, + + "noEmit": true /* Disable emitting files from a compilation. */, + + "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */, + "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */ + }, + "exclude": ["test"], + "include": ["worker-configuration.d.ts", "src/**/*.ts"] +} diff --git a/typescript/github-proxy/vitest.config.ts b/typescript/github-proxy/vitest.config.ts new file mode 100644 index 000000000..931e5113e --- /dev/null +++ b/typescript/github-proxy/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'; + +export default defineWorkersConfig({ + test: { + poolOptions: { + workers: { + wrangler: { configPath: './wrangler.toml' }, + }, + }, + }, +}); diff --git a/typescript/github-proxy/worker-configuration.d.ts b/typescript/github-proxy/worker-configuration.d.ts new file mode 100644 index 000000000..950f110d9 --- /dev/null +++ b/typescript/github-proxy/worker-configuration.d.ts @@ -0,0 +1,6 @@ +// Generated by Wrangler on Tue Sep 03 2024 19:01:13 GMT-0400 (Eastern Daylight Time) +// by running `wrangler types` + +interface Env { + GITHUB_API_KEY: string; +} diff --git a/typescript/github-proxy/wrangler.toml b/typescript/github-proxy/wrangler.toml new file mode 100644 index 000000000..adb957c5f --- /dev/null +++ b/typescript/github-proxy/wrangler.toml @@ -0,0 +1,24 @@ +#:schema node_modules/wrangler/config-schema.json +name = "github-proxy-prod" +main = "src/index.ts" +compatibility_date = "2024-08-21" +compatibility_flags = ["nodejs_compat"] +workers_dev = false +routes = [ + { pattern = "proxy.hyperlane.xyz", custom_domain = true } +] + +# CPU limit - 10ms keeps us within the free tier. As of 9/6/2024, the median CPU time is ~1ms +[limits] +cpu_ms = 10 + +# Automatically place your workloads in an optimal location to minimize latency. +# If you are running back-end logic in a Worker, running it closer to your back-end infrastructure +# rather than the end user may result in better performance. +# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement +[placement] +mode = "smart" + +[env.staging] +name = "github-proxy-staging" +workers_dev = true \ No newline at end of file diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index c93f37421..34aba2ec9 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -4,7 +4,7 @@ "version": "5.1.0", "dependencies": { "@hyperlane-xyz/core": "5.1.0", - "@hyperlane-xyz/registry": "2.5.0", + "@hyperlane-xyz/registry": "4.0.0", "@hyperlane-xyz/sdk": "5.1.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" @@ -18,7 +18,7 @@ "@typechain/hardhat": "^9.1.0", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", - "chai": "^4.3.6", + "chai": "4.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "ethereum-waffle": "^4.0.10", diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 03db2be61..bda53492c 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -14,7 +14,7 @@ "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", "@hyperlane-xyz/helloworld": "5.1.0", - "@hyperlane-xyz/registry": "2.5.0", + "@hyperlane-xyz/registry": "4.0.0", "@hyperlane-xyz/sdk": "5.1.0", "@hyperlane-xyz/utils": "5.1.0", "@inquirer/prompts": "^5.3.8", @@ -30,7 +30,7 @@ "json-stable-stringify": "^1.1.1", "prom-client": "^14.0.1", "prompts": "^2.4.2", - "yaml": "^2.4.5", + "yaml": "2.4.5", "yargs": "^17.7.2" }, "devDependencies": { @@ -43,7 +43,7 @@ "@types/prompts": "^2.0.14", "@types/sinon-chai": "^3.2.12", "@types/yargs": "^17.0.24", - "chai": "^4.3.6", + "chai": "4.5.0", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.2", "hardhat": "^2.22.2", diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 8c612aade..d7bd4235a 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -33,7 +33,7 @@ "@types/sinon": "^17.0.1", "@types/sinon-chai": "^3.2.12", "@types/ws": "^8.5.5", - "chai": "^4.3.6", + "chai": "4.5.0", "dotenv": "^10.0.0", "eslint": "^8.57.0", "ethereum-waffle": "^4.0.10", @@ -44,7 +44,7 @@ "ts-node": "^10.8.0", "tsx": "^4.7.1", "typescript": "5.3.3", - "yaml": "^2.4.1" + "yaml": "2.4.5" }, "type": "module", "exports": { diff --git a/typescript/utils/package.json b/typescript/utils/package.json index dfee030d5..958e419be 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -9,12 +9,12 @@ "ethers": "^5.7.2", "lodash-es": "^4.17.21", "pino": "^8.19.0", - "yaml": "^2.4.1" + "yaml": "2.4.5" }, "devDependencies": { "@types/lodash-es": "^4.17.12", "@types/mocha": "^10.0.1", - "chai": "^4.3.6", + "chai": "4.5.0", "mocha": "^10.2.0", "prettier": "^2.8.8", "typescript": "5.3.3" diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index f1b421e19..dfcacb8b9 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -7,7 +7,7 @@ "react-dom": "^18" }, "dependencies": { - "@hyperlane-xyz/registry": "2.5.0", + "@hyperlane-xyz/registry": "4.0.0", "@hyperlane-xyz/sdk": "5.1.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index a619bd60b..8adeeb70f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5472,6 +5472,84 @@ __metadata: languageName: node linkType: hard +"@cloudflare/kv-asset-handler@npm:0.3.4": + version: 0.3.4 + resolution: "@cloudflare/kv-asset-handler@npm:0.3.4" + dependencies: + mime: "npm:^3.0.0" + checksum: f02840c2da8e75f3dbfe769f3ba99b99fb87b438c518c06c279334882ce7745ba5dd7ab66a07695dde0596e297758ce66761f9aac2365e7dfb83d7001cd44afa + languageName: node + linkType: hard + +"@cloudflare/vitest-pool-workers@npm:^0.4.5": + version: 0.4.28 + resolution: "@cloudflare/vitest-pool-workers@npm:0.4.28" + dependencies: + birpc: "npm:0.2.14" + cjs-module-lexer: "npm:^1.2.3" + devalue: "npm:^4.3.0" + esbuild: "npm:0.17.19" + miniflare: "npm:3.20240821.1" + semver: "npm:^7.5.1" + wrangler: "npm:3.74.0" + zod: "npm:^3.22.3" + peerDependencies: + "@vitest/runner": 1.3.x - 1.5.x + "@vitest/snapshot": 1.3.x - 1.5.x + vitest: 1.3.x - 1.5.x + checksum: f0eb2438743d53930762444b436669f8072f8230bf4847bcb3fcbcfe2e13fb16317e674855b01523bf93085cabc6831ffd3e81ae51f430125570fa4d2abf2ee0 + languageName: node + linkType: hard + +"@cloudflare/workerd-darwin-64@npm:1.20240821.1": + version: 1.20240821.1 + resolution: "@cloudflare/workerd-darwin-64@npm:1.20240821.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@cloudflare/workerd-darwin-arm64@npm:1.20240821.1": + version: 1.20240821.1 + resolution: "@cloudflare/workerd-darwin-arm64@npm:1.20240821.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@cloudflare/workerd-linux-64@npm:1.20240821.1": + version: 1.20240821.1 + resolution: "@cloudflare/workerd-linux-64@npm:1.20240821.1" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@cloudflare/workerd-linux-arm64@npm:1.20240821.1": + version: 1.20240821.1 + resolution: "@cloudflare/workerd-linux-arm64@npm:1.20240821.1" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@cloudflare/workerd-windows-64@npm:1.20240821.1": + version: 1.20240821.1 + resolution: "@cloudflare/workerd-windows-64@npm:1.20240821.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@cloudflare/workers-shared@npm:0.4.1": + version: 0.4.1 + resolution: "@cloudflare/workers-shared@npm:0.4.1" + checksum: 6f6356ccd6633052f4713ae0c074a34608bcda8406cce3a52bded9775800c023c75a443406765adfb63a5c96fca08673531a82977395537932e6e24d823f9b70 + languageName: node + linkType: hard + +"@cloudflare/workers-types@npm:^4.20240821.1": + version: 4.20240821.1 + resolution: "@cloudflare/workers-types@npm:4.20240821.1" + checksum: 981e86ba1b0899f5e1f58087f39ec3720202df9513263704efc9558038c590d67ae9b75b489250c6687ff2dde28b6652cf64d6a6442c6dfef54be3d4d7a70442 + languageName: node + linkType: hard + "@colors/colors@npm:1.5.0": version: 1.5.0 resolution: "@colors/colors@npm:1.5.0" @@ -5642,7 +5720,7 @@ __metadata: languageName: node linkType: hard -"@cspotcode/source-map-support@npm:^0.8.0": +"@cspotcode/source-map-support@npm:0.8.1, @cspotcode/source-map-support@npm:^0.8.0": version: 0.8.1 resolution: "@cspotcode/source-map-support@npm:0.8.1" dependencies: @@ -5667,6 +5745,27 @@ __metadata: languageName: node linkType: hard +"@esbuild-plugins/node-globals-polyfill@npm:^0.2.3": + version: 0.2.3 + resolution: "@esbuild-plugins/node-globals-polyfill@npm:0.2.3" + peerDependencies: + esbuild: "*" + checksum: 6452637b55da3d577b03bb6e9e9c5b88ec153a2c260a71d4f237fac1b46577e3536059030524b7088c9af7bc8da2afd926a5ebb72653876ce83621cc63d57efc + languageName: node + linkType: hard + +"@esbuild-plugins/node-modules-polyfill@npm:^0.2.2": + version: 0.2.2 + resolution: "@esbuild-plugins/node-modules-polyfill@npm:0.2.2" + dependencies: + escape-string-regexp: "npm:^4.0.0" + rollup-plugin-node-polyfills: "npm:^0.2.1" + peerDependencies: + esbuild: "*" + checksum: 0f5601f0ce46b33079c16881142966afff2a528799f85667db7cab38e53607157ef53d8e48cdb1d082b410688a536e14d87b7cd2971784b3afc15befb9b86520 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.19.12": version: 0.19.12 resolution: "@esbuild/aix-ppc64@npm:0.19.12" @@ -5681,6 +5780,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm64@npm:0.17.19" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-arm64@npm:0.18.20" @@ -5702,6 +5808,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm@npm:0.17.19" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-arm@npm:0.18.20" @@ -5723,6 +5836,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-x64@npm:0.17.19" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-x64@npm:0.18.20" @@ -5744,6 +5864,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-arm64@npm:0.17.19" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/darwin-arm64@npm:0.18.20" @@ -5765,6 +5892,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-x64@npm:0.17.19" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/darwin-x64@npm:0.18.20" @@ -5786,6 +5920,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-arm64@npm:0.17.19" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/freebsd-arm64@npm:0.18.20" @@ -5807,6 +5948,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-x64@npm:0.17.19" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/freebsd-x64@npm:0.18.20" @@ -5828,6 +5976,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm64@npm:0.17.19" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-arm64@npm:0.18.20" @@ -5849,6 +6004,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm@npm:0.17.19" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-arm@npm:0.18.20" @@ -5870,6 +6032,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ia32@npm:0.17.19" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-ia32@npm:0.18.20" @@ -5891,6 +6060,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-loong64@npm:0.17.19" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-loong64@npm:0.18.20" @@ -5912,6 +6088,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-mips64el@npm:0.17.19" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-mips64el@npm:0.18.20" @@ -5933,6 +6116,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ppc64@npm:0.17.19" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-ppc64@npm:0.18.20" @@ -5954,6 +6144,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-riscv64@npm:0.17.19" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-riscv64@npm:0.18.20" @@ -5975,6 +6172,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-s390x@npm:0.17.19" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-s390x@npm:0.18.20" @@ -5996,6 +6200,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-x64@npm:0.17.19" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-x64@npm:0.18.20" @@ -6017,6 +6228,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/netbsd-x64@npm:0.17.19" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/netbsd-x64@npm:0.18.20" @@ -6038,6 +6256,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/openbsd-x64@npm:0.17.19" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/openbsd-x64@npm:0.18.20" @@ -6059,6 +6284,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/sunos-x64@npm:0.17.19" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/sunos-x64@npm:0.18.20" @@ -6080,6 +6312,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-arm64@npm:0.17.19" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-arm64@npm:0.18.20" @@ -6101,6 +6340,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-ia32@npm:0.17.19" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-ia32@npm:0.18.20" @@ -6122,6 +6368,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-x64@npm:0.17.19" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-x64@npm:0.18.20" @@ -7117,6 +7370,13 @@ __metadata: languageName: node linkType: hard +"@faker-js/faker@npm:^8.4.1": + version: 8.4.1 + resolution: "@faker-js/faker@npm:8.4.1" + checksum: 5983c2ea64f26055ad6648de748878e11ebe2fb751e3c7435ae141cdffabc2dccfe4c4f49da69a3d2add71e21b415c683ac5fba196fab0d5ed6779fbec436c80 + languageName: node + linkType: hard + "@fal-works/esbuild-plugin-global-externals@npm:^2.1.2": version: 2.1.2 resolution: "@fal-works/esbuild-plugin-global-externals@npm:2.1.2" @@ -7330,7 +7590,7 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.577.0" "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" - "@hyperlane-xyz/registry": "npm:2.5.0" + "@hyperlane-xyz/registry": "npm:4.0.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@hyperlane-xyz/utils": "npm:5.1.0" "@inquirer/prompts": "npm:^3.0.0" @@ -7341,7 +7601,7 @@ __metadata: "@typescript-eslint/parser": "npm:^7.4.0" asn1.js: "npm:^5.4.1" bignumber.js: "npm:^9.1.1" - chai: "npm:^4.3.6" + chai: "npm:4.5.0" chalk: "npm:^5.3.0" eslint: "npm:^8.57.0" eslint-config-prettier: "npm:^9.1.0" @@ -7351,8 +7611,8 @@ __metadata: prettier: "npm:^2.8.8" terminal-link: "npm:^3.0.0" tsx: "npm:^4.7.1" - typescript: "npm:^5.1.6" - yaml: "npm:^2.4.1" + typescript: "npm:5.3.3" + yaml: "npm:2.4.5" yargs: "npm:^17.7.2" zod: "npm:^3.21.2" zod-validation-error: "npm:^3.3.0" @@ -7379,7 +7639,7 @@ __metadata: "@typechain/ethers-v6": "npm:^0.5.1" "@typechain/hardhat": "npm:^9.1.0" "@types/node": "npm:^18.14.5" - chai: "npm:^4.3.6" + chai: "npm:4.5.0" ethereum-waffle: "npm:^4.0.10" ethers: "npm:^5.7.2" fx-portal: "npm:^1.0.3" @@ -7403,12 +7663,27 @@ __metadata: languageName: unknown linkType: soft +"@hyperlane-xyz/github-proxy@workspace:typescript/github-proxy": + version: 0.0.0-use.local + resolution: "@hyperlane-xyz/github-proxy@workspace:typescript/github-proxy" + dependencies: + "@cloudflare/vitest-pool-workers": "npm:^0.4.5" + "@cloudflare/workers-types": "npm:^4.20240821.1" + "@faker-js/faker": "npm:^8.4.1" + chai: "npm:4.5.0" + prettier: "npm:^2.8.8" + typescript: "npm:5.3.3" + vitest: "npm:1.4.0" + wrangler: "npm:^3.74.0" + languageName: unknown + linkType: soft + "@hyperlane-xyz/helloworld@npm:5.1.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: "@hyperlane-xyz/core": "npm:5.1.0" - "@hyperlane-xyz/registry": "npm:2.5.0" + "@hyperlane-xyz/registry": "npm:4.0.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" @@ -7419,7 +7694,7 @@ __metadata: "@typechain/hardhat": "npm:^9.1.0" "@typescript-eslint/eslint-plugin": "npm:^7.4.0" "@typescript-eslint/parser": "npm:^7.4.0" - chai: "npm:^4.3.6" + chai: "npm:4.5.0" eslint: "npm:^8.57.0" eslint-config-prettier: "npm:^9.1.0" ethereum-waffle: "npm:^4.0.10" @@ -7457,7 +7732,7 @@ __metadata: "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" "@hyperlane-xyz/helloworld": "npm:5.1.0" - "@hyperlane-xyz/registry": "npm:2.5.0" + "@hyperlane-xyz/registry": "npm:4.0.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@hyperlane-xyz/utils": "npm:5.1.0" "@inquirer/prompts": "npm:^5.3.8" @@ -7477,7 +7752,7 @@ __metadata: "@types/yargs": "npm:^17.0.24" asn1.js: "npm:5.4.1" aws-kms-ethers-signer: "npm:^0.1.3" - chai: "npm:^4.3.6" + chai: "npm:4.5.0" deep-object-diff: "npm:^1.1.9" dotenv: "npm:^10.0.0" ethereum-waffle: "npm:^4.0.10" @@ -7490,7 +7765,7 @@ __metadata: prompts: "npm:^2.4.2" tsx: "npm:^4.7.1" typescript: "npm:5.3.3" - yaml: "npm:^2.4.5" + yaml: "npm:2.4.5" yargs: "npm:^17.7.2" peerDependencies: "@ethersproject/abi": "*" @@ -7515,13 +7790,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/registry@npm:2.5.0": - version: 2.5.0 - resolution: "@hyperlane-xyz/registry@npm:2.5.0" +"@hyperlane-xyz/registry@npm:4.0.0": + version: 4.0.0 + resolution: "@hyperlane-xyz/registry@npm:4.0.0" dependencies: - yaml: "npm:^2" + yaml: "npm:2.4.5" zod: "npm:^3.21.2" - checksum: 24f433c0938dc31913b0f7a93b880a9aa15eabebf664eb11f319c51f6b38163929429405dd996b8964f8a2f43dfa4ba5424b157ad6fd39432653e46e128e0ffc + checksum: 90dfe259343fa68315ea58a58e60d47261a6af33fab63f1d0708e2c19ff057977a878b1e0079811388634e08ddf40fd4f99d03ea519cb8ad96d2ce1063ebdff5 languageName: node linkType: hard @@ -7550,7 +7825,7 @@ __metadata: "@types/ws": "npm:^8.5.5" "@wagmi/chains": "npm:^1.8.0" bignumber.js: "npm:^9.1.1" - chai: "npm:^4.3.6" + chai: "npm:4.5.0" coingecko-api: "npm:^1.0.10" cosmjs-types: "npm:^0.9.0" cross-fetch: "npm:^3.1.5" @@ -7567,7 +7842,7 @@ __metadata: tsx: "npm:^4.7.1" typescript: "npm:5.3.3" viem: "npm:^1.20.0" - yaml: "npm:^2.4.1" + yaml: "npm:2.4.5" zod: "npm:^3.21.2" peerDependencies: "@ethersproject/abi": "*" @@ -7584,14 +7859,14 @@ __metadata: "@types/lodash-es": "npm:^4.17.12" "@types/mocha": "npm:^10.0.1" bignumber.js: "npm:^9.1.1" - chai: "npm:^4.3.6" + chai: "npm:4.5.0" ethers: "npm:^5.7.2" lodash-es: "npm:^4.17.21" mocha: "npm:^10.2.0" pino: "npm:^8.19.0" prettier: "npm:^2.8.8" typescript: "npm:5.3.3" - yaml: "npm:^2.4.1" + yaml: "npm:2.4.5" languageName: unknown linkType: soft @@ -7599,7 +7874,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: - "@hyperlane-xyz/registry": "npm:2.5.0" + "@hyperlane-xyz/registry": "npm:4.0.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" @@ -10241,6 +10516,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.21.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-android-arm64@npm:4.19.1" @@ -10248,6 +10530,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-android-arm64@npm:4.21.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-darwin-arm64@npm:4.19.1" @@ -10255,6 +10544,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-darwin-arm64@npm:4.21.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-darwin-x64@npm:4.19.1" @@ -10262,6 +10558,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-darwin-x64@npm:4.21.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.19.1" @@ -10269,6 +10572,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.21.2" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-musleabihf@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.19.1" @@ -10276,6 +10586,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.21.2" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.19.1" @@ -10283,6 +10600,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.21.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.19.1" @@ -10290,6 +10614,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.21.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-powerpc64le-gnu@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.19.1" @@ -10297,6 +10628,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.19.1" @@ -10304,6 +10642,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.21.2" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.19.1" @@ -10311,6 +10656,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.21.2" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.19.1" @@ -10318,6 +10670,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.21.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-linux-x64-musl@npm:4.19.1" @@ -10325,6 +10684,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.21.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.19.1" @@ -10332,6 +10698,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.21.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.19.1" @@ -10339,6 +10712,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.21.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.19.1": version: 4.19.1 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.19.1" @@ -10346,6 +10726,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.21.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@safe-global/api-kit@npm:1.3.0": version: 1.3.0 resolution: "@safe-global/api-kit@npm:1.3.0" @@ -12797,6 +13184,15 @@ __metadata: languageName: node linkType: hard +"@types/node-forge@npm:^1.3.0": + version: 1.3.11 + resolution: "@types/node-forge@npm:1.3.11" + dependencies: + "@types/node": "npm:*" + checksum: 670c9b377c48189186ec415e3c8ed371f141ecc1a79ab71b213b20816adeffecba44dae4f8406cc0d09e6349a4db14eb8c5893f643d8e00fa19fc035cf49dee0 + languageName: node + linkType: hard + "@types/node@npm:*": version: 17.0.42 resolution: "@types/node@npm:17.0.42" @@ -13471,6 +13867,17 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:1.4.0": + version: 1.4.0 + resolution: "@vitest/expect@npm:1.4.0" + dependencies: + "@vitest/spy": "npm:1.4.0" + "@vitest/utils": "npm:1.4.0" + chai: "npm:^4.3.10" + checksum: 00d794a807b7e496d8450133430c8528d4b6cfaba9520bf49640c941b14acaa7b28f151c249b44d935740cae887f0648980db63f38e37bdeb6c2906387e15188 + languageName: node + linkType: hard + "@vitest/expect@npm:^0.34.2": version: 0.34.7 resolution: "@vitest/expect@npm:0.34.7" @@ -13482,6 +13889,28 @@ __metadata: languageName: node linkType: hard +"@vitest/runner@npm:1.4.0": + version: 1.4.0 + resolution: "@vitest/runner@npm:1.4.0" + dependencies: + "@vitest/utils": "npm:1.4.0" + p-limit: "npm:^5.0.0" + pathe: "npm:^1.1.1" + checksum: 7b8a692de5cef72ef698e83eb5bbb89076924e7a557ed087e80c5080e000a575f34c481f3b880aa2588da5a095504dc55216c319f6924eddfcfc3412f10a27b2 + languageName: node + linkType: hard + +"@vitest/snapshot@npm:1.4.0": + version: 1.4.0 + resolution: "@vitest/snapshot@npm:1.4.0" + dependencies: + magic-string: "npm:^0.30.5" + pathe: "npm:^1.1.1" + pretty-format: "npm:^29.7.0" + checksum: 43e22f8aeef4b87bcce79b37775415d4b558e32d906992d4a0acbe81c8e84cbfe3e488dd32c504c4f4d8f2c3f96842acb524b4b210036fda6796e64d0140d5f6 + languageName: node + linkType: hard + "@vitest/spy@npm:0.34.7, @vitest/spy@npm:^0.34.1": version: 0.34.7 resolution: "@vitest/spy@npm:0.34.7" @@ -13491,6 +13920,15 @@ __metadata: languageName: node linkType: hard +"@vitest/spy@npm:1.4.0": + version: 1.4.0 + resolution: "@vitest/spy@npm:1.4.0" + dependencies: + tinyspy: "npm:^2.2.0" + checksum: 0e48f9a64f62801c2abf10df1013ec5e5b75c47bdca6a5d4c8246b3dd7bdf01ade3df6c99fd0751a870a16bd63c127b3e58e0f5cbc320c48d0727ab5da89d028 + languageName: node + linkType: hard + "@vitest/utils@npm:0.34.7, @vitest/utils@npm:^0.34.6": version: 0.34.7 resolution: "@vitest/utils@npm:0.34.7" @@ -13502,6 +13940,18 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:1.4.0": + version: 1.4.0 + resolution: "@vitest/utils@npm:1.4.0" + dependencies: + diff-sequences: "npm:^29.6.3" + estree-walker: "npm:^3.0.3" + loupe: "npm:^2.3.7" + pretty-format: "npm:^29.7.0" + checksum: 2261705e2edc10376f2524a4bf6616688680094d94fff683681a1ef8d3d59271dee2d80893efad8e6437bbdb00390e2edd754d94cf42100db86f2cfd9c44826f + languageName: node + linkType: hard + "@wagmi/chains@npm:^1.8.0": version: 1.8.0 resolution: "@wagmi/chains@npm:1.8.0" @@ -13697,6 +14147,15 @@ __metadata: languageName: node linkType: hard +"acorn-walk@npm:^8.2.0, acorn-walk@npm:^8.3.2": + version: 8.3.3 + resolution: "acorn-walk@npm:8.3.3" + dependencies: + acorn: "npm:^8.11.0" + checksum: 59701dcb7070679622ba8e9c7f37577b4935565747ca0fd7c1c3ad30b3f1b1b008276282664e323b5495eb49f77fa12d3816fd06dc68e18f90fbebe759f71450 + languageName: node + linkType: hard + "acorn@npm:^7.4.1": version: 7.4.1 resolution: "acorn@npm:7.4.1" @@ -13706,7 +14165,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.3, acorn@npm:^8.12.1": +"acorn@npm:^8.11.0, acorn@npm:^8.11.3, acorn@npm:^8.12.1, acorn@npm:^8.8.0": version: 8.12.1 resolution: "acorn@npm:8.12.1" bin: @@ -14221,6 +14680,15 @@ __metadata: languageName: node linkType: hard +"as-table@npm:^1.0.36": + version: 1.0.55 + resolution: "as-table@npm:1.0.55" + dependencies: + printable-characters: "npm:^1.0.42" + checksum: 8bbfbd7b6f240efb22f6553f756e89d1cae074e9f7a24580282e9d247c1bd9cf1fd9fb49056202a78a5e69907209d8bf032d8b6c3eaaab5fb6ad92da64a7894a + languageName: node + linkType: hard + "asap@npm:~2.0.6": version: 2.0.6 resolution: "asap@npm:2.0.6" @@ -14741,8 +15209,15 @@ __metadata: languageName: node linkType: hard -"bl@npm:^4.0.3, bl@npm:^4.1.0": - version: 4.1.0 +"birpc@npm:0.2.14": + version: 0.2.14 + resolution: "birpc@npm:0.2.14" + checksum: 4c6329a05f6fc27ac524d3b94f44c3532ee9be75e8a773db950f8ad7a64962905cbe589873cb390294d770e67fd1a1fe4df98f1eab59874aa62d6dd07abe163b + languageName: node + linkType: hard + +"bl@npm:^4.0.3, bl@npm:^4.1.0": + version: 4.1.0 resolution: "bl@npm:4.1.0" dependencies: buffer: "npm:^5.5.0" @@ -14752,6 +15227,13 @@ __metadata: languageName: node linkType: hard +"blake3-wasm@npm:^2.1.5": + version: 2.1.5 + resolution: "blake3-wasm@npm:2.1.5" + checksum: 7138aa209ac8411755ba07df7d035974886aac1fb4bb8cf710d354732037069bacc9984c19b3bc68bf5e17cc203f454cc9cfcb7115393aaf21ce865630dbf920 + languageName: node + linkType: hard + "blakejs@npm:^1.1.0": version: 1.2.1 resolution: "blakejs@npm:1.2.1" @@ -15181,6 +15663,13 @@ __metadata: languageName: node linkType: hard +"cac@npm:^6.7.14": + version: 6.7.14 + resolution: "cac@npm:6.7.14" + checksum: 002769a0fbfc51c062acd2a59df465a2a947916b02ac50b56c69ec6c018ee99ac3e7f4dd7366334ea847f1ecacf4defaa61bcd2ac283db50156ce1f1d8c8ad42 + languageName: node + linkType: hard + "cacache@npm:^16.1.0": version: 16.1.1 resolution: "cacache@npm:16.1.1" @@ -15338,6 +15827,16 @@ __metadata: languageName: node linkType: hard +"capnp-ts@npm:^0.7.0": + version: 0.7.0 + resolution: "capnp-ts@npm:0.7.0" + dependencies: + debug: "npm:^4.3.1" + tslib: "npm:^2.2.0" + checksum: 186a76662e31ab16fe46fe0785ed2a511969d0c5198e2d7baec6b44f71c9b3bf8c05e7627036dc86c2d3ddc229c846559350c13f904fdd8da3590d7054715ba8 + languageName: node + linkType: hard + "case@npm:^1.6.3": version: 1.6.3 resolution: "case@npm:1.6.3" @@ -15378,7 +15877,7 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.10, chai@npm:^4.3.7": +"chai@npm:4.5.0, chai@npm:^4.3.10, chai@npm:^4.3.7": version: 4.5.0 resolution: "chai@npm:4.5.0" dependencies: @@ -15393,7 +15892,7 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.4, chai@npm:^4.3.6": +"chai@npm:^4.3.4": version: 4.3.6 resolution: "chai@npm:4.3.6" dependencies: @@ -15622,6 +16121,13 @@ __metadata: languageName: node linkType: hard +"cjs-module-lexer@npm:^1.2.3": + version: 1.4.0 + resolution: "cjs-module-lexer@npm:1.4.0" + checksum: b041096749792526120d8b8756929f8ef5dd4596502a0e1013f857e3027acd6091915fea77037921d70ee1a99988a100d994d3d3c2e323b04dd4c5ffd516cf13 + languageName: node + linkType: hard + "class-is@npm:^1.1.0": version: 1.1.0 resolution: "class-is@npm:1.1.0" @@ -16133,7 +16639,7 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0": +"cookie@npm:0.5.0, cookie@npm:^0.5.0": version: 0.5.0 resolution: "cookie@npm:0.5.0" checksum: aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 @@ -16418,6 +16924,20 @@ __metadata: languageName: node linkType: hard +"data-uri-to-buffer@npm:^2.0.0": + version: 2.0.2 + resolution: "data-uri-to-buffer@npm:2.0.2" + checksum: 152bec5e77513ee253a7c686700a1723246f582dad8b614e8eaaaba7fa45a15c8671ae4b8f4843f4f3a002dae1d3e7a20f852f7d7bdc8b4c15cfe7adfdfb07f8 + languageName: node + linkType: hard + +"date-fns@npm:^3.6.0": + version: 3.6.0 + resolution: "date-fns@npm:3.6.0" + checksum: cac35c58926a3b5d577082ff2b253612ec1c79eb6754fddef46b6a8e826501ea2cb346ecbd211205f1ba382ddd1f9d8c3f00bf433ad63cc3063454d294e3a6b8 + languageName: node + linkType: hard + "death@npm:^1.1.0": version: 1.1.0 resolution: "death@npm:1.1.0" @@ -16816,6 +17336,13 @@ __metadata: languageName: node linkType: hard +"devalue@npm:^4.3.0": + version: 4.3.3 + resolution: "devalue@npm:4.3.3" + checksum: b53ab9fe1b7b9e45c3eeebe8ff59ef294aaa8f8206c61fa49dedcccb65622882e68b69f1c1c8e7129ff5590a405cd6fb5dbe88afd6fb0f6861d5393cdce93c76 + languageName: node + linkType: hard + "didyoumean@npm:^1.2.2": version: 1.2.2 resolution: "didyoumean@npm:1.2.2" @@ -17438,6 +17965,83 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:0.17.19": + version: 0.17.19 + resolution: "esbuild@npm:0.17.19" + dependencies: + "@esbuild/android-arm": "npm:0.17.19" + "@esbuild/android-arm64": "npm:0.17.19" + "@esbuild/android-x64": "npm:0.17.19" + "@esbuild/darwin-arm64": "npm:0.17.19" + "@esbuild/darwin-x64": "npm:0.17.19" + "@esbuild/freebsd-arm64": "npm:0.17.19" + "@esbuild/freebsd-x64": "npm:0.17.19" + "@esbuild/linux-arm": "npm:0.17.19" + "@esbuild/linux-arm64": "npm:0.17.19" + "@esbuild/linux-ia32": "npm:0.17.19" + "@esbuild/linux-loong64": "npm:0.17.19" + "@esbuild/linux-mips64el": "npm:0.17.19" + "@esbuild/linux-ppc64": "npm:0.17.19" + "@esbuild/linux-riscv64": "npm:0.17.19" + "@esbuild/linux-s390x": "npm:0.17.19" + "@esbuild/linux-x64": "npm:0.17.19" + "@esbuild/netbsd-x64": "npm:0.17.19" + "@esbuild/openbsd-x64": "npm:0.17.19" + "@esbuild/sunos-x64": "npm:0.17.19" + "@esbuild/win32-arm64": "npm:0.17.19" + "@esbuild/win32-ia32": "npm:0.17.19" + "@esbuild/win32-x64": "npm:0.17.19" + dependenciesMeta: + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 86ada7cad6d37a3445858fee31ca39fc6c0436c7c00b2e07b9ce308235be67f36aefe0dda25da9ab08653fde496d1e759d6ad891ce9479f9e1fb4964c8f2a0fa + languageName: node + linkType: hard + "esbuild@npm:^0.18.0": version: 0.18.20 resolution: "esbuild@npm:0.18.20" @@ -17956,6 +18560,13 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^0.6.1": + version: 0.6.1 + resolution: "estree-walker@npm:0.6.1" + checksum: b8da7815030c4e0b735f5f8af370af09525e052ee14e539cecabc24ad6da1782448778361417e7c438091a59e7ca9f4a0c11642f7da4f2ebf1ba7a150a590bcc + languageName: node + linkType: hard + "estree-walker@npm:^2.0.2": version: 2.0.2 resolution: "estree-walker@npm:2.0.2" @@ -17963,6 +18574,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -18301,6 +18921,13 @@ __metadata: languageName: node linkType: hard +"exit-hook@npm:^2.2.1": + version: 2.2.1 + resolution: "exit-hook@npm:2.2.1" + checksum: 75835919e0aca624daa8d114c0014ae84506c4b79ac5806748cc7a86d1610a864ee974be58eec823c7757e5e6b07a5e332647e20ef84f6cc3dc3385c953c78c9 + languageName: node + linkType: hard + "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -19414,6 +20041,16 @@ __metadata: languageName: node linkType: hard +"get-source@npm:^2.0.12": + version: 2.0.12 + resolution: "get-source@npm:2.0.12" + dependencies: + data-uri-to-buffer: "npm:^2.0.0" + source-map: "npm:^0.6.1" + checksum: 6ba35ae0755046199b57d7fe254d50c6d7550d3b150e065a3607e3da8c55c617302f4c7cc3712252c7810954a04e2e56467ad02a0798c0841a5e980064bd3048 + languageName: node + linkType: hard + "get-stream@npm:^3.0.0": version: 3.0.0 resolution: "get-stream@npm:3.0.0" @@ -21964,6 +22601,13 @@ __metadata: languageName: node linkType: hard +"js-tokens@npm:^9.0.0": + version: 9.0.0 + resolution: "js-tokens@npm:9.0.0" + checksum: 65e7a55a1a18d61f1cf94bfd7704da870b74337fa08d4c58118e69a8b10225b5ad887ff3ae595d720301b0924811a9b0594c679621a85ecbac6e3aac8533c53b + languageName: node + linkType: hard + "js-yaml@npm:3.13.1": version: 3.13.1 resolution: "js-yaml@npm:3.13.1" @@ -22631,6 +23275,16 @@ __metadata: languageName: node linkType: hard +"local-pkg@npm:^0.5.0": + version: 0.5.0 + resolution: "local-pkg@npm:0.5.0" + dependencies: + mlly: "npm:^1.4.2" + pkg-types: "npm:^1.0.3" + checksum: 20f4caba50dc6fb00ffcc1a78bc94b5acb33995e0aadf4d4edcdeab257e891aa08f50afddf02f3240b2c3d02432bc2078f2a916a280ed716b64753a3d250db70 + languageName: node + linkType: hard + "locate-path@npm:^2.0.0": version: 2.0.0 resolution: "locate-path@npm:2.0.0" @@ -22797,7 +23451,7 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.6": +"loupe@npm:^2.3.6, loupe@npm:^2.3.7": version: 2.3.7 resolution: "loupe@npm:2.3.7" dependencies: @@ -22892,6 +23546,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.25.3": + version: 0.25.9 + resolution: "magic-string@npm:0.25.9" + dependencies: + sourcemap-codec: "npm:^1.4.8" + checksum: 87a14b944bd169821cbd54b169a7ab6b0348fd44b5497266dc555dd70280744e9e88047da9dcb95675bdc23b1ce33f13398b0f70b3be7b858225ccb1d185ff51 + languageName: node + linkType: hard + "magic-string@npm:^0.27.0": version: 0.27.0 resolution: "magic-string@npm:0.27.0" @@ -22901,7 +23564,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.0": +"magic-string@npm:^0.30.0, magic-string@npm:^0.30.5": version: 0.30.11 resolution: "magic-string@npm:0.30.11" dependencies: @@ -23241,6 +23904,15 @@ __metadata: languageName: node linkType: hard +"mime@npm:^3.0.0": + version: 3.0.0 + resolution: "mime@npm:3.0.0" + bin: + mime: cli.js + checksum: b2d31580deb58be89adaa1877cbbf152b7604b980fd7ef8f08b9e96bfedf7d605d9c23a8ba62aa12c8580b910cd7c1d27b7331d0f40f7a14e17d5a0bbec3b49f + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -23299,6 +23971,28 @@ __metadata: languageName: node linkType: hard +"miniflare@npm:3.20240821.1": + version: 3.20240821.1 + resolution: "miniflare@npm:3.20240821.1" + dependencies: + "@cspotcode/source-map-support": "npm:0.8.1" + acorn: "npm:^8.8.0" + acorn-walk: "npm:^8.2.0" + capnp-ts: "npm:^0.7.0" + exit-hook: "npm:^2.2.1" + glob-to-regexp: "npm:^0.4.1" + stoppable: "npm:^1.1.0" + undici: "npm:^5.28.4" + workerd: "npm:1.20240821.1" + ws: "npm:^8.17.1" + youch: "npm:^3.2.2" + zod: "npm:^3.22.3" + bin: + miniflare: bootstrap.js + checksum: ed6945094d714474fb88a157597148d447440c3dd581e08395da8046c9d2958c402976a017b2172981af517c5dd74b635103682a50e971ce4e565f73b89535b0 + languageName: node + linkType: hard + "minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": version: 1.0.1 resolution: "minimalistic-assert@npm:1.0.1" @@ -23558,7 +24252,7 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.7.1": +"mlly@npm:^1.4.2, mlly@npm:^1.7.1": version: 1.7.1 resolution: "mlly@npm:1.7.1" dependencies: @@ -23784,6 +24478,15 @@ __metadata: languageName: node linkType: hard +"mustache@npm:^4.2.0": + version: 4.2.0 + resolution: "mustache@npm:4.2.0" + bin: + mustache: bin/mustache + checksum: 6e668bd5803255ab0779c3983b9412b5c4f4f90e822230e0e8f414f5449ed7a137eed29430e835aa689886f663385cfe05f808eb34b16e1f3a95525889b05cd3 + languageName: node + linkType: hard + "mute-stream@npm:^1.0.0": version: 1.0.0 resolution: "mute-stream@npm:1.0.0" @@ -23827,7 +24530,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.7": +"nanoid@npm:^3.3.3, nanoid@npm:^3.3.7": version: 3.3.7 resolution: "nanoid@npm:3.3.7" bin: @@ -24011,6 +24714,13 @@ __metadata: languageName: node linkType: hard +"node-forge@npm:^1": + version: 1.3.1 + resolution: "node-forge@npm:1.3.1" + checksum: 05bab6868633bf9ad4c3b1dd50ec501c22ffd69f556cdf169a00998ca1d03e8107a6032ba013852f202035372021b845603aeccd7dfcb58cdb7430013b3daa8d + languageName: node + linkType: hard + "node-gyp-build@npm:4.3.0": version: 4.3.0 resolution: "node-gyp-build@npm:4.3.0" @@ -24597,6 +25307,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^5.0.0": + version: 5.0.0 + resolution: "p-limit@npm:5.0.0" + dependencies: + yocto-queue: "npm:^1.0.0" + checksum: 87bf5837dee6942f0dbeff318436179931d9a97848d1b07dbd86140a477a5d2e6b90d9701b210b4e21fe7beaea2979dfde366e4f576fa644a59bd4d6a6371da7 + languageName: node + linkType: hard + "p-locate@npm:^2.0.0": version: 2.0.0 resolution: "p-locate@npm:2.0.0" @@ -24865,6 +25584,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^6.2.0": + version: 6.2.2 + resolution: "path-to-regexp@npm:6.2.2" + checksum: f7d11c1a9e02576ce0294f4efdc523c11b73894947afdf7b23a0d0f7c6465d7a7772166e770ddf1495a8017cc0ee99e3e8a15ed7302b6b948b89a6dd4eea895e + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -24872,7 +25598,7 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.2": +"pathe@npm:^1.1.1, pathe@npm:^1.1.2": version: 1.1.2 resolution: "pathe@npm:1.1.2" checksum: f201d796351bf7433d147b92c20eb154a4e0ea83512017bf4ec4e492a5d6e738fb45798be4259a61aa81270179fce11026f6ff0d3fa04173041de044defe9d80 @@ -25040,6 +25766,17 @@ __metadata: languageName: node linkType: hard +"pkg-types@npm:^1.0.3": + version: 1.2.0 + resolution: "pkg-types@npm:1.2.0" + dependencies: + confbox: "npm:^0.1.7" + mlly: "npm:^1.7.1" + pathe: "npm:^1.1.2" + checksum: ed732842b86260395b82e31afc0dd8316e74642a78754ad148a5500ca5537565c6dfbd6c80c2dc92077afc1beb471b05a85a9572089cc8a1bba82248c331bf45 + languageName: node + linkType: hard + "pkg-types@npm:^1.1.1": version: 1.1.3 resolution: "pkg-types@npm:1.1.3" @@ -25148,6 +25885,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.43": + version: 8.4.44 + resolution: "postcss@npm:8.4.44" + dependencies: + nanoid: "npm:^3.3.7" + picocolors: "npm:^1.0.1" + source-map-js: "npm:^1.2.0" + checksum: aac7ed383fdcde9def6ed814ee03bc3de68b345e3f9bea414df2daca08185b6cfb4044fe9f67e1d9e886f29642373b34fd4fde5976204ca66a5481859afdcb7d + languageName: node + linkType: hard + "prebuild-install@npm:^5.3.4": version: 5.3.6 resolution: "prebuild-install@npm:5.3.6" @@ -25298,6 +26046,13 @@ __metadata: languageName: node linkType: hard +"printable-characters@npm:^1.0.42": + version: 1.0.42 + resolution: "printable-characters@npm:1.0.42" + checksum: 5fd9f44f2b24c9d875a97642a72be27f53aaac7f0f8f2792f969f3082e4516878db21cfa999f827606b002a890e6afeac0e0cc8dcb0d2d7965252975e634c6b2 + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -26399,7 +27154,7 @@ __metadata: languageName: node linkType: hard -"resolve.exports@npm:^2.0.0": +"resolve.exports@npm:^2.0.0, resolve.exports@npm:^2.0.2": version: 2.0.2 resolution: "resolve.exports@npm:2.0.2" checksum: f1cc0b6680f9a7e0345d783e0547f2a5110d8336b3c2a4227231dd007271ffd331fd722df934f017af90bae0373920ca0d4005da6f76cb3176c8ae426370f893 @@ -26435,7 +27190,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.2": +"resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.2, resolve@npm:^1.22.8": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -26477,7 +27232,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin": +"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -26622,6 +27377,35 @@ __metadata: languageName: node linkType: hard +"rollup-plugin-inject@npm:^3.0.0": + version: 3.0.2 + resolution: "rollup-plugin-inject@npm:3.0.2" + dependencies: + estree-walker: "npm:^0.6.1" + magic-string: "npm:^0.25.3" + rollup-pluginutils: "npm:^2.8.1" + checksum: 34081611c4b00b582339fc76880844d9729d9a26ede987c9939440cb0affe5965d4c9b1ebb62a021bb67e118426420de77114731404fa57126e35186267548e7 + languageName: node + linkType: hard + +"rollup-plugin-node-polyfills@npm:^0.2.1": + version: 0.2.1 + resolution: "rollup-plugin-node-polyfills@npm:0.2.1" + dependencies: + rollup-plugin-inject: "npm:^3.0.0" + checksum: 283c108108f93684975c83fd2b274d028162a9df0db2225737bfd0f8cab9215f0228d3703928ef667a8ba2f4749649ba06c58b89f48a211d7116e7f98fc988dd + languageName: node + linkType: hard + +"rollup-pluginutils@npm:^2.8.1": + version: 2.8.2 + resolution: "rollup-pluginutils@npm:2.8.2" + dependencies: + estree-walker: "npm:^0.6.1" + checksum: f3dc20a8731523aff43e07fa50ed84857e9dd3ab81e2cfb0351d517c46820e585bfbd1530a5dddec3ac14d61d41eb9bf50b38ded987e558292790331cc5b0628 + languageName: node + linkType: hard + "rollup@npm:^2.25.0 || ^3.3.0": version: 3.29.4 resolution: "rollup@npm:3.29.4" @@ -26699,6 +27483,69 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.20.0": + version: 4.21.2 + resolution: "rollup@npm:4.21.2" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.21.2" + "@rollup/rollup-android-arm64": "npm:4.21.2" + "@rollup/rollup-darwin-arm64": "npm:4.21.2" + "@rollup/rollup-darwin-x64": "npm:4.21.2" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.21.2" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.21.2" + "@rollup/rollup-linux-arm64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-arm64-musl": "npm:4.21.2" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.21.2" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-s390x-gnu": "npm:4.21.2" + "@rollup/rollup-linux-x64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-x64-musl": "npm:4.21.2" + "@rollup/rollup-win32-arm64-msvc": "npm:4.21.2" + "@rollup/rollup-win32-ia32-msvc": "npm:4.21.2" + "@rollup/rollup-win32-x64-msvc": "npm:4.21.2" + "@types/estree": "npm:1.0.5" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 5d679af1a04170f7164e3e975a375adb76f9bbf34d1ad8d9c3fa789252d377e7d364dfee054a4283121f9f9368d7b35404b9d42fb260be314d34739243ab0722 + languageName: node + linkType: hard + "rpc-websockets@npm:^7.5.1": version: 7.5.1 resolution: "rpc-websockets@npm:7.5.1" @@ -26896,6 +27743,16 @@ __metadata: languageName: node linkType: hard +"selfsigned@npm:^2.0.1": + version: 2.4.1 + resolution: "selfsigned@npm:2.4.1" + dependencies: + "@types/node-forge": "npm:^1.3.0" + node-forge: "npm:^1" + checksum: 52536623f1cfdeb2f8b9198377f2ce7931c677ea69421238d1dc1ea2983bbe258e56c19e7d1af87035cad7270f19b7e996eaab1212e724d887722502f68e17f2 + languageName: node + linkType: hard + "semaphore-async-await@npm:^1.5.1": version: 1.5.1 resolution: "semaphore-async-await@npm:1.5.1" @@ -26950,6 +27807,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.5.1": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 36b1fbe1a2b6f873559cd57b238f1094a053dbfd997ceeb8757d79d1d2089c56d1321b9f1069ce263dc64cfa922fa1d2ad566b39426fe1ac6c723c1487589e10 + languageName: node + linkType: hard + "semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" @@ -27196,6 +28062,13 @@ __metadata: languageName: node linkType: hard +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: e93ff66c6531a079af8fb217240df01f980155b5dc408d2d7bebc398dd284e383eb318153bf8acd4db3c4fe799aa5b9a641e38b0ba3b1975700b1c89547ea4e7 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -27665,6 +28538,13 @@ __metadata: languageName: node linkType: hard +"sourcemap-codec@npm:^1.4.8": + version: 1.4.8 + resolution: "sourcemap-codec@npm:1.4.8" + checksum: 6fc57a151e982b5c9468362690c6d062f3a0d4d8520beb68a82f319c79e7a4d7027eeb1e396de0ecc2cd19491e1d602b2d06fd444feac9b63dd43fea4c55a857 + languageName: node + linkType: hard + "space-separated-tokens@npm:^1.0.0": version: 1.1.5 resolution: "space-separated-tokens@npm:1.1.5" @@ -27769,6 +28649,13 @@ __metadata: languageName: node linkType: hard +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 + languageName: node + linkType: hard + "stacktrace-parser@npm:^0.1.10": version: 0.1.10 resolution: "stacktrace-parser@npm:0.1.10" @@ -27778,6 +28665,16 @@ __metadata: languageName: node linkType: hard +"stacktracey@npm:^2.1.8": + version: 2.1.8 + resolution: "stacktracey@npm:2.1.8" + dependencies: + as-table: "npm:^1.0.36" + get-source: "npm:^2.0.12" + checksum: c87f708b639636788c4b46ecc6e503c27b6124bec724bcdc3180d7cdddfab0dee370225009e3b407adaedf847362cfc77af64f01c805516e39a28d16c6d40df8 + languageName: node + linkType: hard + "statuses@npm:2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" @@ -27785,6 +28682,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.5.0": + version: 3.7.0 + resolution: "std-env@npm:3.7.0" + checksum: 6ee0cca1add3fd84656b0002cfbc5bfa20340389d9ba4720569840f1caa34bce74322aef4c93f046391583e50649d0cf81a5f8fe1d411e50b659571690a45f12 + languageName: node + linkType: hard + "stealthy-require@npm:^1.1.1": version: 1.1.1 resolution: "stealthy-require@npm:1.1.1" @@ -27801,6 +28705,13 @@ __metadata: languageName: node linkType: hard +"stoppable@npm:^1.1.0": + version: 1.1.0 + resolution: "stoppable@npm:1.1.0" + checksum: 63104fcbdece130bc4906fd982061e763d2ef48065ed1ab29895e5ad00552c625f8a4c50c9cd2e3bfa805c8a2c3bfdda0f07c5ae39694bd2d5cb0bee1618d1e9 + languageName: node + linkType: hard + "store2@npm:^2.14.2": version: 2.14.3 resolution: "store2@npm:2.14.3" @@ -28124,6 +29035,15 @@ __metadata: languageName: node linkType: hard +"strip-literal@npm:^2.0.0": + version: 2.1.0 + resolution: "strip-literal@npm:2.1.0" + dependencies: + js-tokens: "npm:^9.0.0" + checksum: 21c813aa1e669944e7e2318c8c927939fb90b0c52f53f57282bfc3dd6e19d53f70004f1f1693e33e5e790ad5ef102b0fce2b243808229d1ce07ae71f326c0e82 + languageName: node + linkType: hard + "strnum@npm:^1.0.5": version: 1.0.5 resolution: "strnum@npm:1.0.5" @@ -28603,7 +29523,21 @@ __metadata: languageName: node linkType: hard -"tinyspy@npm:^2.1.1": +"tinybench@npm:^2.5.1": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: cfa1e1418e91289219501703c4693c70708c91ffb7f040fd318d24aef419fb5a43e0c0160df9471499191968b2451d8da7f8087b08c3133c251c40d24aced06c + languageName: node + linkType: hard + +"tinypool@npm:^0.8.2": + version: 0.8.4 + resolution: "tinypool@npm:0.8.4" + checksum: 7365944c2532f240111443e7012be31a634faf1a02db08a91db3aa07361c26a374d0be00a0f2ea052c4bee39c107ba67f1f814c108d9d51dfc725c559c1a9c03 + languageName: node + linkType: hard + +"tinyspy@npm:^2.1.1, tinyspy@npm:^2.2.0": version: 2.2.1 resolution: "tinyspy@npm:2.2.1" checksum: 170d6232e87f9044f537b50b406a38fbfd6f79a261cd12b92879947bd340939a833a678632ce4f5c4a6feab4477e9c21cd43faac3b90b68b77dd0536c4149736 @@ -28862,6 +29796,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^2.2.0": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 9a5b47ddac65874fa011c20ff76db69f97cf90c78cff5934799ab8894a5342db2d17b4e7613a087046bc1d133d21547ddff87ac558abeec31ffa929c88b7fce6 + languageName: node + linkType: hard + "tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" @@ -29193,16 +30134,6 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.1.6": - version: 5.3.2 - resolution: "typescript@npm:5.3.2" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 415e5fb6611f5713e460bad48039f00bcfdbde53a2f911727862d5aa9c5d5edd250059a419df382d8f031709e15a169c41eb62b6a401da5eec7ac0f4e359d6ac - languageName: node - linkType: hard - "typescript@patch:typescript@npm%3A5.3.3#optional!builtin": version: 5.3.3 resolution: "typescript@patch:typescript@npm%3A5.3.3#optional!builtin::version=5.3.3&hash=e012d7" @@ -29213,16 +30144,6 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.1.6#optional!builtin": - version: 5.3.2 - resolution: "typescript@patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 1b45cdfb577a78ae7a9a9d0b77a7b772142cb98ba05e4e5aefba7044a028ded885bcecef63166407a5986645cea816fe4986894336aacd5e791796ea79a6a7ed - languageName: node - linkType: hard - "typical@npm:^4.0.0": version: 4.0.0 resolution: "typical@npm:4.0.0" @@ -29244,7 +30165,7 @@ __metadata: languageName: node linkType: hard -"ufo@npm:^1.5.3": +"ufo@npm:^1.5.3, ufo@npm:^1.5.4": version: 1.5.4 resolution: "ufo@npm:1.5.4" checksum: a885ed421e656aea6ca64e9727b8118a9488715460b6f1a0f0427118adfe2f2830fe7c1d5bd9c5c754a332e6807516551cd663ea67ce9ed6a4e3edc739916335 @@ -29309,6 +30230,18 @@ __metadata: languageName: node linkType: hard +"unenv@npm:unenv-nightly@2.0.0-1724863496.70db6f1": + version: 2.0.0-1724863496.70db6f1 + resolution: "unenv-nightly@npm:2.0.0-1724863496.70db6f1" + dependencies: + defu: "npm:^6.1.4" + ohash: "npm:^1.1.3" + pathe: "npm:^1.1.2" + ufo: "npm:^1.5.4" + checksum: 1133947cc084eedc2d256025f81d0c3716600415efe6f49950091084b0ece18b02d676f07537e5de17237621f5499d3ed754c8f35cd13109252ed1b204b38c55 + languageName: node + linkType: hard + "unfetch@npm:^4.2.0": version: 4.2.0 resolution: "unfetch@npm:4.2.0" @@ -29751,6 +30684,64 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:1.4.0": + version: 1.4.0 + resolution: "vite-node@npm:1.4.0" + dependencies: + cac: "npm:^6.7.14" + debug: "npm:^4.3.4" + pathe: "npm:^1.1.1" + picocolors: "npm:^1.0.0" + vite: "npm:^5.0.0" + bin: + vite-node: vite-node.mjs + checksum: 691e828c2abe6b62d44183c4e04bdfd119fed405439126fbdc5bfb791644baee3961c1ce429a67b360cc3d8b7c472160c7e82c59491f044a232b4ff480d8a2a2 + languageName: node + linkType: hard + +"vite@npm:^5.0.0": + version: 5.4.3 + resolution: "vite@npm:5.4.3" + dependencies: + esbuild: "npm:^0.21.3" + fsevents: "npm:~2.3.3" + postcss: "npm:^8.4.43" + rollup: "npm:^4.20.0" + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 864bf64fe57bd26b1527ea6d8dac2f4f8b834791f836590043463c0ded6a150a9407ffac6a859abc34ec013ecfcd23f405c20aa76f4ad99deab1176d5f017574 + languageName: node + linkType: hard + "vite@npm:^5.1.1": version: 5.3.5 resolution: "vite@npm:5.3.5" @@ -29791,6 +30782,56 @@ __metadata: languageName: node linkType: hard +"vitest@npm:1.4.0": + version: 1.4.0 + resolution: "vitest@npm:1.4.0" + dependencies: + "@vitest/expect": "npm:1.4.0" + "@vitest/runner": "npm:1.4.0" + "@vitest/snapshot": "npm:1.4.0" + "@vitest/spy": "npm:1.4.0" + "@vitest/utils": "npm:1.4.0" + acorn-walk: "npm:^8.3.2" + chai: "npm:^4.3.10" + debug: "npm:^4.3.4" + execa: "npm:^8.0.1" + local-pkg: "npm:^0.5.0" + magic-string: "npm:^0.30.5" + pathe: "npm:^1.1.1" + picocolors: "npm:^1.0.0" + std-env: "npm:^3.5.0" + strip-literal: "npm:^2.0.0" + tinybench: "npm:^2.5.1" + tinypool: "npm:^0.8.2" + vite: "npm:^5.0.0" + vite-node: "npm:1.4.0" + why-is-node-running: "npm:^2.2.2" + peerDependencies: + "@edge-runtime/vm": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": 1.4.0 + "@vitest/ui": 1.4.0 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: cf4675657f4a9ea755d0af70d62827fca9daee64e81d0392067c70a0d1f5f8fd4a47523e28ecf42d667e4d4d7c68b09d5e08389d4b58dc36065364f6c76cda7d + languageName: node + linkType: hard + "walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" @@ -30361,6 +31402,18 @@ __metadata: languageName: node linkType: hard +"why-is-node-running@npm:^2.2.2": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: "npm:^2.0.0" + stackback: "npm:0.0.2" + bin: + why-is-node-running: cli.js + checksum: 0de6e6cd8f2f94a8b5ca44e84cf1751eadcac3ebedcdc6e5fbbe6c8011904afcbc1a2777c53496ec02ced7b81f2e7eda61e76bf8262a8bc3ceaa1f6040508051 + languageName: node + linkType: hard + "wide-align@npm:1.1.3": version: 1.1.3 resolution: "wide-align@npm:1.1.3" @@ -30412,6 +31465,32 @@ __metadata: languageName: node linkType: hard +"workerd@npm:1.20240821.1": + version: 1.20240821.1 + resolution: "workerd@npm:1.20240821.1" + dependencies: + "@cloudflare/workerd-darwin-64": "npm:1.20240821.1" + "@cloudflare/workerd-darwin-arm64": "npm:1.20240821.1" + "@cloudflare/workerd-linux-64": "npm:1.20240821.1" + "@cloudflare/workerd-linux-arm64": "npm:1.20240821.1" + "@cloudflare/workerd-windows-64": "npm:1.20240821.1" + dependenciesMeta: + "@cloudflare/workerd-darwin-64": + optional: true + "@cloudflare/workerd-darwin-arm64": + optional: true + "@cloudflare/workerd-linux-64": + optional: true + "@cloudflare/workerd-linux-arm64": + optional: true + "@cloudflare/workerd-windows-64": + optional: true + bin: + workerd: bin/workerd + checksum: 4784019f2cd638efd505bd895766c76bf21f56333e93f4f1665c97e8c8877f9ef46ef2ce1682127706aa607902e8ea4dcfec852427858e78454a0d6181de38ce + languageName: node + linkType: hard + "workerpool@npm:6.2.1": version: 6.2.1 resolution: "workerpool@npm:6.2.1" @@ -30419,6 +31498,44 @@ __metadata: languageName: node linkType: hard +"wrangler@npm:3.74.0, wrangler@npm:^3.74.0": + version: 3.74.0 + resolution: "wrangler@npm:3.74.0" + dependencies: + "@cloudflare/kv-asset-handler": "npm:0.3.4" + "@cloudflare/workers-shared": "npm:0.4.1" + "@esbuild-plugins/node-globals-polyfill": "npm:^0.2.3" + "@esbuild-plugins/node-modules-polyfill": "npm:^0.2.2" + blake3-wasm: "npm:^2.1.5" + chokidar: "npm:^3.5.3" + date-fns: "npm:^3.6.0" + esbuild: "npm:0.17.19" + fsevents: "npm:~2.3.2" + miniflare: "npm:3.20240821.1" + nanoid: "npm:^3.3.3" + path-to-regexp: "npm:^6.2.0" + resolve: "npm:^1.22.8" + resolve.exports: "npm:^2.0.2" + selfsigned: "npm:^2.0.1" + source-map: "npm:^0.6.1" + unenv: "npm:unenv-nightly@2.0.0-1724863496.70db6f1" + workerd: "npm:1.20240821.1" + xxhash-wasm: "npm:^1.0.1" + peerDependencies: + "@cloudflare/workers-types": ^4.20240821.1 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@cloudflare/workers-types": + optional: true + bin: + wrangler: bin/wrangler.js + wrangler2: bin/wrangler.js + checksum: 12e3b97eca2ac1ce6f28d7b584e5be3f17377d84c7794df95dc68f6eadccabcf1a6640db7f76ceebc8855159b603dbc1f453dc27ff536a831a9e913c6d681151 + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" @@ -30571,7 +31688,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.2.3": +"ws@npm:^8.17.1, ws@npm:^8.2.3": version: 8.18.0 resolution: "ws@npm:8.18.0" peerDependencies: @@ -30646,6 +31763,13 @@ __metadata: languageName: node linkType: hard +"xxhash-wasm@npm:^1.0.1": + version: 1.0.2 + resolution: "xxhash-wasm@npm:1.0.2" + checksum: fb66e00f57c87353688ff31a8456ca71e16b1c13610d94d09f83cbd859a1985de07ccfc6aa912a045c991da0078d4122d78d409123e36557afab7ce5d3b04a98 + languageName: node + linkType: hard + "y18n@npm:^4.0.0": version: 4.0.3 resolution: "y18n@npm:4.0.3" @@ -30688,6 +31812,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:2.4.5": + version: 2.4.5 + resolution: "yaml@npm:2.4.5" + bin: + yaml: bin.mjs + checksum: b09bf5a615a65276d433d76b8e34ad6b4c0320b85eb3f1a39da132c61ae6e2ff34eff4624e6458d96d49566c93cf43408ba5e568218293a8c6541a2006883f64 + languageName: node + linkType: hard + "yaml@npm:^1.10.2": version: 1.10.2 resolution: "yaml@npm:1.10.2" @@ -30695,15 +31828,6 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2, yaml@npm:^2.4.1": - version: 2.4.1 - resolution: "yaml@npm:2.4.1" - bin: - yaml: bin.mjs - checksum: 2c54fd69ef59126758ae710f9756405a7d41abcbb61aca894250d0e81e76057c14dc9bb00a9528f72f99b8f24077f694a6f7fd09cdd6711fcec2eebfbb5df409 - languageName: node - linkType: hard - "yaml@npm:^2.3.4": version: 2.5.0 resolution: "yaml@npm:2.5.0" @@ -30713,15 +31837,6 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.4.5": - version: 2.4.5 - resolution: "yaml@npm:2.4.5" - bin: - yaml: bin.mjs - checksum: b09bf5a615a65276d433d76b8e34ad6b4c0320b85eb3f1a39da132c61ae6e2ff34eff4624e6458d96d49566c93cf43408ba5e568218293a8c6541a2006883f64 - languageName: node - linkType: hard - "yargs-parser@npm:13.1.2, yargs-parser@npm:^13.1.2": version: 13.1.2 resolution: "yargs-parser@npm:13.1.2" @@ -30877,6 +31992,13 @@ __metadata: languageName: node linkType: hard +"yocto-queue@npm:^1.0.0": + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: f2e05b767ed3141e6372a80af9caa4715d60969227f38b1a4370d60bffe153c9c5b33a862905609afc9b375ec57cd40999810d20e5e10229a204e8bde7ef255c + languageName: node + linkType: hard + "yoctocolors-cjs@npm:^2.1.2": version: 2.1.2 resolution: "yoctocolors-cjs@npm:2.1.2" @@ -30884,6 +32006,17 @@ __metadata: languageName: node linkType: hard +"youch@npm:^3.2.2": + version: 3.3.3 + resolution: "youch@npm:3.3.3" + dependencies: + cookie: "npm:^0.5.0" + mustache: "npm:^4.2.0" + stacktracey: "npm:^2.1.8" + checksum: d13fb6f1e756823397ba02dd0c6f8a1b060a21327238872b46677ea1e1570b6b90fe216560a2ff9f34ba2eead6c442403b70df44354c6224bbfe31cc9a182c38 + languageName: node + linkType: hard + "zksync-web3@npm:^0.14.3": version: 0.14.4 resolution: "zksync-web3@npm:0.14.4" @@ -30909,6 +32042,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.22.3": + version: 3.23.8 + resolution: "zod@npm:3.23.8" + checksum: 846fd73e1af0def79c19d510ea9e4a795544a67d5b34b7e1c4d0425bf6bfd1c719446d94cdfa1721c1987d891321d61f779e8236fde517dc0e524aa851a6eff1 + languageName: node + linkType: hard + "zx@npm:^8.1.4": version: 8.1.4 resolution: "zx@npm:8.1.4" From 741477a0b1f25fbde37446e36c10d3e75e802895 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:52:54 +0100 Subject: [PATCH 023/224] feat: update validators and ICA owners for recent deployments (#4467) feat: update validators for latest chain deployment - add merkly validators to new chains - add luganodes to default fraxtal ISM - add renzo to default mode ISM - add solana validators - add eclipse validators feat: configure ICA ownership for recently deployed chains: - jul26 batch - xlayer cheesechain worldchain - zircuit is already safe-owned - aug5 batch - cyber degenchain kroma lisk lukso merlin metis mint proofofplay real sanko tangle xai - taiko is already safe-owned - aug26 batch - astar astarzkevm bitlayer coredao dogechain flare molten shibarium drive-by: - improve formatting on check-validator-announce script --- .../config/environments/mainnet3/owners.ts | 33 +++++ .../infra/scripts/check-validator-announce.ts | 91 +++++++++++++- .../infra/src/govern/HyperlaneAppGovernor.ts | 4 +- typescript/sdk/src/consts/multisigIsm.ts | 114 +++++++++++++----- typescript/sdk/src/ism/EvmIsmReader.ts | 2 +- 5 files changed, 209 insertions(+), 35 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/owners.ts b/typescript/infra/config/environments/mainnet3/owners.ts index 028f5d8a4..c0a1e34d9 100644 --- a/typescript/infra/config/environments/mainnet3/owners.ts +++ b/typescript/infra/config/environments/mainnet3/owners.ts @@ -66,6 +66,39 @@ export const icas: Partial< > = { viction: '0x23ed65DE22ac29Ec1C16E75EddB0cE3A187357b4', inevm: '0xFDF9EDcb2243D51f5f317b9CEcA8edD2bEEE036e', + + // Jul 26, 2024 batch + // ------------------------------------- + xlayer: '0x1571c482fe9E76bbf50829912b1c746792966369', + cheesechain: '0xEe2C5320BE9bC7A1492187cfb289953b53E3ff1b', + worldchain: '0x1996DbFcFB433737fE404F58D2c32A7f5f334210', + // zircuit: '0x0d67c56E818a02ABa58cd2394b95EF26db999aA3', // already has a safe + + // Aug 5, 2024 batch + cyber: '0x984Fe5a45Ac4aaeC4E4655b50f776aB79c9Be19F', + degenchain: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A', + kroma: '0xc1e20A0D78E79B94D71d4bDBC8FD0Af7c856Dd7A', + lisk: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A', + lukso: '0xc1e20A0D78E79B94D71d4bDBC8FD0Af7c856Dd7A', + merlin: '0xCf867cEaeeE8CBe65C680c734D29d26440931D5b', + metis: '0xb51e63CD0842D670a13c88B159fCFc268DA652A3', + mint: '0xb51e63CD0842D670a13c88B159fCFc268DA652A3', + proofofplay: '0xb51e63CD0842D670a13c88B159fCFc268DA652A3', + real: '0xc761e68BF3A94326FD0D305e3ccb4cdaab2edA19', + sanko: '0x5DAcd2f1AafC749F2935A160865Ab1568eC23752', + tangle: '0xCC2aeb692197C7894E561d31ADFE8F79746f7d9F', + xai: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A', + // taiko: '0x483D218D2FEe7FC7204ba15F00C7901acbF9697D', // already has a safe + + // Aug 26, 2024 batch + astar: '0x6b241544eBa7d89B51b72DF85a0342dAa37371Ca', + astarzkevm: '0x526c6DAee1175A1A2337E703B63593acb327Dde4', + bitlayer: '0xe6239316cA60814229E801fF0B9DD71C9CA29008', + coredao: '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F', + dogechain: '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F', + flare: '0x689b8DaBBF2f9Fd83D37427A062B30edF463e20b', + molten: '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F', + shibarium: '0x6348FAe3a8374dbAAaE84EEe5458AE4063Fe2be7', } as const; export const DEPLOYER = '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba'; diff --git a/typescript/infra/scripts/check-validator-announce.ts b/typescript/infra/scripts/check-validator-announce.ts index 28e29ce74..2857ceab4 100644 --- a/typescript/infra/scripts/check-validator-announce.ts +++ b/typescript/infra/scripts/check-validator-announce.ts @@ -1,4 +1,4 @@ -import { defaultMultisigConfigs } from '@hyperlane-xyz/sdk'; +import { ChainMap, defaultMultisigConfigs } from '@hyperlane-xyz/sdk'; import { eqAddress } from '@hyperlane-xyz/utils'; import { isEthereumProtocolChain } from '../src/utils/utils.js'; @@ -6,6 +6,19 @@ import { isEthereumProtocolChain } from '../src/utils/utils.js'; import { getArgs, withChains } from './agent-utils.js'; import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js'; +const minimumValidatorCount = 3; + +const getMinimumThreshold = (validatorCount: number): number => + Math.floor(validatorCount / 2) + 1; + +const thresholdOK = 'threshold OK'; +const totalOK = 'total OK'; + +enum CheckResult { + OK = '✅', + WARNING = '🚨', +} + async function main() { const { environment, chains } = await withChains(getArgs()).argv; const config = getEnvironmentConfig(environment); @@ -15,6 +28,8 @@ async function main() { chains && chains.length > 0 ? chains : config.supportedChainNames ).filter(isEthereumProtocolChain); + const chainsWithUnannouncedValidators: ChainMap = {}; + const results = await Promise.all( targetNetworks.map(async (chain) => { const validatorAnnounce = core.getContracts(chain).validatorAnnounce; @@ -22,20 +37,88 @@ async function main() { await validatorAnnounce.getAnnouncedValidators(); const validators = defaultMultisigConfigs[chain].validators || []; - const missingValidators = validators.filter( + const unannouncedValidators = validators.filter( (validator) => !announcedValidators.some((x) => eqAddress(x, validator)), ); + if (unannouncedValidators.length > 0) { + chainsWithUnannouncedValidators[chain] = unannouncedValidators; + } + + const validatorCount = validators.length; + const unannouncedValidatorCount = unannouncedValidators.length; + + const threshold = defaultMultisigConfigs[chain].threshold; + const minimumThreshold = getMinimumThreshold(validatorCount); + return { chain, - status: - missingValidators.length === 0 ? '✅' : missingValidators.join(', '), + threshold, + [thresholdOK]: + threshold < minimumThreshold || threshold > validatorCount + ? CheckResult.WARNING + : CheckResult.OK, + total: validatorCount, + [totalOK]: + validatorCount < minimumValidatorCount + ? CheckResult.WARNING + : CheckResult.OK, + unannounced: + unannouncedValidatorCount > 0 ? unannouncedValidatorCount : '', }; }), ); console.table(results); + + const invalidThresholdChains = results + .filter((r) => r[thresholdOK] === CheckResult.WARNING) + .map((r) => r.chain); + + const lowValidatorCountChains = results + .filter((r) => r[totalOK] === CheckResult.WARNING) + .map((r) => ({ + chain: r.chain, + neededValidators: minimumValidatorCount - r.total, + })); + + if (invalidThresholdChains.length > 0) { + console.log('\n⚠️ Chains with invalid thresholds:'); + invalidThresholdChains.forEach((chain) => { + const validatorCount = defaultMultisigConfigs[chain].validators.length; + const minimumThreshold = getMinimumThreshold(validatorCount); + console.log( + ` - ${chain}:`, + `threshold should be ${minimumThreshold} ≤ t ≤ ${validatorCount}`, + ); + }); + } else { + console.log('\n✅ Thresholds look good!'); + } + + if (lowValidatorCountChains.length > 0) { + console.log('\n⚠️ Chains with low validator counts:'); + lowValidatorCountChains.forEach((c) => { + console.log( + ` - ${c.chain}: needs ${c.neededValidators} more validator${ + c.neededValidators === 1 ? '' : 's' + }`, + ); + }); + } else { + console.log('\n✅ Validator counts look good!'); + } + + const unnanouncedChains = Object.keys(chainsWithUnannouncedValidators); + if (unnanouncedChains.length > 0) { + console.log('\n⚠️ Chains with unannounced validators:'); + unnanouncedChains.forEach((chain) => { + console.log(` - ${chain}: ${chainsWithUnannouncedValidators[chain]}`); + }); + } else { + console.log('\n✅ All validators announced!'); + } } main().catch(console.error); diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index c6ca3d87f..f901e9c67 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -168,9 +168,7 @@ export abstract class HyperlaneAppGovernor< const safeOwner = this.checker.configMap[chain].ownerOverrides?._safeAddress; - if (!safeOwner) { - console.warn(`No Safe owner found for chain ${chain}`); - } else { + if (safeOwner) { await retryAsync( () => sendCallsForType( diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index 473ff86a3..5e43d8623 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -38,13 +38,21 @@ export const defaultMultisigConfigs: ChainMap = { }, astar: { - threshold: 1, - validators: ['0x4d1b2cade01ee3493f44304653d8e352c66ec3e7'], + threshold: 2, + validators: [ + '0x4d1b2cade01ee3493f44304653d8e352c66ec3e7', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, astarzkevm: { - threshold: 1, - validators: ['0x89ecdd6caf138934bf3a2fb7b323984d72fd66de'], + threshold: 2, + validators: [ + '0x89ecdd6caf138934bf3a2fb7b323984d72fd66de', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, avalanche: { @@ -73,8 +81,12 @@ export const defaultMultisigConfigs: ChainMap = { }, bitlayer: { - threshold: 1, - validators: ['0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f'], + threshold: 2, + validators: [ + '0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, blast: { @@ -148,8 +160,12 @@ export const defaultMultisigConfigs: ChainMap = { }, coredao: { - threshold: 1, - validators: ['0xbd6e158a3f5830d99d7d2bce192695bc4a148de2'], + threshold: 2, + validators: [ + '0xbd6e158a3f5830d99d7d2bce192695bc4a148de2', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, cyber: { @@ -171,13 +187,22 @@ export const defaultMultisigConfigs: ChainMap = { }, dogechain: { - threshold: 1, - validators: ['0xe43f742c37858746e6d7e458bc591180d0cba440'], + threshold: 2, + validators: [ + '0xe43f742c37858746e6d7e458bc591180d0cba440', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, eclipsemainnet: { - threshold: 1, - validators: ['0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0'], + threshold: 3, + validators: [ + '0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0', + '0x3571223e745dc0fcbdefa164c9b826b90c0d2dac', // luganodes + '0xea83086a62617a7228ce4206fae2ea8b0ab23513', // imperator + '0x4d4629f5bfeabe66edc7a78da26ef5273c266f97', // eclipse + ], }, eclipsetestnet: { @@ -213,13 +238,21 @@ export const defaultMultisigConfigs: ChainMap = { }, everclear: { - threshold: 1, - validators: ['0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837'], + threshold: 2, + validators: [ + '0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0xD79DFbF56ee2268f061cc613027a44A880f61Ba2', // everclear + ], }, flare: { - threshold: 1, - validators: ['0xb65e52be342dba3ab2c088ceeb4290c744809134'], + threshold: 2, + validators: [ + '0xb65e52be342dba3ab2c088ceeb4290c744809134', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, fraxtal: { @@ -227,6 +260,7 @@ export const defaultMultisigConfigs: ChainMap = { validators: [ '0x4bce180dac6da60d0f3a2bdf036ffe9004f944c1', '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x25b3a88f7cfd3c9f7d7e32b295673a16a6ddbd91', // luganodes ], }, @@ -313,6 +347,7 @@ export const defaultMultisigConfigs: ChainMap = { validators: [ '0xa5e953701dcddc5b958b5defb677a829d908df6d', '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters ], }, @@ -366,16 +401,22 @@ export const defaultMultisigConfigs: ChainMap = { }, mode: { - threshold: 2, + threshold: 3, validators: [ '0x7eb2e1920a4166c19d6884c1cec3d2cf356fc9b7', '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + '0x7e29608c6e5792bbf9128599ca309be0728af7b4', // renzo + '0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters ], }, molten: { - threshold: 1, - validators: ['0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f'], + threshold: 2, + validators: [ + '0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, moonbeam: { @@ -402,8 +443,12 @@ export const defaultMultisigConfigs: ChainMap = { }, oortmainnet: { - threshold: 1, - validators: ['0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7'], + threshold: 2, + validators: [ + '0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7', + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + '0x032dE4f94676bF9314331e7D83E8Db4aC74c9E21', // oort + ], }, optimism: { @@ -479,6 +524,7 @@ export const defaultMultisigConfigs: ChainMap = { validators: [ '0x1400b9737007f7978d8b4bbafb4a69c83f0641a7', '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis ], }, @@ -511,10 +557,12 @@ export const defaultMultisigConfigs: ChainMap = { }, sei: { - threshold: 2, + threshold: 3, validators: [ '0x9920d2dbf6c85ffc228fdc2e810bf895732c6aa5', '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis ], }, @@ -528,8 +576,12 @@ export const defaultMultisigConfigs: ChainMap = { }, shibarium: { - threshold: 1, - validators: ['0xfa33391ee38597cbeef72ccde8c9e13e01e78521'], + threshold: 2, + validators: [ + '0xfa33391ee38597cbeef72ccde8c9e13e01e78521', + '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, solanadevnet: { @@ -542,8 +594,14 @@ export const defaultMultisigConfigs: ChainMap = { }, solanamainnet: { - threshold: 1, - validators: ['0x28464752829b3ea59a497fca0bdff575c534c3ff'], + threshold: 3, + validators: [ + '0x28464752829b3ea59a497fca0bdff575c534c3ff', + '0x2b7514a2f77bd86bbf093fe6bb67d8611f51c659', // luganodes + '0xd90ea26ff731d967c5ea660851f7d63cb04ab820', // dsrv + '0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8', // everstake + '0xcb6bcbd0de155072a7ff486d9d7286b0f71dcc2d', // eclipse + ], }, solanatestnet: { @@ -628,10 +686,12 @@ export const defaultMultisigConfigs: ChainMap = { }, zetachain: { - threshold: 2, + threshold: 3, validators: [ '0xa3bca0b80317dbf9c7dce16a16ac89f4ff2b23ef', '0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly + '0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis ], }, diff --git a/typescript/sdk/src/ism/EvmIsmReader.ts b/typescript/sdk/src/ism/EvmIsmReader.ts index c252a94a9..c7d766e8c 100644 --- a/typescript/sdk/src/ism/EvmIsmReader.ts +++ b/typescript/sdk/src/ism/EvmIsmReader.ts @@ -112,7 +112,7 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { throw new Error(`Unknown ISM ModuleType: ${moduleType}`); } } catch (e: any) { - const errorMessage = `Failed to derive ISM module type ${moduleType} (${address}):\n\t${e}`; + const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`; this.logger.debug(errorMessage); throw new Error(errorMessage); } finally { From 291c5fe36a568e3c0a7ada5ea5d5dfc8030310ff Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:08:49 +0100 Subject: [PATCH 024/224] chore: move gasLimit buffer calculation to utils (#4482) drive-by: move gasLimit buffer calculation to utils --- .changeset/gorgeous-panthers-switch.md | 6 ++++++ .changeset/quick-students-cover.md | 5 +++++ typescript/helloworld/src/app/app.ts | 5 ++--- .../src/multiProtocolApp/evmAdapter.ts | 5 ++--- typescript/infra/src/govern/multisend.ts | 9 +++++++-- typescript/sdk/src/deploy/EvmModuleDeployer.ts | 10 +++++----- typescript/sdk/src/deploy/HyperlaneDeployer.ts | 5 +++-- typescript/sdk/src/ism/EvmIsmModule.ts | 5 +++-- typescript/sdk/src/ism/HyperlaneIsmFactory.ts | 13 +++++++------ typescript/sdk/src/providers/MultiProvider.ts | 11 ++++++++--- .../sdk/src/router/HyperlaneRouterDeployer.ts | 3 ++- typescript/utils/src/amount.ts | 18 ++++++++++++++++++ typescript/utils/src/index.ts | 1 + 13 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 .changeset/gorgeous-panthers-switch.md create mode 100644 .changeset/quick-students-cover.md diff --git a/.changeset/gorgeous-panthers-switch.md b/.changeset/gorgeous-panthers-switch.md new file mode 100644 index 000000000..df3bbe95d --- /dev/null +++ b/.changeset/gorgeous-panthers-switch.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/helloworld': minor +'@hyperlane-xyz/sdk': minor +--- + +Use addBufferToGasLimit from @hyperlane-xyz/utils diff --git a/.changeset/quick-students-cover.md b/.changeset/quick-students-cover.md new file mode 100644 index 000000000..00ce3a8e0 --- /dev/null +++ b/.changeset/quick-students-cover.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/utils': minor +--- + +Add addBufferToGasLimit for gas limit buffer calculations diff --git a/typescript/helloworld/src/app/app.ts b/typescript/helloworld/src/app/app.ts index 809cdaf7d..4cdde7761 100644 --- a/typescript/helloworld/src/app/app.ts +++ b/typescript/helloworld/src/app/app.ts @@ -9,7 +9,7 @@ import { MultiProvider, RouterApp, } from '@hyperlane-xyz/sdk'; -import { Address, rootLogger } from '@hyperlane-xyz/utils'; +import { Address, addBufferToGasLimit, rootLogger } from '@hyperlane-xyz/utils'; import { HelloWorld } from '../types/index.js'; @@ -52,12 +52,11 @@ export class HelloWorldApp extends RouterApp { message, { ...transactionOverrides, value }, ); - const gasLimit = estimated.mul(12).div(10); const quote = await sender.quoteDispatch(toDomain, message); const tx = await sender.sendHelloWorld(toDomain, message, { + gasLimit: addBufferToGasLimit(estimated), ...transactionOverrides, - gasLimit, value: value.add(quote), }); this.logger.info('Sending hello message', { diff --git a/typescript/helloworld/src/multiProtocolApp/evmAdapter.ts b/typescript/helloworld/src/multiProtocolApp/evmAdapter.ts index 5d9bacc23..964571cd3 100644 --- a/typescript/helloworld/src/multiProtocolApp/evmAdapter.ts +++ b/typescript/helloworld/src/multiProtocolApp/evmAdapter.ts @@ -7,7 +7,7 @@ import { MultiProtocolProvider, ProviderType, } from '@hyperlane-xyz/sdk'; -import { Address } from '@hyperlane-xyz/utils'; +import { Address, addBufferToGasLimit } from '@hyperlane-xyz/utils'; import { HelloWorld, HelloWorld__factory } from '../types/index.js'; @@ -54,14 +54,13 @@ export class EvmHelloWorldAdapter value: BigNumber.from(value).add(quote), }, ); - const gasLimit = estimated.mul(12).div(10); const tx = await contract.populateTransaction.sendHelloWorld( toDomain, message, { + gasLimit: addBufferToGasLimit(estimated), ...transactionOverrides, - gasLimit, value: BigNumber.from(value).add(quote), }, ); diff --git a/typescript/infra/src/govern/multisend.ts b/typescript/infra/src/govern/multisend.ts index 26c066ff8..01b05b293 100644 --- a/typescript/infra/src/govern/multisend.ts +++ b/typescript/infra/src/govern/multisend.ts @@ -3,7 +3,12 @@ import Safe from '@safe-global/protocol-kit'; import { SafeTransaction } from '@safe-global/safe-core-sdk-types'; import { ChainName, MultiProvider } from '@hyperlane-xyz/sdk'; -import { Address, CallData, eqAddress } from '@hyperlane-xyz/utils'; +import { + Address, + CallData, + addBufferToGasLimit, + eqAddress, +} from '@hyperlane-xyz/utils'; import { createSafeTransaction, @@ -28,7 +33,7 @@ export class SignerMultiSend extends MultiSend { for (const call of calls) { const estimate = await this.multiProvider.estimateGas(this.chain, call); const receipt = await this.multiProvider.sendTransaction(this.chain, { - gasLimit: estimate.mul(11).div(10), // 10% buffer + gasLimit: addBufferToGasLimit(estimate), ...call, }); console.log(`confirmed tx ${receipt.transactionHash}`); diff --git a/typescript/sdk/src/deploy/EvmModuleDeployer.ts b/typescript/sdk/src/deploy/EvmModuleDeployer.ts index 0d098134a..377a1ffd2 100644 --- a/typescript/sdk/src/deploy/EvmModuleDeployer.ts +++ b/typescript/sdk/src/deploy/EvmModuleDeployer.ts @@ -7,7 +7,7 @@ import { TransparentUpgradeableProxy__factory, } from '@hyperlane-xyz/core'; import { buildArtifact as coreBuildArtifact } from '@hyperlane-xyz/core/buildArtifact.js'; -import { Address, rootLogger } from '@hyperlane-xyz/utils'; +import { Address, addBufferToGasLimit, rootLogger } from '@hyperlane-xyz/utils'; import { HyperlaneContracts, HyperlaneFactories } from '../contracts/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; @@ -74,10 +74,10 @@ export class EvmModuleDeployer { ...initializeArgs, ); - // deploy with 10% buffer on gas limit + // deploy with buffer on gas limit const overrides = this.multiProvider.getTransactionOverrides(chain); const initTx = await contract.initialize(...initializeArgs, { - gasLimit: estimatedGas.add(estimatedGas.div(10)), + gasLimit: addBufferToGasLimit(estimatedGas), ...overrides, }); @@ -284,13 +284,13 @@ export class EvmModuleDeployer { overrides, ); - // add 10% buffer + // add gas buffer const hash = await factory['deploy(address[],uint8)']( sortedValues, threshold, { + gasLimit: addBufferToGasLimit(estimatedGas), ...overrides, - gasLimit: estimatedGas.add(estimatedGas.div(10)), // 10% buffer }, ); diff --git a/typescript/sdk/src/deploy/HyperlaneDeployer.ts b/typescript/sdk/src/deploy/HyperlaneDeployer.ts index c771337a5..ef5acfc1b 100644 --- a/typescript/sdk/src/deploy/HyperlaneDeployer.ts +++ b/typescript/sdk/src/deploy/HyperlaneDeployer.ts @@ -15,6 +15,7 @@ import { buildArtifact as coreBuildArtifact } from '@hyperlane-xyz/core/buildArt import { Address, ProtocolType, + addBufferToGasLimit, eqAddress, isZeroishAddress, rootLogger, @@ -421,10 +422,10 @@ export abstract class HyperlaneDeployer< ...initializeArgs, ); - // deploy with 10% buffer on gas limit + // deploy with buffer on gas limit const overrides = this.multiProvider.getTransactionOverrides(chain); const initTx = await contract.initialize(...initializeArgs, { - gasLimit: estimatedGas.add(estimatedGas.div(10)), + gasLimit: addBufferToGasLimit(estimatedGas), ...overrides, }); const receipt = await this.multiProvider.handleTx(chain, initTx); diff --git a/typescript/sdk/src/ism/EvmIsmModule.ts b/typescript/sdk/src/ism/EvmIsmModule.ts index c000cc341..7ab88b027 100644 --- a/typescript/sdk/src/ism/EvmIsmModule.ts +++ b/typescript/sdk/src/ism/EvmIsmModule.ts @@ -23,6 +23,7 @@ import { Address, Domain, ProtocolType, + addBufferToGasLimit, assert, deepEquals, eqAddress, @@ -538,14 +539,14 @@ export class EvmIsmModule extends HyperlaneModule< overrides, ); - // deploying new domain routing ISM, add 10% buffer + // deploying new domain routing ISM, add gas buffer const tx = await domainRoutingIsmFactory.deploy( owner, domainIds, submoduleAddresses, { + gasLimit: addBufferToGasLimit(estimatedGas), ...overrides, - gasLimit: estimatedGas.add(estimatedGas.div(10)), // 10% buffer }, ); diff --git a/typescript/sdk/src/ism/HyperlaneIsmFactory.ts b/typescript/sdk/src/ism/HyperlaneIsmFactory.ts index 15aae7b50..c2f42b8db 100644 --- a/typescript/sdk/src/ism/HyperlaneIsmFactory.ts +++ b/typescript/sdk/src/ism/HyperlaneIsmFactory.ts @@ -24,6 +24,7 @@ import { import { Address, Domain, + addBufferToGasLimit, assert, eqAddress, objFilter, @@ -400,14 +401,14 @@ export class HyperlaneIsmFactory extends HyperlaneApp { submoduleAddresses, overrides, ); - // add 10% buffer + // add gas buffer const tx = await domainRoutingIsmFactory.deploy( owner, safeConfigDomains, submoduleAddresses, { + gasLimit: addBufferToGasLimit(estimatedGas), ...overrides, - gasLimit: estimatedGas.add(estimatedGas.div(10)), // 10% buffer }, ); // TODO: Should verify contract here @@ -496,10 +497,10 @@ export class HyperlaneIsmFactory extends HyperlaneApp { threshold, overrides, ); - // add 10% buffer + // add gas buffer const hash = await factory['deploy(address[],uint8)'](sorted, threshold, { + gasLimit: addBufferToGasLimit(estimatedGas), ...overrides, - gasLimit: estimatedGas.add(estimatedGas.div(10)), // 10% buffer }); await this.multiProvider.handleTx(chain, hash); @@ -536,13 +537,13 @@ export class HyperlaneIsmFactory extends HyperlaneApp { const estimatedGas = await factory.estimateGas[ 'deploy((address,uint96)[],uint96)' ](sorted, thresholdWeight, overrides); - // add 10% buffer + // add gas buffer const hash = await factory['deploy((address,uint96)[],uint96)']( sorted, thresholdWeight, { + gasLimit: addBufferToGasLimit(estimatedGas), ...overrides, - gasLimit: estimatedGas.add(estimatedGas.div(10)), // 10% buffer }, ); diff --git a/typescript/sdk/src/providers/MultiProvider.ts b/typescript/sdk/src/providers/MultiProvider.ts index 307122e43..b37aba1c5 100644 --- a/typescript/sdk/src/providers/MultiProvider.ts +++ b/typescript/sdk/src/providers/MultiProvider.ts @@ -9,7 +9,12 @@ import { } from 'ethers'; import { Logger } from 'pino'; -import { Address, pick, rootLogger } from '@hyperlane-xyz/utils'; +import { + Address, + addBufferToGasLimit, + pick, + rootLogger, +} from '@hyperlane-xyz/utils'; import { testChainMetadata, testChains } from '../consts/testChains.js'; import { ChainMetadataManager } from '../metadata/ChainMetadataManager.js'; @@ -317,9 +322,9 @@ export class MultiProvider extends ChainMetadataManager { const deployTx = contractFactory.getDeployTransaction(...params); const gasEstimated = await signer.estimateGas(deployTx); - // deploy with 10% buffer on gas limit + // deploy with buffer on gas limit const contract = await contractFactory.deploy(...params, { - gasLimit: gasEstimated.add(gasEstimated.div(10)), // 10% buffer + gasLimit: addBufferToGasLimit(gasEstimated), ...overrides, }); diff --git a/typescript/sdk/src/router/HyperlaneRouterDeployer.ts b/typescript/sdk/src/router/HyperlaneRouterDeployer.ts index 54f502847..bc68d047c 100644 --- a/typescript/sdk/src/router/HyperlaneRouterDeployer.ts +++ b/typescript/sdk/src/router/HyperlaneRouterDeployer.ts @@ -1,6 +1,7 @@ import { Ownable, Router } from '@hyperlane-xyz/core'; import { Address, + addBufferToGasLimit, addressToBytes32, objFilter, objMap, @@ -90,7 +91,7 @@ export abstract class HyperlaneRouterDeployer< ); // deploy with 10% buffer on gas limit const enrollTx = await router.enrollRemoteRouters(domains, addresses, { - gasLimit: estimatedGas.add(estimatedGas.div(10)), + gasLimit: addBufferToGasLimit(estimatedGas), ...this.multiProvider.getTransactionOverrides(chain), }); await this.multiProvider.handleTx(chain, enrollTx); diff --git a/typescript/utils/src/amount.ts b/typescript/utils/src/amount.ts index 02f6467dd..f415c268d 100644 --- a/typescript/utils/src/amount.ts +++ b/typescript/utils/src/amount.ts @@ -1,5 +1,6 @@ import { formatUnits, parseUnits } from '@ethersproject/units'; import { BigNumber } from 'bignumber.js'; +import { ethers } from 'ethers'; const DEFAULT_DISPLAY_DECIMALS = 4; const DEFAULT_TOKEN_DECIMALS = 18; @@ -131,3 +132,20 @@ export function convertDecimals( return amount.times(BigNumber(10).pow(difference)).toString(10); } } + +// Default gas limit buffer percentage +const DEFAULT_GAS_LIMIT_BUFFER_PERCENT = 10; + +/** + * Calculates the gas limit with a buffer added to the estimated gas. + * @param estimatedGas The estimated gas for the transaction. + * @param bufferPercent The percentage to add as a buffer (default: 10%). + * @returns The calculated gas limit with the buffer added. + */ +export function addBufferToGasLimit( + estimatedGas: ethers.BigNumber, + bufferPercent: number = DEFAULT_GAS_LIMIT_BUFFER_PERCENT, +): ethers.BigNumber { + const bufferMultiplier = 100 + bufferPercent; + return estimatedGas.mul(bufferMultiplier).div(100); +} diff --git a/typescript/utils/src/index.ts b/typescript/utils/src/index.ts index fdaa20476..527c6af98 100644 --- a/typescript/utils/src/index.ts +++ b/typescript/utils/src/index.ts @@ -39,6 +39,7 @@ export { strip0x, } from './addresses.js'; export { + addBufferToGasLimit, convertDecimals, eqAmountApproximate, fromWei, From 0c54c534b96bcbbd81c300c1680de9870bbb454b Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Mon, 16 Sep 2024 12:04:17 +0100 Subject: [PATCH 025/224] chore: disable plumetestnet during airplane mode (#4488) ### Description - Plumetestnet shut down https://miles.plumenetwork.xyz/ without a specific end date - Removing it from the list of supported chains for now. Only updating infra workloads and nothing onchain atm ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../infra/config/environments/testnet4/agent.ts | 9 ++++++--- .../testnet4/aw-validators/hyperlane.json | 7 ------- .../infra/config/environments/testnet4/funding.ts | 11 +++++++---- .../infra/config/environments/testnet4/gas-oracle.ts | 6 ++++-- .../environments/testnet4/supportedChainNames.ts | 3 ++- typescript/infra/scripts/funding/deploy-key-funder.ts | 3 +-- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index 43a210e29..ed709a5e4 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -52,7 +52,8 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, optimismsepolia: true, - plumetestnet: true, + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: true, polygonamoy: true, scrollsepolia: true, sepolia: true, @@ -70,7 +71,8 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, optimismsepolia: true, - plumetestnet: true, + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: true, polygonamoy: true, scrollsepolia: true, sepolia: true, @@ -89,7 +91,8 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, optimismsepolia: true, - plumetestnet: true, + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: true, polygonamoy: true, scrollsepolia: true, sepolia: true, diff --git a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json index e1f39aaab..ae0fcf160 100644 --- a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json @@ -38,13 +38,6 @@ "optimismsepolia": { "validators": ["0x03efe4d0632ee15685d7e8f46dea0a874304aa29"] }, - "plumetestnet": { - "validators": [ - "0xe765a214849f3ecdf00793b97d00422f2d408ea6", - "0xb59998f71efc65190a85ac5e81b66bd72a192a3b", - "0xc906470a73e6b5aad65a4ceb4acd73e3eaf80e2c" - ] - }, "polygonamoy": { "validators": ["0xf0290b06e446b320bd4e9c4a519420354d7ddccd"] }, diff --git a/typescript/infra/config/environments/testnet4/funding.ts b/typescript/infra/config/environments/testnet4/funding.ts index 6ec5340b4..12f9cf622 100644 --- a/typescript/infra/config/environments/testnet4/funding.ts +++ b/typescript/infra/config/environments/testnet4/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '874a58f-20240812-172413', + tag: '344aa49-20240916-102227', }, // We're currently using the same deployer key as testnet2. // To minimize nonce clobbering we offset the key funder cron @@ -37,7 +37,8 @@ export const keyFunderConfig: KeyFunderConfig< fuji: '5', holesky: '5', optimismsepolia: '0.1', - plumetestnet: '0.2', + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: '0.2', polygonamoy: '0.2', scrollsepolia: '1', sepolia: '5', @@ -57,7 +58,8 @@ export const keyFunderConfig: KeyFunderConfig< fuji: '1', holesky: '0', optimismsepolia: '0', - plumetestnet: '0.05', + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: '0.05', polygonamoy: '0', scrollsepolia: '1', sepolia: '1', @@ -77,7 +79,8 @@ export const keyFunderConfig: KeyFunderConfig< fuji: '1', holesky: '1', optimismsepolia: '0.05', - plumetestnet: '0.1', + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: '0.1', polygonamoy: '0.1', scrollsepolia: '0.1', sepolia: '1', diff --git a/typescript/infra/config/environments/testnet4/gas-oracle.ts b/typescript/infra/config/environments/testnet4/gas-oracle.ts index 316400270..b09184c44 100644 --- a/typescript/infra/config/environments/testnet4/gas-oracle.ts +++ b/typescript/infra/config/environments/testnet4/gas-oracle.ts @@ -27,7 +27,8 @@ const gasPrices: Record< fuji: ethers.utils.parseUnits('30', 'gwei'), holesky: ethers.utils.parseUnits('10', 'gwei'), optimismsepolia: ethers.utils.parseUnits('0.5', 'gwei'), - plumetestnet: ethers.utils.parseUnits('0.01', 'gwei'), + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: ethers.utils.parseUnits('0.01', 'gwei'), polygonamoy: ethers.utils.parseUnits('100', 'gwei'), scrollsepolia: ethers.utils.parseUnits('0.5', 'gwei'), sepolia: ethers.utils.parseUnits('5', 'gwei'), @@ -65,7 +66,8 @@ const chainTokenRarity: Record< fuji: Rarity.Rare, holesky: Rarity.Common, optimismsepolia: Rarity.Common, - plumetestnet: Rarity.Common, + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // plumetestnet: Rarity.Common, polygonamoy: Rarity.Rare, scrollsepolia: Rarity.Rare, sepolia: Rarity.Mythic, diff --git a/typescript/infra/config/environments/testnet4/supportedChainNames.ts b/typescript/infra/config/environments/testnet4/supportedChainNames.ts index 2ffecf7f2..d0fb545c7 100644 --- a/typescript/infra/config/environments/testnet4/supportedChainNames.ts +++ b/typescript/infra/config/environments/testnet4/supportedChainNames.ts @@ -10,7 +10,8 @@ export const testnet4SupportedChainNames = [ 'fuji', 'holesky', 'optimismsepolia', - 'plumetestnet', + // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" + // 'plumetestnet', 'polygonamoy', 'scrollsepolia', 'sepolia', diff --git a/typescript/infra/scripts/funding/deploy-key-funder.ts b/typescript/infra/scripts/funding/deploy-key-funder.ts index 87ac67d7c..265a7e7d2 100644 --- a/typescript/infra/scripts/funding/deploy-key-funder.ts +++ b/typescript/infra/scripts/funding/deploy-key-funder.ts @@ -1,12 +1,11 @@ import { Contexts } from '../../config/contexts.js'; -import { environment } from '../../config/environments/mainnet3/chains.js'; import { KeyFunderHelmManager } from '../../src/funding/key-funder.js'; import { HelmCommand } from '../../src/utils/helm.js'; import { assertCorrectKubeContext } from '../agent-utils.js'; import { getConfigsBasedOnArgs } from '../core-utils.js'; async function main() { - const { agentConfig, envConfig, context } = await getConfigsBasedOnArgs(); + const { agentConfig, envConfig, environment } = await getConfigsBasedOnArgs(); if (agentConfig.context != Contexts.Hyperlane) throw new Error( `Invalid context ${agentConfig.context}, must be ${Contexts.Hyperlane}`, From a8f0ccd14f5805792c1d0ca39057a3910fc12002 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:59:17 +0100 Subject: [PATCH 026/224] chore: general fixes from enrolling new validators and chains (#4483) feat: enroll new validators and chains on core mailboxes - update token/gas prices - update to latest registry, containing the new ISM addresses - required some tooling fixes to handle solana/eclipse addresses being present - fix tooling where required - actually filter for EVM chains in HyperlaneAppChecker drive-by: - fix github-proxy changeset - fix print balances script - fix agent config update script - fix getRouterConfig - fix setting manual submission if unable to check on safe --- .changeset/famous-ants-tan.md | 2 +- .registryrc | 2 +- rust/main/config/mainnet_config.json | 118 ++++++++--------- typescript/cli/package.json | 2 +- typescript/helloworld/package.json | 2 +- .../environments/mainnet3/gasPrices.json | 14 +- .../environments/mainnet3/tokenPrices.json | 122 +++++++++--------- typescript/infra/package.json | 2 +- .../scripts/agents/update-agent-config.ts | 82 +++++++----- typescript/infra/scripts/check-owner-ica.ts | 64 +++++++++ typescript/infra/scripts/print-balances.ts | 94 +++++++++----- .../infra/src/govern/HyperlaneAppGovernor.ts | 63 +++++---- typescript/sdk/src/core/HyperlaneCore.ts | 22 ++-- .../sdk/src/core/HyperlaneCoreChecker.ts | 8 +- .../sdk/src/deploy/HyperlaneAppChecker.ts | 31 +++-- typescript/widgets/package.json | 2 +- yarn.lock | 16 +-- 17 files changed, 389 insertions(+), 257 deletions(-) create mode 100644 typescript/infra/scripts/check-owner-ica.ts diff --git a/.changeset/famous-ants-tan.md b/.changeset/famous-ants-tan.md index 5bc059463..927bdc346 100644 --- a/.changeset/famous-ants-tan.md +++ b/.changeset/famous-ants-tan.md @@ -1,5 +1,5 @@ --- -'github-proxy': major +'@hyperlane-xyz/github-proxy': major --- Add github proxy to reduce github API load diff --git a/.registryrc b/.registryrc index a3ab34ee4..b913b7c65 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -8e93ecb4fa207fc4822393a4c13627be3da89eaa +v4.1.0 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index 60e0a6217..fa99ee61a 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -34,7 +34,7 @@ "interchainAccountIsm": "0xd766e7C7517f2d0D92754b2fe4aE7AdEf7bDEC3e", "interchainAccountRouter": "0x25C87e735021F72d8728438C2130b02E3141f2cb", "interchainGasPaymaster": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA", - "interchainSecurityModule": "0x6C73cA7bF00FFd3617eF28E26B28EbC1e53D6075", + "interchainSecurityModule": "0x565C280Cdb56095Cf6BF23b5fF140180208CBa9e", "isTestnet": false, "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x811808Dd29ba8B0FC6C0ec0b5537035E59745162", @@ -100,7 +100,7 @@ "interchainAccountIsm": "0x2A7574358Ec53522CE2452887661AB4c86F7d400", "interchainAccountRouter": "0x91874Dbed74925dFe6059B90385EEb90DdE0B2E6", "interchainGasPaymaster": "0x3b6044acd6767f017e99318AA6Ef93b7B06A5a22", - "interchainSecurityModule": "0xC270F9DF86bb320A31757a64d1d5429B4D7a516e", + "interchainSecurityModule": "0x3d0BE14dFbB1Eb736303260c1724B6ea270c8Dc4", "mailbox": "0x979Ca5202784112f4738403dBec5D0F3B9daabB9", "merkleTreeHook": "0x748040afB89B8FdBb992799808215419d36A0930", "name": "arbitrum", @@ -172,7 +172,7 @@ "interchainAccountIsm": "0x27a3233c05C1Df7c163123301D14bE9349E3Cb48", "interchainAccountRouter": "0xa82a0227e6d6db53AF4B264A852bfF91C6504a51", "interchainGasPaymaster": "0x95519ba800BBd0d34eeAE026fEc620AD978176C0", - "interchainSecurityModule": "0xCBcE96dAa697A2A51f488a47264D623c3593bb18", + "interchainSecurityModule": "0x6723A49c12FE37ccBD08512dd586C8471743676f", "mailbox": "0xFf06aFcaABaDDd1fb08371f9ccA15D73D51FeBD6", "merkleTreeHook": "0x84eea61D679F42D92145fA052C89900CBAccE95A", "name": "avalanche", @@ -244,7 +244,7 @@ "interchainAccountIsm": "0x223F7D3f27E6272266AE4B5B91Fd5C7A2d798cD8", "interchainAccountRouter": "0x4767D22117bBeeb295413000B620B93FD8522d53", "interchainGasPaymaster": "0xc3F23848Ed2e04C0c6d41bd7804fa8f89F940B94", - "interchainSecurityModule": "0xf1d67752c6399933d850dC27F41F581a198fbEdE", + "interchainSecurityModule": "0xaeEf8f7D049C03181E0B5f2746CA2Db4d25C0B82", "mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", "merkleTreeHook": "0x19dc38aeae620380430C200a6E990D5Af5480117", "name": "base", @@ -314,7 +314,7 @@ "interchainAccountIsm": "0xe93f2f409ad8B5000431D234472973fe848dcBEC", "interchainAccountRouter": "0x2f4Eb04189e11Af642237Da62d163Ab714614498", "interchainGasPaymaster": "0xB3fCcD379ad66CED0c91028520C64226611A48c9", - "interchainSecurityModule": "0x0aa862a0039ed2d7908d749049ed2766Ff03AABb", + "interchainSecurityModule": "0xbCe3469E8C270e04ea9ccd20Efdeed2b90c9d57C", "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", "merkleTreeHook": "0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465", "name": "blast", @@ -382,7 +382,7 @@ "interchainAccountIsm": "0x451dF8AB0936D85526D816f0b4dCaDD934A034A4", "interchainAccountRouter": "0x5C02157068a52cEcfc98EDb6115DE6134EcB4764", "interchainGasPaymaster": "0x62B7592C1B6D1E43f4630B8e37f4377097840C05", - "interchainSecurityModule": "0x83a33bc769aE0b830cdbACbC82a151A1217EbD60", + "interchainSecurityModule": "0x26eA240CB4cABd7B75A9F17E7f4e224170270Ee3", "mailbox": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147", "merkleTreeHook": "0x781bE492F1232E66990d83a9D3AC3Ec26f56DAfB", "name": "bob", @@ -448,7 +448,7 @@ "interchainAccountIsm": "0x9e22945bE593946618383B108CC5bce09eBA4C26", "interchainAccountRouter": "0x32A07c1B7a7fe8D4A0e44B0181873aB9d64C16c1", "interchainGasPaymaster": "0x78E25e7f84416e69b9339B0A6336EB6EFfF6b451", - "interchainSecurityModule": "0x6a46c4db32c06bF8D6A4E2e1ed311427E8087E47", + "interchainSecurityModule": "0x0A7cE15E3cc638abC3B5FfA7Fc8F3295Ae3595D1", "mailbox": "0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4", "merkleTreeHook": "0xFDb9Cd5f9daAA2E4474019405A328a88E7484f26", "name": "bsc", @@ -528,7 +528,7 @@ "interchainAccountIsm": "0xB732c83aeE29596E3163Da2260710eAB67Bc0B29", "interchainAccountRouter": "0x27a6cAe33378bB6A6663b382070427A01fc9cB37", "interchainGasPaymaster": "0x571f1435613381208477ac5d6974310d88AC7cB7", - "interchainSecurityModule": "0x8718d2867085C065BE7a65ec669ceE4a6d0902E1", + "interchainSecurityModule": "0x33BC62504248F4cb43813532067ccAEd46a5e61C", "mailbox": "0x50da3B3907A08a24fe4999F4Dcf337E8dC7954bb", "merkleTreeHook": "0x04dB778f05854f26E67e0a66b740BBbE9070D366", "name": "celo", @@ -592,7 +592,7 @@ "interchainAccountIsm": "0x4Eb82Ee35b0a1c1d776E3a3B547f9A9bA6FCC9f2", "interchainAccountRouter": "0xEF9A332Ec1fD233Bf9344A58be56ff9E104B4f60", "interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503", - "interchainSecurityModule": "0xbf8c84422e09BB9866F9E416d6f447A33e261D05", + "interchainSecurityModule": "0xc1FF2bf7a4C315bE2a06941D236457EB02F93993", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD", "name": "cheesechain", @@ -655,7 +655,7 @@ "from": 4842212 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x18E1F88A882cE015b135Acdf356dd4F5773763B9", + "interchainSecurityModule": "0xEfFaEddFf4FFd6F8a6D714bf149b114fD34E5Fd4", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "cyber", @@ -721,7 +721,7 @@ "from": 23783929 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xcCdAcCCc5defCb56852e2945eaF0Ba2b3751B1aF", + "interchainSecurityModule": "0xB5e6AA45E117f9fD2a3F8e78432fCAfdB833d316", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "degenchain", @@ -796,7 +796,8 @@ "http": "https://mainnetbeta-rpc.eclipse.xyz" } ], - "validatorAnnounce": "Hqnn593pqDZWLy6bKZ4NbY767wFhUNBShDrLktuQa3Q2" + "validatorAnnounce": "Hqnn593pqDZWLy6bKZ4NbY767wFhUNBShDrLktuQa3Q2", + "interchainSecurityModule": "BgG35GxoaMgmiam3EJzcwivwQ2DTYGPTLfUCg7bhiH6V" }, "endurance": { "aggregationHook": "0x62c39B0500760c46Ae9Ae312A30f63445dc24C3a", @@ -831,7 +832,7 @@ "interchainAccountIsm": "0xCeafc098e5c3c7768b9229Be2FEC275862A81Abd", "interchainAccountRouter": "0xed9a722c543883FB7e07E78F3879762DE09eA7D5", "interchainGasPaymaster": "0xB30EAB08aa87138D57168D0e236850A530f49921", - "interchainSecurityModule": "0x0A5bB58D8C66Dee715C22E6Dc2FFAABBc2E2473d", + "interchainSecurityModule": "0xC0737f1EA1d0aF287c2804090370b1715c593385", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xC831271c1fB212012811a91Dd43e5926C1020563", "name": "endurance", @@ -901,7 +902,7 @@ "interchainAccountIsm": "0x292C614ED53DaaDBf971521bc2C652d1ca51cB47", "interchainAccountRouter": "0x5E532F7B610618eE73C2B462978e94CB1F7995Ce", "interchainGasPaymaster": "0x9e6B1022bE9BBF5aFd152483DAD9b88911bC8611", - "interchainSecurityModule": "0x33F9760969408cc5138Bc6683F42514a74114a53", + "interchainSecurityModule": "0xFc440a9c946Bf4840623E4adf49646089361584a", "mailbox": "0xc005dc82818d67AF737725bD4bf75435d065D239", "merkleTreeHook": "0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA", "name": "ethereum", @@ -973,7 +974,7 @@ "interchainAccountIsm": "0x7C012DCA02C42cfA3Fd7Da3B0ED7234B52AE68eF", "interchainAccountRouter": "0xbed53B5C5BCE9433f25A2A702e6df13E22d84Ae9", "interchainGasPaymaster": "0x2Fca7f6eC3d4A0408900f2BB30004d4616eE985E", - "interchainSecurityModule": "0xDEFa968CE11b3F707C785cEF07e2cFb79b6B0D14", + "interchainSecurityModule": "0x2bed66bbfE45f1d73928179e72B73e5eCF7B9900", "mailbox": "0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3", "merkleTreeHook": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147", "name": "fraxtal", @@ -1040,7 +1041,7 @@ "interchainAccountIsm": "0x9629c28990F11c31735765A6FD59E1E1bC197DbD", "interchainAccountRouter": "0x2351FBe24C1212F253b7a300ff0cBCFd97952a19", "interchainGasPaymaster": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", - "interchainSecurityModule": "0x94f9670390f63CFA0Bf49944ccD28322922b4B14", + "interchainSecurityModule": "0x1E12bdb6a33442102FEF2ab766b93c863653B4bE", "mailbox": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696", "merkleTreeHook": "0xfBc08389224d23b79cb21cDc16c5d42F0ad0F57f", "name": "fusemainnet", @@ -1113,7 +1114,7 @@ "interchainAccountIsm": "0x07E2062A1bC66a2C1d05cb5C3870a4AF86e0056E", "interchainAccountRouter": "0xBE70Ab882D1F7E37e04a70CDd9Ec23b37a234064", "interchainGasPaymaster": "0xDd260B99d302f0A3fF885728c086f729c06f227f", - "interchainSecurityModule": "0x46902BD2e22A6672eD2E8D04771cC8CB5eD06481", + "interchainSecurityModule": "0x996Be332325DA49Ea590A9772a515d62dD90C74c", "mailbox": "0xaD09d78f4c6b9dA2Ae82b1D34107802d380Bb74f", "merkleTreeHook": "0x2684C6F89E901987E1FdB7649dC5Be0c57C61645", "name": "gnosis", @@ -1183,7 +1184,7 @@ "interchainAccountIsm": "0x708E002637792FDC031E6B62f23DD60014AC976a", "interchainAccountRouter": "0xfB8cea1c7F45608Da30655b50bbF355D123A4358", "interchainGasPaymaster": "0x19dc38aeae620380430C200a6E990D5Af5480117", - "interchainSecurityModule": "0x2dcFd91eCd43adfd5644De57387575F97539C18a", + "interchainSecurityModule": "0x1Bff27a1c1319b0704348895b67426a4Eb1b629e", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0972954923a1e2b2aAb04Fa0c4a0797e5989Cd65", "name": "inevm", @@ -1303,7 +1304,7 @@ "from": 14616307 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336", + "interchainSecurityModule": "0xcaE599dD2142CD8F09a68bAC89b4d809A038d2E9", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "kroma", @@ -1375,7 +1376,7 @@ "interchainAccountIsm": "0xdcA646C56E7768DD11654956adE24bfFf9Ba4893", "interchainAccountRouter": "0xD59dA396F162Ed93a41252Cebb8d5DD4F093238C", "interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28", - "interchainSecurityModule": "0x72CC2baC9e33Eb96395FE8caC142D368fbF8Dc50", + "interchainSecurityModule": "0x916e612358dA3F7E8e19f51ba2Cf7af3285a6793", "mailbox": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9", "merkleTreeHook": "0xC077A0Cc408173349b1c9870C667B40FE3C01dd7", "name": "linea", @@ -1445,7 +1446,7 @@ "from": 4195553 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x1b9cDC236760f40064863DA3d67f5553208B65DE", + "interchainSecurityModule": "0xa660FA2047105E0341b356393218586ED2191d14", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "lisk", @@ -1508,7 +1509,7 @@ "from": 3088760 }, "interchainGasPaymaster": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", - "interchainSecurityModule": "0xc6ec1364d1ce3E963Fa65A0bDF57eC722478e1FB", + "interchainSecurityModule": "0x391BD8dD2709F77d39dab4fB3bf4BCAfd5EC3248", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x062200d92dF6bB7bA89Ce4D6800110450f94784e", "name": "lukso", @@ -1581,7 +1582,7 @@ "interchainAccountIsm": "0x8Ea50255C282F89d1A14ad3F159437EE5EF0507f", "interchainAccountRouter": "0x693A4cE39d99e46B04cb562329e3F0141cA17331", "interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4", - "interchainSecurityModule": "0x855a679627f8A283861d363E8Daaf2e6fac74230", + "interchainSecurityModule": "0xBcB96842301c659B575c40C3f93F7311D09c93d9", "isTestnet": false, "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112", @@ -1650,7 +1651,7 @@ "interchainAccountIsm": "0xe039DA3A0071BEd087A12660D7b03cf669c7776E", "interchainAccountRouter": "0x45285463352c53a481e882cD5E2AF2E25BBdAd0D", "interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28", - "interchainSecurityModule": "0xDA06C0c607CdbcED8B01d7b7caafeeDA550b4120", + "interchainSecurityModule": "0xe542Ed13B5782aF0AFAe7f232bB867FB0208Ab7B", "mailbox": "0x398633D19f4371e1DB5a8EFE90468eB70B1176AA", "merkleTreeHook": "0x5332D1AC0A626D265298c14ff681c0A8D28dB86d", "name": "mantle", @@ -1712,7 +1713,7 @@ "from": 13523607 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xD89521A871B43f1116083d79A937445D2675Be37", + "interchainSecurityModule": "0x5725a9Bf3bdaF104Ce1A0098308DD974F6395365", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "merlin", @@ -1778,7 +1779,7 @@ "from": 17966274 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x1ffca4c17aEe10a8fCAd338750191ce1C2188b6f", + "interchainSecurityModule": "0xfd810678075502F76A6ef79cedffe58cff6Cc410", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "metis", @@ -1843,7 +1844,7 @@ "from": 3752032 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x1ffca4c17aEe10a8fCAd338750191ce1C2188b6f", + "interchainSecurityModule": "0xfd810678075502F76A6ef79cedffe58cff6Cc410", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "mint", @@ -1909,7 +1910,7 @@ "interchainAccountIsm": "0xa377b8269e0A47cdd2fD5AAeAe860b45623c6d82", "interchainAccountRouter": "0x6e1B9f776bd415d7cC3C7458A5f0d801016918f8", "interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d", - "interchainSecurityModule": "0x691ca7575ff8D2415158b95f4F4D9307aD9115d5", + "interchainSecurityModule": "0x1ab6985E0e15d293e71d01510fa6B57311C69718", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6", "name": "mode", @@ -1977,7 +1978,7 @@ "interchainAccountIsm": "0x79b3730CE3685f65802aF1771319992bA960EB9D", "interchainAccountRouter": "0xc4482f66191754a8629D35289043C4EB0285F10E", "interchainGasPaymaster": "0x14760E32C0746094cF14D97124865BC7F0F7368F", - "interchainSecurityModule": "0x3E4c6E0f336657467175cFeC13fdecC78BaE253d", + "interchainSecurityModule": "0x105215D46F45a88B3793B798Fb87AF231Ad9f611", "mailbox": "0x094d03E751f49908080EFf000Dd6FD177fd44CC3", "merkleTreeHook": "0x87403b85f6f316e7ba91ba1fa6C3Fb7dD4095547", "name": "moonbeam", @@ -2117,7 +2118,7 @@ "interchainAccountIsm": "0x2c46BF14641d00549ECa4779BF5CBf91602C1DEd", "interchainAccountRouter": "0x03D6cC17d45E9EA27ED757A8214d1F07F7D901aD", "interchainGasPaymaster": "0xD8A76C4D91fCbB7Cc8eA795DFDF870E48368995C", - "interchainSecurityModule": "0x1bc5500Cc5d338e2daDBa6db936b4046030aF3A3", + "interchainSecurityModule": "0x1E491c93Ab56A298bBC34B4Fca8A4cE68E8d540a", "mailbox": "0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D", "merkleTreeHook": "0x68eE9bec9B4dbB61f69D9D293Ae26a5AACb2e28f", "name": "optimism", @@ -2250,7 +2251,7 @@ "interchainAccountIsm": "0xBAC4529cdfE7CCe9E858BF706e41F8Ed096C1BAd", "interchainAccountRouter": "0xF163949AD9F88977ebF649D0461398Ca752E64B9", "interchainGasPaymaster": "0x0071740Bf129b05C4684abfbBeD248D80971cce2", - "interchainSecurityModule": "0x017B4ee44A205B3c9576512F83c583F59da3f1f4", + "interchainSecurityModule": "0x0D408EF040ca0E7a75f03c41Aa46cAc904770D45", "mailbox": "0x5d934f4e2f797775e53561bB72aca21ba36B96BB", "merkleTreeHook": "0x73FbD25c3e817DC4B4Cd9d00eff6D83dcde2DfF6", "name": "polygon", @@ -2326,7 +2327,7 @@ "interchainAccountIsm": "0xc1198e241DAe48BF5AEDE5DCE49Fe4A6064cF7a7", "interchainAccountRouter": "0x20a0A32a110362920597F72974E1E0d7e25cA20a", "interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4", - "interchainSecurityModule": "0x6d1c7Cba7fa5cA1895EBC2045A93D53719C47Fed", + "interchainSecurityModule": "0x5C622f40365F57D06b5e7132B1483fcbc9566560", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112", "name": "polygonzkevm", @@ -2393,7 +2394,7 @@ "from": 32018468 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xA00CCe6085E4fae65EfD61cEfd080cb99B6d750f", + "interchainSecurityModule": "0x336306ADB3c510A318107c01D109D2072c7abB6B", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "proofofplay", @@ -2457,7 +2458,7 @@ "from": 363159 }, "interchainGasPaymaster": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696", - "interchainSecurityModule": "0x20c612974cBAE138e76b991C1FBA829b7E52C070", + "interchainSecurityModule": "0x06567d07b49ad922A821A641F1C962569a255dbB", "mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", "merkleTreeHook": "0x55E4F0bc6b7Bb493D50839A8592e7ad8d5e93cf7", "name": "real", @@ -2524,7 +2525,7 @@ "interchainAccountIsm": "0x5DA60220C5dDe35b7aE91c042ff5979047FA0785", "interchainAccountRouter": "0x7a4d31a686A36285d68e14EDD53631417eB19603", "interchainGasPaymaster": "0x2Fa570E83009eaEef3a1cbd496a9a30F05266634", - "interchainSecurityModule": "0xbB8D11681396d410fa00B92Bc92Fff1e61a31C3F", + "interchainSecurityModule": "0x5a3bB91853CfDaDb1bC95D2E061B50d433fbe3E8", "mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", "merkleTreeHook": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA", "name": "redstone", @@ -2585,7 +2586,7 @@ "from": 937117 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x597DB3036b5E7bE9b2216F599e1Ba92734c4cd6f", + "interchainSecurityModule": "0xA76F4620ac1e97d273B2C9Ca71805c8afD792098", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "sanko", @@ -2653,7 +2654,7 @@ "interchainAccountIsm": "0x32af5Df81fEd5E26119F6640FBB13f3d63a94CDe", "interchainAccountRouter": "0x0B48a744698ba8dFa514742dFEB6728f52fD66f7", "interchainGasPaymaster": "0xBF12ef4B9f307463D3FB59c3604F294dDCe287E2", - "interchainSecurityModule": "0xBf15bABBB938F0F734F77Eda8b583429838490E7", + "interchainSecurityModule": "0x37e17723b665A9F95F4aecEEc40D9eF39624764e", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x6119E37Bd66406A1Db74920aC79C15fB8411Ba76", "name": "scroll", @@ -2720,7 +2721,7 @@ "interchainAccountIsm": "0xf35dc7B9eE4Ebf0cd3546Bd6EE3b403dE2b9F5D6", "interchainAccountRouter": "0xBcaedE97a98573A88242B3b0CB0A255F3f90d4d5", "interchainGasPaymaster": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72", - "interchainSecurityModule": "0xf0FcAb13ACec74402fFC5006bBEb81E3C14f071f", + "interchainSecurityModule": "0x26184898fA27D3471B50BD956AB5b3E9Aa14763C", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xca1b69fA4c4a7c7fD839bC50867c589592bcfe49", "name": "sei", @@ -2796,7 +2797,8 @@ "http": "https://api.mainnet-beta.solana.com" } ], - "validatorAnnounce": "pRgs5vN4Pj7WvFbxf6QDHizo2njq2uksqEUbaSghVA8" + "validatorAnnounce": "pRgs5vN4Pj7WvFbxf6QDHizo2njq2uksqEUbaSghVA8", + "interchainSecurityModule": "372D5YP7jMYUgYBXTVJ7BZtzKv1mq1J6wvjSFLNTRreC" }, "taiko": { "aggregationHook": "0x1175A31f66C5e3d0ce0ca3B7F80Abe72c6FcE272", @@ -2831,7 +2833,7 @@ "interchainAccountIsm": "0xAE557e108b3336130370aC74836f1356B4b30Cf2", "interchainAccountRouter": "0x1F8CF09F060A2AE962c0Bb1F92e209a1E7b0E10B", "interchainGasPaymaster": "0x273Bc6b01D9E88c064b6E5e409BdF998246AEF42", - "interchainSecurityModule": "0xbCF47BFb1f863e349b588d6b0A817161541a82A6", + "interchainSecurityModule": "0x478D0e5d221C8d7CA1A6353315fac6FA88Ff1B97", "mailbox": "0x28EFBCadA00A7ed6772b3666F3898d276e88CAe3", "merkleTreeHook": "0x6A55822cf11f9fcBc4c75BC2638AfE8Eb942cAdd", "name": "taiko", @@ -2893,7 +2895,7 @@ "from": 1678063 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xA00CCe6085E4fae65EfD61cEfd080cb99B6d750f", + "interchainSecurityModule": "0x336306ADB3c510A318107c01D109D2072c7abB6B", "isTestnet": false, "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", @@ -2960,7 +2962,7 @@ "interchainAccountIsm": "0x551BbEc45FD665a8C95ca8731CbC32b7653Bc59B", "interchainAccountRouter": "0xc11f8Cf2343d3788405582F65B8af6A4F7a6FfC8", "interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4", - "interchainSecurityModule": "0x37E2EBF4DD9F6636f28Ac2a20284d2d47f93Cc3A", + "interchainSecurityModule": "0x5542503cBde841c336Afef014FE80b0F1c9d716d", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112", "name": "viction", @@ -3027,7 +3029,7 @@ "interchainAccountIsm": "0xCB9f90EE5d83Ea52ABd922BD70898f0155D54798", "interchainAccountRouter": "0x473884010F0C1742DA8Ad01E7E295624B931076b", "interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503", - "interchainSecurityModule": "0xbf8c84422e09BB9866F9E416d6f447A33e261D05", + "interchainSecurityModule": "0xc1FF2bf7a4C315bE2a06941D236457EB02F93993", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD", "name": "worldchain", @@ -3088,7 +3090,7 @@ "from": 24395308 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x18E1F88A882cE015b135Acdf356dd4F5773763B9", + "interchainSecurityModule": "0xC630ef37e03534721557026FeC397Ec05f85584C", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "xai", @@ -3156,7 +3158,7 @@ "interchainAccountIsm": "0x29B37088724B745C0ABcE591449Cf042772160C2", "interchainAccountRouter": "0x03cF708E42C89623bd83B281A56935cB562b9258", "interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503", - "interchainSecurityModule": "0x6455CbF559E2227aA23409930D0F860e2f244B70", + "interchainSecurityModule": "0x0811C6250965E7Ba1A872A12249B1b2300d85CFD", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD", "name": "xlayer", @@ -3223,7 +3225,7 @@ "interchainAccountIsm": "0x2b6d3F7d28B5EC8C3C028fBCAdcf774D9709Dd29", "interchainAccountRouter": "0x3AdCBc94ab8C48EC52D06dc65Bb787fD1981E3d5", "interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d", - "interchainSecurityModule": "0xCAc4123018406911D43e778410313A594276c96E", + "interchainSecurityModule": "0x858a077945bCC4afA40DaE5a75faB9237e899b30", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6", "name": "zetachain", @@ -3288,7 +3290,7 @@ "from": 1511458 }, "interchainGasPaymaster": "0x03cF708E42C89623bd83B281A56935cB562b9258", - "interchainSecurityModule": "0xe569C2cC7f2e41ABF1c1CFdE7BBd1694BEF5cc5D", + "interchainSecurityModule": "0xb04DE6Cbc6E258E8f2D2B00EBdcD2Ea901791EAA", "mailbox": "0xc2FbB9411186AB3b1a6AFCCA702D1a80B48b197c", "merkleTreeHook": "0x4C97D35c668EE5194a13c8DE8Afc18cce40C9F28", "name": "zircuit", @@ -3360,7 +3362,7 @@ "interchainAccountIsm": "0xb2674E213019972f937CCFc5e23BF963D915809e", "interchainAccountRouter": "0x11b76D93a9D39Eb51F54eBf5566308640cDe882b", "interchainGasPaymaster": "0x18B0688990720103dB63559a3563f7E8d0f63EDb", - "interchainSecurityModule": "0xe2089faE2D98f2CF280E8d218E5a36966ee04d39", + "interchainSecurityModule": "0xDede6e50E548460FB6a939320F707214CFfC701C", "mailbox": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "merkleTreeHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", "name": "zoramainnet", @@ -3430,7 +3432,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x78A31fF00D79158c22C09DC6D7Fa7188e21925E4", + "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3496,7 +3498,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x71c9bB4297518034f89cDb243fBfd37d549bEbAa", + "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3565,7 +3567,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x78A31fF00D79158c22C09DC6D7Fa7188e21925E4", + "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3640,7 +3642,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x78A31fF00D79158c22C09DC6D7Fa7188e21925E4", + "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3703,7 +3705,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x78A31fF00D79158c22C09DC6D7Fa7188e21925E4", + "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3775,7 +3777,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x78A31fF00D79158c22C09DC6D7Fa7188e21925E4", + "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3842,7 +3844,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x78A31fF00D79158c22C09DC6D7Fa7188e21925E4", + "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3905,7 +3907,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x78A31fF00D79158c22C09DC6D7Fa7188e21925E4", + "interchainSecurityModule": "0x12C8cfA5B97Df96AaB2795a4186675dA49938968", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3974,7 +3976,7 @@ "interchainAccountIsm": "0xcd9D3744512F07AE844c40E27912092d7c503565", "interchainAccountRouter": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8", "interchainGasPaymaster": "0xb58257cc81E47EC72fD38aE16297048de23163b4", - "interchainSecurityModule": "0x47F57D08d01544Ed082152B73807A9D39305Fac6", + "interchainSecurityModule": "0xD5a72d4EF4D7db52C12802d0e3fBEF47b268e0dB", "mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", "merkleTreeHook": "0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1", "pausableHook": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", @@ -4034,7 +4036,7 @@ "interchainAccountIsm": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319", "interchainAccountRouter": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE", "interchainGasPaymaster": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86", - "interchainSecurityModule": "0xdc2da0D5d7A69fa86366235E426ff4a0E214cC60", + "interchainSecurityModule": "0x9E59d69F8e23dc159761Ca713C61a081422d1d47", "mailbox": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", "merkleTreeHook": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", "pausableHook": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2", diff --git a/typescript/cli/package.json b/typescript/cli/package.json index 6725dddd1..b44e7fb50 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -5,7 +5,7 @@ "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", - "@hyperlane-xyz/registry": "4.0.0", + "@hyperlane-xyz/registry": "4.1.0", "@hyperlane-xyz/sdk": "5.1.0", "@hyperlane-xyz/utils": "5.1.0", "@inquirer/prompts": "^3.0.0", diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index 34aba2ec9..b3fc92a52 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -4,7 +4,7 @@ "version": "5.1.0", "dependencies": { "@hyperlane-xyz/core": "5.1.0", - "@hyperlane-xyz/registry": "4.0.0", + "@hyperlane-xyz/registry": "4.1.0", "@hyperlane-xyz/sdk": "5.1.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 042437b60..3542719f7 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -4,7 +4,7 @@ "decimals": 9 }, "arbitrum": { - "amount": "0.5", + "amount": "0.1", "decimals": 9 }, "astar": { @@ -12,7 +12,7 @@ "decimals": 9 }, "astarzkevm": { - "amount": "0.0097", + "amount": "0.0562", "decimals": 9 }, "avalanche": { @@ -20,7 +20,7 @@ "decimals": 9 }, "base": { - "amount": "0.013311447", + "amount": "0.013571998", "decimals": 9 }, "bitlayer": { @@ -72,7 +72,7 @@ "decimals": 9 }, "ethereum": { - "amount": "6.654595701", + "amount": "10", "decimals": 9 }, "everclear": { @@ -120,7 +120,7 @@ "decimals": 9 }, "mantapacific": { - "amount": "0.113932514", + "amount": "0.011", "decimals": 9 }, "mantle": { @@ -140,7 +140,7 @@ "decimals": 9 }, "mode": { - "amount": "0.1", + "amount": "0.01", "decimals": 9 }, "molten": { @@ -168,7 +168,7 @@ "decimals": 1 }, "polygon": { - "amount": "101.76455238", + "amount": "219.572738168", "decimals": 9 }, "polygonzkevm": { diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index 121d89832..0abb12d06 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -1,63 +1,63 @@ { - "ancient8": "2342.46", - "arbitrum": "2342.46", - "astar": "0.054438", - "astarzkevm": "2342.46", - "avalanche": "23.83", - "base": "2342.46", - "bitlayer": "56880", - "blast": "2342.46", - "bob": "2342.46", - "bsc": "519.43", - "celo": "0.444294", - "cheesechain": "0.00249894", - "coredao": "0.942068", - "cyber": "2342.46", - "degenchain": "0.00324668", - "dogechain": "0.102724", - "eclipsemainnet": "2342.46", - "endurance": "2.14", - "ethereum": "2342.46", - "everclear": "2342.46", - "flare": "0.01473859", - "fraxtal": "2335.15", - "fusemainnet": "0.02525184", - "gnosis": "0.990366", - "inevm": "17.79", - "injective": "17.79", - "kroma": "2342.46", - "linea": "2342.46", - "lisk": "2342.46", - "lukso": "2.1", - "mantapacific": "2342.46", - "mantle": "0.563082", - "merlin": "56884", - "metis": "29.99", - "mint": "2342.46", - "mode": "2342.46", - "molten": "0.663236", - "moonbeam": "0.159678", - "neutron": "0.359547", - "oortmainnet": "0.089435", - "optimism": "2342.46", - "osmosis": "0.39708", - "polygon": "0.384058", - "polygonzkevm": "2342.46", - "proofofplay": "2342.46", - "real": "2342.46", - "redstone": "2342.46", - "sanko": "39.51", - "scroll": "2342.46", - "sei": "0.290644", - "shibarium": "0.398366", - "solanamainnet": "133.81", - "taiko": "2342.46", - "tangle": "0.999864", - "viction": "0.438134", - "worldchain": "2342.46", - "xai": "0.183944", - "xlayer": "37.86", - "zetachain": "0.465693", - "zircuit": "2342.46", - "zoramainnet": "2342.46" + "ancient8": "2411.78", + "arbitrum": "2411.78", + "astar": "0.058925", + "astarzkevm": "2411.78", + "avalanche": "24.66", + "base": "2411.78", + "bitlayer": "59677", + "blast": "2411.78", + "bob": "2411.78", + "bsc": "552.99", + "celo": "0.444888", + "cheesechain": "0.00192649", + "coredao": "0.936135", + "cyber": "2411.78", + "degenchain": "0.00324113", + "dogechain": "0.107549", + "eclipsemainnet": "2411.78", + "endurance": "2.28", + "ethereum": "2411.78", + "everclear": "2411.78", + "flare": "0.01486694", + "fraxtal": "2389.6", + "fusemainnet": "0.0254922", + "gnosis": "1.011", + "inevm": "19.13", + "injective": "19.13", + "kroma": "2411.78", + "linea": "2411.78", + "lisk": "2411.78", + "lukso": "2.11", + "mantapacific": "2411.78", + "mantle": "0.571121", + "merlin": "59786", + "metis": "31.92", + "mint": "2411.78", + "mode": "2411.78", + "molten": "0.671515", + "moonbeam": "0.170166", + "neutron": "0.368584", + "oortmainnet": "0.091528", + "optimism": "2411.78", + "osmosis": "0.412102", + "polygon": "0.426289", + "polygonzkevm": "2411.78", + "proofofplay": "2411.78", + "real": "2411.78", + "redstone": "2411.78", + "sanko": "34.23", + "scroll": "2411.78", + "sei": "0.304985", + "shibarium": "0.407481", + "solanamainnet": "137.07", + "taiko": "2411.78", + "tangle": "1.001", + "viction": "0.437209", + "worldchain": "2411.78", + "xai": "0.190543", + "xlayer": "40.24", + "zetachain": "0.489689", + "zircuit": "2411.78", + "zoramainnet": "2411.78" } diff --git a/typescript/infra/package.json b/typescript/infra/package.json index bda53492c..174906ae1 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -14,7 +14,7 @@ "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", "@hyperlane-xyz/helloworld": "5.1.0", - "@hyperlane-xyz/registry": "4.0.0", + "@hyperlane-xyz/registry": "4.1.0", "@hyperlane-xyz/sdk": "5.1.0", "@hyperlane-xyz/utils": "5.1.0", "@inquirer/prompts": "^5.3.8", diff --git a/typescript/infra/scripts/agents/update-agent-config.ts b/typescript/infra/scripts/agents/update-agent-config.ts index 551be6cda..4584348cf 100644 --- a/typescript/infra/scripts/agents/update-agent-config.ts +++ b/typescript/infra/scripts/agents/update-agent-config.ts @@ -2,12 +2,19 @@ import { ChainAddresses } from '@hyperlane-xyz/registry'; import { ChainMap, ChainTechnicalStack, + CoreFactories, + HyperlaneContracts, HyperlaneCore, HyperlaneDeploymentArtifacts, MultiProvider, buildAgentConfig, } from '@hyperlane-xyz/sdk'; -import { ProtocolType, objMap, promiseObjAll } from '@hyperlane-xyz/utils'; +import { + ProtocolType, + objFilter, + objMap, + promiseObjAll, +} from '@hyperlane-xyz/utils'; import { Contexts } from '../../config/contexts.js'; import { @@ -18,6 +25,7 @@ import { getCosmosChainGasPrice } from '../../src/config/gas-oracle.js'; import { chainIsProtocol, filterRemoteDomainMetadata, + isEthereumProtocolChain, writeMergedJSONAtPath, } from '../../src/utils/utils.js'; import { @@ -50,41 +58,53 @@ export async function writeAgentConfig( const addressesForEnv = filterRemoteDomainMetadata(addressesMap); const core = HyperlaneCore.fromAddressesMap(addressesForEnv, multiProvider); + const evmContractsMap = objFilter( + core.contractsMap, + (chain, _): _ is HyperlaneContracts => + isEthereumProtocolChain(chain), + ); + // Write agent config indexing from the deployed Mailbox which stores the block number at deployment const startBlocks = await promiseObjAll( - objMap(addressesForEnv, async (chain: string, _) => { - const { index, technicalStack } = multiProvider.getChainMetadata(chain); - const indexFrom = index?.from; + objMap( + evmContractsMap, + async (chain: string, contracts: HyperlaneContracts) => { + const { index, technicalStack } = multiProvider.getChainMetadata(chain); + const indexFrom = index?.from; - // Arbitrum Nitro chains record the L1 block number they were deployed at, - // not the L2 block number. - // See: https://docs.arbitrum.io/build-decentralized-apps/arbitrum-vs-ethereum/block-numbers-and-time#ethereum-block-numbers-within-arbitrum - if (technicalStack === ChainTechnicalStack.ArbitrumNitro && !indexFrom) { - // Should never get here because registry should enforce this, but we're being defensive. - throw new Error( - `index.from is not set for Arbitrum Nitro chain ${chain}`, - ); - } + // Arbitrum Nitro chains record the L1 block number they were deployed at, + // not the L2 block number. + // See: https://docs.arbitrum.io/build-decentralized-apps/arbitrum-vs-ethereum/block-numbers-and-time#ethereum-block-numbers-within-arbitrum + if ( + technicalStack === ChainTechnicalStack.ArbitrumNitro && + !indexFrom + ) { + // Should never get here because registry should enforce this, but we're being defensive. + throw new Error( + `index.from is not set for Arbitrum Nitro chain ${chain}`, + ); + } - // If the index.from is specified in the chain metadata, use that. - if (indexFrom) { - return indexFrom; - } + // If the index.from is specified in the chain metadata, use that. + if (indexFrom) { + return indexFrom; + } - const mailbox = core.getContracts(chain).mailbox; - try { - const deployedBlock = await mailbox.deployedBlock(); - return deployedBlock.toNumber(); - } catch (err) { - console.error( - 'Failed to get deployed block, defaulting to 0. Chain:', - chain, - 'Error:', - err, - ); - return 0; - } - }), + const mailbox = contracts.mailbox; + try { + const deployedBlock = await mailbox.deployedBlock(); + return deployedBlock.toNumber(); + } catch (err) { + console.error( + 'Failed to get deployed block, defaulting to 0. Chain:', + chain, + 'Error:', + err, + ); + return 0; + } + }, + ), ); // Get gas prices for Cosmos chains. diff --git a/typescript/infra/scripts/check-owner-ica.ts b/typescript/infra/scripts/check-owner-ica.ts new file mode 100644 index 000000000..1866eeb10 --- /dev/null +++ b/typescript/infra/scripts/check-owner-ica.ts @@ -0,0 +1,64 @@ +import { AccountConfig, InterchainAccount } from '@hyperlane-xyz/sdk'; +import { Address, eqAddress } from '@hyperlane-xyz/utils'; + +import { icas } from '../config/environments/mainnet3/owners.js'; + +import { getArgs as getEnvArgs } from './agent-utils.js'; +import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js'; + +function getArgs() { + return getEnvArgs().option('ownerChain', { + type: 'string', + description: 'Origin chain where the Safe owner lives', + default: 'ethereum', + }).argv; +} + +async function main() { + const { environment, ownerChain } = await getArgs(); + const config = getEnvironmentConfig(environment); + const multiProvider = await config.getMultiProvider(); + + const owner = config.owners[ownerChain].ownerOverrides?._safeAddress; + if (!owner) { + console.error(`No Safe owner found for ${ownerChain}`); + process.exit(1); + } + + console.log(`Safe owner on ${ownerChain}: ${owner}`); + + const { chainAddresses } = await getHyperlaneCore(environment, multiProvider); + const ica = InterchainAccount.fromAddressesMap(chainAddresses, multiProvider); + + const ownerConfig: AccountConfig = { + origin: ownerChain, + owner: owner, + }; + + const mismatchedResults: Record< + string, + { Expected: Address; Actual: Address } + > = {}; + for (const [chain, expectedAddress] of Object.entries(icas)) { + const actualAccount = await ica.getAccount(chain, ownerConfig); + if (!eqAddress(expectedAddress, actualAccount)) { + mismatchedResults[chain] = { + Expected: expectedAddress, + Actual: actualAccount, + }; + } + } + + if (Object.keys(mismatchedResults).length > 0) { + console.error('\nMismatched ICAs found:'); + console.table(mismatchedResults); + process.exit(1); + } else { + console.log('✅ All ICAs match the expected addresses.'); + } +} + +main().catch((err) => { + console.error('Error:', err); + process.exit(1); +}); diff --git a/typescript/infra/scripts/print-balances.ts b/typescript/infra/scripts/print-balances.ts index f46ca4634..b528be05d 100644 --- a/typescript/infra/scripts/print-balances.ts +++ b/typescript/infra/scripts/print-balances.ts @@ -39,42 +39,68 @@ async function main() { const balancesObject = await Promise.all( chainsToCheck.map(async (chain) => { - const provider = multiProvider.getProvider(chain); - const { decimals, symbol } = await multiProvider.getNativeToken(chain); - const roleBalances = await Promise.all( - roles.map(async (role) => { - // Fetch key - const keys = await envConfig.getKeys(context, role as Role); - await Promise.all(Object.values(keys).map((key) => key.fetch())); + try { + const provider = multiProvider.getProvider(chain); + const { decimals, symbol } = await multiProvider.getNativeToken(chain); + const roleBalances = await Promise.all( + roles.map(async (role) => { + try { + let address: string | undefined; - // Default to known deployer/relayer addresses if not found - let address = keys[chain]?.address; - if (!address) { - if (role === Role.Deployer) { - address = - environment === 'mainnet3' ? MainnetDeployer : TestnetDeployer; - } else if (role === Role.Relayer) { - address = - environment === 'mainnet3' ? MainnetRelayer : TestnetRelayer; - } - } + if ( + role === Role.Deployer && + (environment === 'mainnet3' || environment === 'testnet4') + ) { + address = + environment === 'mainnet3' + ? MainnetDeployer + : TestnetDeployer; + } else if ( + role === Role.Relayer && + (environment === 'mainnet3' || environment === 'testnet4') + ) { + address = + environment === 'mainnet3' ? MainnetRelayer : TestnetRelayer; + } else { + // Fetch key only if role is not deployer/relayer or env is not mainnet/testnet + const keys = await envConfig.getKeys(context, role as Role); + await Promise.all( + Object.values(keys).map((key) => key.fetch()), + ); + address = keys[chain]?.address; + } - // Fetch balance - if (address) { - const balance = await provider.getBalance(address); - const formattedBalance = formatUnits(balance, decimals); - return Number(formattedBalance).toFixed(3); - } - return null; - }), - ); - return { - chain, - symbol, - ...Object.fromEntries( - roles.map((role, index) => [role, roleBalances[index]]), - ), - }; + // Fetch balance + if (address) { + const balance = await provider.getBalance(address); + const formattedBalance = formatUnits(balance, decimals); + return Number(formattedBalance).toFixed(3); + } + return null; + } catch (error) { + console.error( + `Error fetching balance for ${role} on ${chain}:`, + error, + ); + return null; + } + }), + ); + return { + chain, + symbol, + ...Object.fromEntries( + roles.map((role, index) => [role, roleBalances[index]]), + ), + }; + } catch (error) { + console.error(`Error processing chain ${chain}:`, error); + return { + chain, + symbol: 'ERROR', + ...Object.fromEntries(roles.map((role) => [role, null])), + }; + } }), ); diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index f901e9c67..d91465d24 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -99,52 +99,56 @@ export abstract class HyperlaneAppGovernor< } protected async sendCalls(chain: ChainName, requestConfirmation: boolean) { - const calls = this.calls[chain]; + const calls = this.calls[chain] || []; console.log(`\nFound ${calls.length} transactions for ${chain}`); const filterCalls = (submissionType: SubmissionType) => calls.filter((call) => call.submissionType == submissionType); const summarizeCalls = async ( submissionType: SubmissionType, - calls: AnnotatedCallData[], + callsForSubmissionType: AnnotatedCallData[], ): Promise => { - if (calls.length > 0) { - console.log( - `> ${calls.length} calls will be submitted via ${SubmissionType[submissionType]}`, - ); - calls.map((c) => { - console.log(`> > ${c.description}`); - console.log(`> > > to: ${c.to}`); - console.log(`> > > data: ${c.data}`); - console.log(`> > > value: ${c.value}`); - }); - if (!requestConfirmation) return true; + if (!callsForSubmissionType || callsForSubmissionType.length === 0) { + return false; + } - const { value: confirmed } = await prompts({ - type: 'confirm', - name: 'value', - message: 'Can you confirm?', - initial: false, - }); + console.log( + `> ${callsForSubmissionType.length} calls will be submitted via ${SubmissionType[submissionType]}`, + ); + callsForSubmissionType.map((c) => { + console.log(`> > ${c.description.trim()}`); + console.log(`> > > to: ${c.to}`); + console.log(`> > > data: ${c.data}`); + console.log(`> > > value: ${c.value}`); + }); + if (!requestConfirmation) return true; - return !!confirmed; - } - return false; + const { value: confirmed } = await prompts({ + type: 'confirm', + name: 'value', + message: 'Can you confirm?', + initial: false, + }); + + return !!confirmed; }; const sendCallsForType = async ( submissionType: SubmissionType, multiSend: MultiSend, ) => { - const calls = filterCalls(submissionType); - if (calls.length > 0) { - const confirmed = await summarizeCalls(submissionType, calls); + const callsForSubmissionType = filterCalls(submissionType) || []; + if (callsForSubmissionType.length > 0) { + const confirmed = await summarizeCalls( + submissionType, + callsForSubmissionType, + ); if (confirmed) { console.log( `Submitting calls on ${chain} via ${SubmissionType[submissionType]}`, ); try { await multiSend.sendTransactions( - calls.map((call) => ({ + callsForSubmissionType.map((call) => ({ to: call.to, data: call.data, value: call.value, @@ -411,8 +415,13 @@ export abstract class HyperlaneAppGovernor< }; } else { console.error( - `Failed to determine if signer can propose safe transactions: ${error}`, + `Failed to determine if signer can propose safe transactions on ${chain}. Setting submission type to MANUAL. Error: ${error}`, ); + return { + type: SubmissionType.MANUAL, + chain, + call, + }; } } } diff --git a/typescript/sdk/src/core/HyperlaneCore.ts b/typescript/sdk/src/core/HyperlaneCore.ts index 16391b2a8..4dc133bc8 100644 --- a/typescript/sdk/src/core/HyperlaneCore.ts +++ b/typescript/sdk/src/core/HyperlaneCore.ts @@ -25,7 +25,10 @@ import { import { HyperlaneApp } from '../app/HyperlaneApp.js'; import { appFromAddressesMapHelper } from '../contracts/contracts.js'; -import { HyperlaneAddressesMap } from '../contracts/types.js'; +import { + HyperlaneAddressesMap, + HyperlaneContracts, +} from '../contracts/types.js'; import { OwnableConfig } from '../deploy/types.js'; import { DerivedHookConfig, EvmHookReader } from '../hook/EvmHookReader.js'; import { DerivedIsmConfig, EvmIsmReader } from '../ism/EvmIsmReader.js'; @@ -54,9 +57,16 @@ export class HyperlaneCore extends HyperlaneApp { getRouterConfig = ( owners: Address | ChainMap, ): ChainMap => { + // filter for EVM chains + const evmContractsMap = objFilter( + this.contractsMap, + (chainName, _): _ is HyperlaneContracts => + this.multiProvider.getProtocol(chainName) === ProtocolType.Ethereum, + ); + // get config const config = objMap( - this.contractsMap, + evmContractsMap, (chain, contracts): RouterConfig => ({ mailbox: contracts.mailbox.address, owner: typeof owners === 'string' ? owners : owners[chain].owner, @@ -64,12 +74,8 @@ export class HyperlaneCore extends HyperlaneApp { typeof owners === 'string' ? undefined : owners[chain].ownerOverrides, }), ); - // filter for EVM chains - return objFilter( - config, - (chainName, _): _ is RouterConfig => - this.multiProvider.getProtocol(chainName) === ProtocolType.Ethereum, - ); + + return config; }; quoteGasPayment = ( diff --git a/typescript/sdk/src/core/HyperlaneCoreChecker.ts b/typescript/sdk/src/core/HyperlaneCoreChecker.ts index 5fc7f014d..cb7bb9046 100644 --- a/typescript/sdk/src/core/HyperlaneCoreChecker.ts +++ b/typescript/sdk/src/core/HyperlaneCoreChecker.ts @@ -1,6 +1,6 @@ import { ethers, utils as ethersUtils } from 'ethers'; -import { assert, eqAddress } from '@hyperlane-xyz/utils'; +import { assert, eqAddress, rootLogger } from '@hyperlane-xyz/utils'; import { BytecodeHash } from '../consts/bytecode.js'; import { HyperlaneAppChecker } from '../deploy/HyperlaneAppChecker.js'; @@ -36,6 +36,12 @@ export class HyperlaneCoreChecker extends HyperlaneAppChecker< async checkChain(chain: ChainName): Promise { const config = this.configMap[chain]; + + if (!config) { + rootLogger.warn(`No config for chain ${chain}`); + return; + } + // skip chains that are configured to be removed if (config.remove) { return; diff --git a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts index 753e2c0ea..63672be18 100644 --- a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts +++ b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts @@ -35,30 +35,24 @@ export abstract class HyperlaneAppChecker< App extends HyperlaneApp, Config, > { - readonly multiProvider: MultiProvider; - readonly app: App; - readonly configMap: ChainMap; - readonly violations: CheckerViolation[]; + readonly violations: CheckerViolation[] = []; constructor( - multiProvider: MultiProvider, - app: App, - configMap: ChainMap, - ) { - this.multiProvider = multiProvider; - this.app = app; - this.violations = []; - this.configMap = configMap; - } + readonly multiProvider: MultiProvider, + readonly app: App, + readonly configMap: ChainMap, + ) {} abstract checkChain(chain: ChainName): Promise; async check(): Promise { + const appChains = this.app.chains(); + Object.keys(this.configMap) .filter( (chain) => this.multiProvider.getChainMetadata(chain).protocol === - ProtocolType.Ethereum && !this.app.chains().includes(chain), + ProtocolType.Ethereum && !appChains.includes(chain), ) .forEach((chain: string) => this.addViolation({ @@ -70,8 +64,13 @@ export abstract class HyperlaneAppChecker< ); return Promise.all( - // this.app.chains() will only return Ethereum chains that can be interacted with. - this.app.chains().map((chain) => this.checkChain(chain)), + appChains + .filter( + (chain) => + this.multiProvider.getChainMetadata(chain).protocol === + ProtocolType.Ethereum, + ) + .map((chain) => this.checkChain(chain)), ); } diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index dfcacb8b9..373917e0e 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -7,7 +7,7 @@ "react-dom": "^18" }, "dependencies": { - "@hyperlane-xyz/registry": "4.0.0", + "@hyperlane-xyz/registry": "4.1.0", "@hyperlane-xyz/sdk": "5.1.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 8adeeb70f..31d1ea72a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7590,7 +7590,7 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.577.0" "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" - "@hyperlane-xyz/registry": "npm:4.0.0" + "@hyperlane-xyz/registry": "npm:4.1.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@hyperlane-xyz/utils": "npm:5.1.0" "@inquirer/prompts": "npm:^3.0.0" @@ -7683,7 +7683,7 @@ __metadata: resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: "@hyperlane-xyz/core": "npm:5.1.0" - "@hyperlane-xyz/registry": "npm:4.0.0" + "@hyperlane-xyz/registry": "npm:4.1.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" @@ -7732,7 +7732,7 @@ __metadata: "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" "@hyperlane-xyz/helloworld": "npm:5.1.0" - "@hyperlane-xyz/registry": "npm:4.0.0" + "@hyperlane-xyz/registry": "npm:4.1.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@hyperlane-xyz/utils": "npm:5.1.0" "@inquirer/prompts": "npm:^5.3.8" @@ -7790,13 +7790,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/registry@npm:4.0.0": - version: 4.0.0 - resolution: "@hyperlane-xyz/registry@npm:4.0.0" +"@hyperlane-xyz/registry@npm:4.1.0": + version: 4.1.0 + resolution: "@hyperlane-xyz/registry@npm:4.1.0" dependencies: yaml: "npm:2.4.5" zod: "npm:^3.21.2" - checksum: 90dfe259343fa68315ea58a58e60d47261a6af33fab63f1d0708e2c19ff057977a878b1e0079811388634e08ddf40fd4f99d03ea519cb8ad96d2ce1063ebdff5 + checksum: 5de3ef5539abfaadbfefb82e6e69fdb2413f404d8321456c91810fb50a5a70e9f93b38789495efce6ab5963682536e95a2abe636c7d0ad91ee158cc0ce6b063a languageName: node linkType: hard @@ -7874,7 +7874,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: - "@hyperlane-xyz/registry": "npm:4.0.0" + "@hyperlane-xyz/registry": "npm:4.1.0" "@hyperlane-xyz/sdk": "npm:5.1.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" From 78d6fcf5aaef8c3c1f64fe9e5e919f837b53c20b Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Mon, 16 Sep 2024 14:09:49 +0100 Subject: [PATCH 027/224] fix: cap agent EVM tx limit to the latest block gas limit (#4489) ### Description - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4239 - I think ideally we'd maybe cache this, but there isn't a super accessible way of doing this atm and we need this ASAP to accommodate Everclear. So personally am happy to take on the extra RPC per transaction and at some point we'll likely want to revisit our tx submission efficiency, plus we end up needing the latest block for eip 1559 estimation anyways ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../src/contracts/mailbox.rs | 80 +++++++++++++++++-- rust/main/chains/hyperlane-ethereum/src/tx.rs | 32 ++++++-- 2 files changed, 96 insertions(+), 16 deletions(-) diff --git a/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs index 406673b51..72d01e4d6 100644 --- a/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs @@ -619,8 +619,12 @@ mod test { /// An amount of gas to add to the estimated gas const GAS_ESTIMATE_BUFFER: u32 = 75_000; - #[tokio::test] - async fn test_process_estimate_costs_sets_l2_gas_limit_for_arbitrum() { + fn get_test_mailbox( + domain: HyperlaneDomain, + ) -> ( + EthereumMailbox>>, + Arc, + ) { let mock_provider = Arc::new(MockProvider::new()); let provider = Arc::new(Provider::new(mock_provider.clone())); let connection_conf = ConnectionConf { @@ -635,12 +639,19 @@ mod test { provider.clone(), &connection_conf, &ContractLocator { - // An Arbitrum Nitro chain - domain: &HyperlaneDomain::Known(KnownHyperlaneDomain::PlumeTestnet), + domain: &domain, // Address doesn't matter because we're using a MockProvider address: H256::default(), }, ); + (mailbox, mock_provider) + } + + #[tokio::test] + async fn test_process_estimate_costs_sets_l2_gas_limit_for_arbitrum() { + // An Arbitrum Nitro chain + let (mailbox, mock_provider) = + get_test_mailbox(HyperlaneDomain::Known(KnownHyperlaneDomain::PlumeTestnet)); let message = HyperlaneMessage::default(); let metadata: Vec = vec![]; @@ -662,12 +673,17 @@ mod test { EthersU256::from(ethers::utils::parse_units("15", "gwei").unwrap()).into(); mock_provider.push(gas_price).unwrap(); - // RPC 3: eth_estimateGas to the ArbitrumNodeInterface's estimateRetryableTicket function by process_estimate_costs + // RPC 4: eth_estimateGas to the ArbitrumNodeInterface's estimateRetryableTicket function by process_estimate_costs let l2_gas_limit = U256::from(200000); // 200k gas mock_provider.push(l2_gas_limit).unwrap(); - // RPC 2: eth_getBlockByNumber from the estimate_eip1559_fees call in process_contract_call - mock_provider.push(Block::::default()).unwrap(); + let latest_block: Block = Block { + gas_limit: ethers::types::U256::MAX, + ..Block::::default() + }; + // RPC 3: eth_getBlockByNumber from the fill_tx_gas_params call in process_contract_call + // to get the latest block gas limit and for eip 1559 fee estimation + mock_provider.push(latest_block).unwrap(); // RPC 1: eth_estimateGas from the estimate_gas call in process_contract_call // Return 1M gas @@ -679,7 +695,7 @@ mod test { .await .unwrap(); - // The TxCostEstimat's gas limit includes the buffer + // The TxCostEstimate's gas limit includes the buffer let estimated_gas_limit = gas_limit.saturating_add(GAS_ESTIMATE_BUFFER.into()); assert_eq!( @@ -691,4 +707,52 @@ mod test { }, ); } + + #[tokio::test] + async fn test_tx_gas_limit_caps_at_block_gas_limit() { + let (mailbox, mock_provider) = + get_test_mailbox(HyperlaneDomain::Known(KnownHyperlaneDomain::Ethereum)); + + let message = HyperlaneMessage::default(); + let metadata: Vec = vec![]; + + // The MockProvider responses we push are processed in LIFO + // order, so we start with the final RPCs and work toward the first + // RPCs + + // RPC 4: eth_gasPrice by process_estimate_costs + // Return 15 gwei + let gas_price: U256 = + EthersU256::from(ethers::utils::parse_units("15", "gwei").unwrap()).into(); + mock_provider.push(gas_price).unwrap(); + + let latest_block_gas_limit = U256::from(12345u32); + let latest_block: Block = Block { + gas_limit: latest_block_gas_limit.into(), + ..Block::::default() + }; + // RPC 3: eth_getBlockByNumber from the fill_tx_gas_params call in process_contract_call + // to get the latest block gas limit and for eip 1559 fee estimation + mock_provider.push(latest_block).unwrap(); + + // RPC 1: eth_estimateGas from the estimate_gas call in process_contract_call + // Return 1M gas + let gas_limit = U256::from(1000000u32); + mock_provider.push(gas_limit).unwrap(); + + let tx_cost_estimate = mailbox + .process_estimate_costs(&message, &metadata) + .await + .unwrap(); + + assert_eq!( + tx_cost_estimate, + TxCostEstimate { + // The block gas limit is the cap + gas_limit: latest_block_gas_limit, + gas_price: gas_price.try_into().unwrap(), + l2_gas_limit: None, + }, + ); + } } diff --git a/rust/main/chains/hyperlane-ethereum/src/tx.rs b/rust/main/chains/hyperlane-ethereum/src/tx.rs index 290260711..eb42f66d4 100644 --- a/rust/main/chains/hyperlane-ethereum/src/tx.rs +++ b/rust/main/chains/hyperlane-ethereum/src/tx.rs @@ -6,7 +6,7 @@ use ethers::{ abi::Detokenize, prelude::{NameOrAddress, TransactionReceipt}, providers::{JsonRpcClient, PendingTransaction, ProviderError}, - types::Eip1559TransactionRequest, + types::{Block, Eip1559TransactionRequest, TxHash}, }; use ethers_contract::builders::ContractCall; use ethers_core::{ @@ -17,7 +17,7 @@ use ethers_core::{ }, }; use hyperlane_core::{utils::bytes_to_hex, ChainCommunicationError, ChainResult, H256, U256}; -use tracing::{debug, error, info}; +use tracing::{debug, error, info, warn}; use crate::{Middleware, TransactionOverrides}; @@ -107,6 +107,24 @@ where } else { estimated_gas_limit }; + + // Cap the gas limit to the block gas limit + let latest_block = provider + .get_block(BlockNumber::Latest) + .await + .map_err(ChainCommunicationError::from_other)? + .ok_or_else(|| ProviderError::CustomError("Latest block not found".into()))?; + let block_gas_limit: U256 = latest_block.gas_limit.into(); + let gas_limit = if gas_limit > block_gas_limit { + warn!( + ?gas_limit, + ?block_gas_limit, + "Gas limit for transaction is higher than the block gas limit. Capping it to the block gas limit." + ); + block_gas_limit + } else { + gas_limit + }; debug!(?estimated_gas_limit, gas_override=?transaction_overrides.gas_limit, used_gas_limit=?gas_limit, "Gas limit set for transaction"); if let Some(gas_price) = transaction_overrides.gas_price { @@ -114,7 +132,8 @@ where return Ok(tx.gas_price(gas_price).gas(gas_limit)); } - let Ok((base_fee, max_fee, max_priority_fee)) = estimate_eip1559_fees(provider, None).await + let Ok((base_fee, max_fee, max_priority_fee)) = + estimate_eip1559_fees(provider, None, &latest_block).await else { // Is not EIP 1559 chain return Ok(tx.gas(gas_limit)); @@ -169,15 +188,12 @@ type FeeEstimator = fn(EthersU256, Vec>) -> (EthersU256, EthersU async fn estimate_eip1559_fees( provider: Arc, estimator: Option, + latest_block: &Block, ) -> ChainResult<(EthersU256, EthersU256, EthersU256)> where M: Middleware + 'static, { - let base_fee_per_gas = provider - .get_block(BlockNumber::Latest) - .await - .map_err(ChainCommunicationError::from_other)? - .ok_or_else(|| ProviderError::CustomError("Latest block not found".into()))? + let base_fee_per_gas = latest_block .base_fee_per_gas .ok_or_else(|| ProviderError::CustomError("EIP-1559 not activated".into()))?; From 57b07354728849bd72fe143f5756f22721412c1c Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Mon, 16 Sep 2024 14:39:42 +0100 Subject: [PATCH 028/224] feat: support multiple validator sets for a single app context in the relayer's observed validator metrics (#4495) ### Description - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4030 - The general idea of this change is that if the function `set_validator_latest_checkpoints` is called multiple times in a single message's metadata building, the reset of metrics relating to previously set validators now won't always occur. Atm, if two different multisig ISM validator sets are aggregated, they race each other to update the metric. With this change I expect the contention here to not occur anymore, and to still be able to handle changes in validator sets - This is a bit of a quick fix rather than something super robust tbh - I think in a vacuum I'd prefer something not dependent on time but instead dependent on a context of what message is being processed or something. But at the moment we're seeing very noisy alerts because of this issue, so would like to fix it ASAP. ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/main/hyperlane-base/src/metrics/core.rs | 36 +++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/rust/main/hyperlane-base/src/metrics/core.rs b/rust/main/hyperlane-base/src/metrics/core.rs index bc28ecca9..5603ece22 100644 --- a/rust/main/hyperlane-base/src/metrics/core.rs +++ b/rust/main/hyperlane-base/src/metrics/core.rs @@ -1,6 +1,7 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::fmt::{Debug, Formatter}; use std::sync::OnceLock; +use std::time; use eyre::Result; use hyperlane_core::{HyperlaneDomain, H160}; @@ -458,11 +459,19 @@ struct AppContextKey { app_context: String, } +/// If this period has elapsed since a validator was last updated in the metrics, +/// it will be removed from the metrics. +const MIN_VALIDATOR_METRIC_RESET_PERIOD: time::Duration = time::Duration::from_secs(60 * 3); + /// Manages metrics for observing sets of validators. pub struct ValidatorObservabilityMetricManager { observed_validator_latest_index: IntGaugeVec, - app_context_validators: RwLock>>, + // AppContextKey -> Validator -> Last updated at + // Used to track the last time a validator was updated in the metrics, allowing + // for the removal of validators that have not been updated in a while to support + // changing validator sets. + app_context_validators: RwLock>>, } impl ValidatorObservabilityMetricManager { @@ -490,10 +499,23 @@ impl ValidatorObservabilityMetricManager { let mut app_context_validators = self.app_context_validators.write().await; - // First, clear out all previous metrics for the app context. + let mut new_set = HashMap::new(); + + // First, attempt to clear out all previous metrics for the app context. // This is necessary because the set of validators may have changed. if let Some(prev_validators) = app_context_validators.get(&key) { - for validator in prev_validators { + // If the validator was last updated in the metrics more than + // a certain period ago, remove it from the metrics. + // Some leniency is given here to allow this function to be called + // multiple times in a short period without clearing out the metrics, + // e.g. when a message's ISM aggregates multiple different validator sets. + for (validator, last_updated_at) in prev_validators { + if last_updated_at.elapsed() < MIN_VALIDATOR_METRIC_RESET_PERIOD { + // If the last metric refresh was too recent, keep the validator + // and the time of its last metric update. + new_set.insert(*validator, *last_updated_at); + continue; + } // We unwrap because an error here occurs if the # of labels // provided is incorrect, and we'd like to loudly fail in e2e if that // happens. @@ -508,8 +530,6 @@ impl ValidatorObservabilityMetricManager { } } - let mut set = HashSet::new(); - // Then set the new metrics and update the cached set of validators. for (validator, latest_checkpoint) in latest_checkpoints { self.observed_validator_latest_index @@ -522,9 +542,9 @@ impl ValidatorObservabilityMetricManager { // If the latest checkpoint is None, set to -1 to indicate that // the validator did not provide a valid latest checkpoint index. .set(latest_checkpoint.map(|i| i as i64).unwrap_or(-1)); - set.insert(*validator); + new_set.insert(*validator, time::Instant::now()); } - app_context_validators.insert(key, set); + app_context_validators.insert(key, new_set); } /// Gauge for reporting recently observed latest checkpoint indices for validator sets. From 5a0d68bdce143d31bd775e697aca11119c60fdea Mon Sep 17 00:00:00 2001 From: Tien Dao <15717476+tiendn@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:27:18 +0700 Subject: [PATCH 029/224] fix: replace import console module with direct console (#4487) This PR addresses the restriction on using 'console' from module for follow [eslint rule](https://eslint.org/docs/latest/rules/no-restricted-imports). The changes include: - Remove all import `console` module, use directly instead Such as: `import {log} from 'console` and `@hyperlane-xyz/utils` ### Changes #### Added #### Modified - `services/HyperlaneService.ts` - `scripts/annouce-validator.ts` ### Testing - Everything work well. Just console ### Notes - In the future, we should manage log on a unified logger instead of directly console --- .changeset/gorgeous-owls-kiss.md | 6 ++++++ typescript/ccip-server/src/services/HyperlaneService.ts | 4 +--- typescript/infra/scripts/announce-validators.ts | 7 +++++-- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 .changeset/gorgeous-owls-kiss.md diff --git a/.changeset/gorgeous-owls-kiss.md b/.changeset/gorgeous-owls-kiss.md new file mode 100644 index 000000000..0355a25b4 --- /dev/null +++ b/.changeset/gorgeous-owls-kiss.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/ccip-server': patch +'@hyperlane-xyz/infra': patch +--- + +replace import console module with direct console diff --git a/typescript/ccip-server/src/services/HyperlaneService.ts b/typescript/ccip-server/src/services/HyperlaneService.ts index 47d86d6ee..a3c8b3b3f 100644 --- a/typescript/ccip-server/src/services/HyperlaneService.ts +++ b/typescript/ccip-server/src/services/HyperlaneService.ts @@ -1,5 +1,3 @@ -import { info } from 'console'; - import { Message, MessageTx } from './explorerTypes'; // These types are copied from hyperlane-explorer. TODO: export them so this file can use them directly. @@ -21,7 +19,7 @@ class HyperlaneService { * @param id: Message id to look up */ async getOriginBlockByMessageId(id: string): Promise { - info(`Fetching block for id: ${id}`); + console.info(`Fetching block for id: ${id}`); const response = await fetch( `${this.baseUrl}?module=message&action=${API_ACTION.GetMessages}&id=${id}`, ); diff --git a/typescript/infra/scripts/announce-validators.ts b/typescript/infra/scripts/announce-validators.ts index 0d6e47fd1..a4691fe75 100644 --- a/typescript/infra/scripts/announce-validators.ts +++ b/typescript/infra/scripts/announce-validators.ts @@ -1,9 +1,9 @@ -import { assert } from 'console'; import { ethers } from 'ethers'; import { readFileSync } from 'fs'; import * as path from 'path'; import { ChainName } from '@hyperlane-xyz/sdk'; +import { assert } from '@hyperlane-xyz/utils'; import { getChains } from '../config/registry.js'; import { InfraS3Validator } from '../src/agents/aws/validator.js'; @@ -118,7 +118,10 @@ async function main() { const location = announcement.value.storage_location; const announcedLocations = await validatorAnnounce.getAnnouncedStorageLocations([address]); - assert(announcedLocations.length == 1); + assert( + announcedLocations.length == 1, + `Expected 1 announced location, got ${announcedLocations.length}`, + ); const announced = announcedLocations[0].includes(location); if (!announced) { const signature = ethers.utils.joinSignature(announcement.signature); From 739af9a34b79a65a56b25f5f7f227e82aa03eab9 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:29:15 +0100 Subject: [PATCH 030/224] feat: check-deploy multiple specified chains (#4494) feat: check-deploy multiple specified chains - resolves https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4491 --- .changeset/flat-seals-prove.md | 5 +++ .../infra/scripts/check/check-deploy.ts | 11 ++----- typescript/infra/scripts/check/check-utils.ts | 32 +++++++++++-------- .../infra/scripts/check/check-warp-deploy.ts | 4 +-- .../infra/src/govern/HyperlaneAppGovernor.ts | 4 +-- .../infra/src/govern/HyperlaneHaasGovernor.ts | 6 ++-- .../sdk/src/deploy/HyperlaneAppChecker.ts | 31 +++++++++++------- 7 files changed, 52 insertions(+), 41 deletions(-) create mode 100644 .changeset/flat-seals-prove.md diff --git a/.changeset/flat-seals-prove.md b/.changeset/flat-seals-prove.md new file mode 100644 index 000000000..a51d5ef68 --- /dev/null +++ b/.changeset/flat-seals-prove.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Support providing multiple chains for checking in HyperlaneAppChecker diff --git a/typescript/infra/scripts/check/check-deploy.ts b/typescript/infra/scripts/check/check-deploy.ts index 19943286e..2121d2582 100644 --- a/typescript/infra/scripts/check/check-deploy.ts +++ b/typescript/infra/scripts/check/check-deploy.ts @@ -10,7 +10,7 @@ async function main() { context, environment, asDeployer, - chain, + chains, fork, govern, warpRouteId, @@ -22,7 +22,7 @@ async function main() { environment, asDeployer, warpRouteId, - chain, + chains, fork, govern, ); @@ -32,13 +32,8 @@ async function main() { if (govern) { await governor.govern(false, fork); } - } else if (chain) { - await governor.checkChain(chain); - if (govern) { - await governor.govern(true, chain); - } } else { - await governor.check(); + await governor.check(chains); if (govern) { await governor.govern(); } diff --git a/typescript/infra/scripts/check/check-utils.ts b/typescript/infra/scripts/check/check-utils.ts index 2b2d4d22f..096745134 100644 --- a/typescript/infra/scripts/check/check-utils.ts +++ b/typescript/infra/scripts/check/check-utils.ts @@ -37,7 +37,7 @@ import { getArgs as getRootArgs, getWarpAddresses, withAsDeployer, - withChain, + withChains, withContext, withFork, withGovern, @@ -50,7 +50,7 @@ import { getHelloWorldApp } from '../helloworld/utils.js'; export function getCheckBaseArgs() { return withAsDeployer( - withGovern(withChain(withFork(withContext(getRootArgs())))), + withGovern(withChains(withFork(withContext(getRootArgs())))), ); } @@ -68,7 +68,7 @@ export async function getGovernor( environment: DeployEnvironment, asDeployer: boolean, warpRouteId?: string, - chain?: string, + chains?: string[], fork?: string, govern?: boolean, ) { @@ -217,20 +217,24 @@ export async function getGovernor( multiProvider, ); - // log error and return if foreign deployment chain is specifically checked - if ( - (chain && foreignDeployments[chain]) || - (fork && foreignDeployments[fork]) - ) { + // log error and return if requesting check on foreign deployment + const nonEvmChains = chains + ? chains.filter((c) => foreignDeployments[c]) + : fork && foreignDeployments[fork] + ? [fork] + : []; + + if (nonEvmChains.length > 0) { + const chainList = nonEvmChains.join(', '); console.log( - `${ - chain ?? fork - } is non evm and it not compatible with warp checker tooling`, + `${chainList} ${ + nonEvmChains.length > 1 ? 'are' : 'is' + } non-EVM and not compatible with warp checker tooling`, ); throw Error( - `${ - chain ?? fork - } is non evm and it not compatible with warp checker tooling`, + `${chainList} ${ + nonEvmChains.length > 1 ? 'are' : 'is' + } non-EVM and not compatible with warp checker tooling`, ); } diff --git a/typescript/infra/scripts/check/check-warp-deploy.ts b/typescript/infra/scripts/check/check-warp-deploy.ts index 8082a6347..1a582aa8c 100644 --- a/typescript/infra/scripts/check/check-warp-deploy.ts +++ b/typescript/infra/scripts/check/check-warp-deploy.ts @@ -13,7 +13,7 @@ import { } from './check-utils.js'; async function main() { - const { environment, asDeployer, chain, fork, context, pushMetrics } = + const { environment, asDeployer, chains, fork, context, pushMetrics } = await getCheckWarpDeployArgs().argv; const metricsRegister = new Registry(); @@ -36,7 +36,7 @@ async function main() { environment, asDeployer, warpRouteId, - chain, + chains, fork, ); diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index d91465d24..f8464f3a6 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -70,8 +70,8 @@ export abstract class HyperlaneAppGovernor< } } - async check() { - await this.checker.check(); + async check(chainsToCheck?: ChainName[]) { + await this.checker.check(chainsToCheck); } async checkChain(chain: ChainName) { diff --git a/typescript/infra/src/govern/HyperlaneHaasGovernor.ts b/typescript/infra/src/govern/HyperlaneHaasGovernor.ts index e1fca5731..921649c5b 100644 --- a/typescript/infra/src/govern/HyperlaneHaasGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneHaasGovernor.ts @@ -70,9 +70,9 @@ export class HyperlaneHaasGovernor extends HyperlaneAppGovernor< } } - async check() { - await this.icaChecker.check(); - await this.coreChecker.check(); + async check(chainsToCheck?: ChainName[]) { + await this.icaChecker.check(chainsToCheck); + await this.coreChecker.check(chainsToCheck); } async checkChain(chain: ChainName) { diff --git a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts index 63672be18..871019a17 100644 --- a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts +++ b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts @@ -45,26 +45,33 @@ export abstract class HyperlaneAppChecker< abstract checkChain(chain: ChainName): Promise; - async check(): Promise { - const appChains = this.app.chains(); + async check(chainsToCheck?: ChainName[]): Promise { + // Get all EVM chains from config + const evmChains = Object.keys(this.configMap).filter( + (chain) => + this.multiProvider.getChainMetadata(chain).protocol === + ProtocolType.Ethereum, + ); - Object.keys(this.configMap) - .filter( - (chain) => - this.multiProvider.getChainMetadata(chain).protocol === - ProtocolType.Ethereum && !appChains.includes(chain), - ) - .forEach((chain: string) => + // Mark any EVM chains that are not deployed + const appChains = this.app.chains(); + for (const chain of evmChains) { + if (!appChains.includes(chain)) { this.addViolation({ type: ViolationType.NotDeployed, chain, expected: '', actual: '', - }), - ); + }); + } + } + // Finally, check the chains that were explicitly requested + // If no chains were requested, check all app chains + const chains = + !chainsToCheck || chainsToCheck.length === 0 ? appChains : chainsToCheck; return Promise.all( - appChains + chains .filter( (chain) => this.multiProvider.getChainMetadata(chain).protocol === From 509213dcfceddc623731af7c31191275f29d49f6 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:34:11 -0400 Subject: [PATCH 031/224] fix: warp apply throws if submitter transactionReceipts is undefined (#4501) ### Description Fix to add conditional for `transactionReceipts` so that the yaml is only parsed when it is not `undefined`. ### Drive-by changes E2e tests for warp apply strategy ### Backward compatibility Yes ### Testing Manual/Unit Tests --- .../strategy/json-rpc-chain-strategy.yaml | 5 +- typescript/cli/src/deploy/warp.ts | 11 ++-- typescript/cli/src/tests/commands/helpers.ts | 25 +++++--- typescript/cli/src/tests/commands/warp.ts | 2 + .../cli/src/tests/warp-apply.e2e-test.ts | 60 ++++++++++++++++++- .../ethersV5/EV5GnosisSafeTxSubmitter.ts | 6 +- 6 files changed, 88 insertions(+), 21 deletions(-) diff --git a/typescript/cli/examples/submit/strategy/json-rpc-chain-strategy.yaml b/typescript/cli/examples/submit/strategy/json-rpc-chain-strategy.yaml index 6e4c2ce6f..20197ffd6 100644 --- a/typescript/cli/examples/submit/strategy/json-rpc-chain-strategy.yaml +++ b/typescript/cli/examples/submit/strategy/json-rpc-chain-strategy.yaml @@ -1,3 +1,6 @@ -anvil1: +anvil2: + submitter: + type: jsonRpc +anvil3: submitter: type: jsonRpc diff --git a/typescript/cli/src/deploy/warp.ts b/typescript/cli/src/deploy/warp.ts index f2dafcef9..b34caa910 100644 --- a/typescript/cli/src/deploy/warp.ts +++ b/typescript/cli/src/deploy/warp.ts @@ -497,12 +497,10 @@ export async function runWarpRouteApply( }); const transactionReceipts = await submitter.submit(...transactions); - if (transactionReceipts && transactionReceipts.length > 0) { - return logGreen( - `✅ Warp config update successfully submitted with ${submitter.txSubmitterType} on ${chain}:\n\n`, - indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 4), - ); - } + return logGreen( + `✅ Warp config update successfully submitted with ${submitter.txSubmitterType} on ${chain}:\n\n`, + indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 4), + ); } catch (e) { logRed(`Warp config on ${chain} failed to update.`, e); } @@ -677,7 +675,6 @@ async function enrollRemoteRouters( strategyUrl, }); const transactionReceipts = await submitter.submit(...mutatedConfigTxs); - return logGreen( `✅ Router enrollment update successfully submitted with ${submitter.txSubmitterType} on ${chain}:\n\n`, indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 4), diff --git a/typescript/cli/src/tests/commands/helpers.ts b/typescript/cli/src/tests/commands/helpers.ts index 47fb9a11c..e4f43e894 100644 --- a/typescript/cli/src/tests/commands/helpers.ts +++ b/typescript/cli/src/tests/commands/helpers.ts @@ -64,13 +64,22 @@ export async function updateOwner( /** * Extends the Warp route deployment with a new warp config */ -export async function extendWarpConfig( - chain: string, - chainToExtend: string, - extendedConfig: TokenRouterConfig, - warpCorePath: string, - warpDeployPath: string, -): Promise { +export async function extendWarpConfig(params: { + chain: string; + chainToExtend: string; + extendedConfig: TokenRouterConfig; + warpCorePath: string; + warpDeployPath: string; + strategyUrl?: string; +}): Promise { + const { + chain, + chainToExtend, + extendedConfig, + warpCorePath, + warpDeployPath, + strategyUrl, + } = params; const warpDeployConfig = await readWarpConfig( chain, warpCorePath, @@ -78,7 +87,7 @@ export async function extendWarpConfig( ); warpDeployConfig[chainToExtend] = extendedConfig; writeYamlOrJson(warpDeployPath, warpDeployConfig); - await hyperlaneWarpApply(warpDeployPath, warpCorePath); + await hyperlaneWarpApply(warpDeployPath, warpCorePath, strategyUrl); return warpDeployPath; } diff --git a/typescript/cli/src/tests/commands/warp.ts b/typescript/cli/src/tests/commands/warp.ts index 905778433..16b8acbfe 100644 --- a/typescript/cli/src/tests/commands/warp.ts +++ b/typescript/cli/src/tests/commands/warp.ts @@ -26,6 +26,7 @@ export async function hyperlaneWarpDeploy(warpCorePath: string) { export async function hyperlaneWarpApply( warpDeployPath: string, warpCorePath: string, + strategyUrl = '', ) { return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp apply \ --registry ${REGISTRY_PATH} \ @@ -33,6 +34,7 @@ export async function hyperlaneWarpApply( --warp ${warpCorePath} \ --key ${ANVIL_KEY} \ --verbosity debug \ + --strategy ${strategyUrl} \ --yes`; } diff --git a/typescript/cli/src/tests/warp-apply.e2e-test.ts b/typescript/cli/src/tests/warp-apply.e2e-test.ts index 23a135d8f..791726861 100644 --- a/typescript/cli/src/tests/warp-apply.e2e-test.ts +++ b/typescript/cli/src/tests/warp-apply.e2e-test.ts @@ -108,14 +108,68 @@ describe('WarpApply e2e tests', async function () { type: TokenType.native, }; - await extendWarpConfig( + await extendWarpConfig({ + chain: CHAIN_NAME_2, + chainToExtend: CHAIN_NAME_3, + extendedConfig: config, + warpCorePath: WARP_CORE_CONFIG_PATH_2, + warpDeployPath: warpConfigPath, + }); + + const COMBINED_WARP_CORE_CONFIG_PATH = `${REGISTRY_PATH}/deployments/warp_routes/ETH/anvil2-anvil3-config.yaml`; + + // Check that chain2 is enrolled in chain1 + const updatedWarpDeployConfig1 = await readWarpConfig( CHAIN_NAME_2, + COMBINED_WARP_CORE_CONFIG_PATH, + warpConfigPath, + ); + + const chain2Id = await getChainId(CHAIN_NAME_3, ANVIL_KEY); + const remoteRouterKeys1 = Object.keys( + updatedWarpDeployConfig1[CHAIN_NAME_2].remoteRouters!, + ); + expect(remoteRouterKeys1).to.include(chain2Id); + + // Check that chain1 is enrolled in chain2 + const updatedWarpDeployConfig2 = await readWarpConfig( CHAIN_NAME_3, - config, - WARP_CORE_CONFIG_PATH_2, + COMBINED_WARP_CORE_CONFIG_PATH, warpConfigPath, ); + const chain1Id = await getChainId(CHAIN_NAME_2, ANVIL_KEY); + const remoteRouterKeys2 = Object.keys( + updatedWarpDeployConfig2[CHAIN_NAME_3].remoteRouters!, + ); + expect(remoteRouterKeys2).to.include(chain1Id); + }); + + it('should extend an existing warp route with json strategy', async () => { + // Read existing config into a file + const warpConfigPath = `${TEMP_PATH}/warp-route-deployment-2.yaml`; + await readWarpConfig(CHAIN_NAME_2, WARP_CORE_CONFIG_PATH_2, warpConfigPath); + + // Extend with new config + const config: TokenRouterConfig = { + decimals: 18, + mailbox: chain2Addresses!.mailbox, + name: 'Ether', + owner: new Wallet(ANVIL_KEY).address, + symbol: 'ETH', + totalSupply: 0, + type: TokenType.native, + }; + + await extendWarpConfig({ + chain: CHAIN_NAME_2, + chainToExtend: CHAIN_NAME_3, + extendedConfig: config, + warpCorePath: WARP_CORE_CONFIG_PATH_2, + warpDeployPath: warpConfigPath, + strategyUrl: `${EXAMPLES_PATH}/submit/strategy/json-rpc-chain-strategy.yaml`, + }); + const COMBINED_WARP_CORE_CONFIG_PATH = `${REGISTRY_PATH}/deployments/warp_routes/ETH/anvil2-anvil3-config.yaml`; // Check that chain2 is enrolled in chain1 diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts index ff120d6d3..195b0b454 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts @@ -62,7 +62,7 @@ export class EV5GnosisSafeTxSubmitter implements EV5TxSubmitterInterface { ); } - public async submit(...txs: PopulatedTransactions): Promise { + public async submit(...txs: PopulatedTransactions): Promise { const nextNonce: number = await this.safeService.getNextNonce( this.props.safeAddress, ); @@ -94,12 +94,14 @@ export class EV5GnosisSafeTxSubmitter implements EV5TxSubmitterInterface { `Submitting transaction proposal to ${this.props.safeAddress} on ${this.props.chain}: ${safeTxHash}`, ); - return this.safeService.proposeTransaction({ + const transactionReceipts = await this.safeService.proposeTransaction({ safeAddress: this.props.safeAddress, safeTransactionData, safeTxHash, senderAddress, senderSignature, }); + + return transactionReceipts ?? []; } } From be53dd23c7e3cd69942c3d2bef2af767b0d85c0c Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:58:22 +0100 Subject: [PATCH 032/224] feat: infra script for printing mailbox ownership (#4497) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: script to check mailbox ownership drive-by: - ICA ownership for everclear+oortmainnet - move check scripts to check dir mainnet3: ```sh ┌──────────────┬──────────────────────────────────────────────┬────────┐ │ (index) │ address │ owner │ ├──────────────┼──────────────────────────────────────────────┼────────┤ │ ancient8 │ '0xD2BFA0F0654E3f2139b8cDC56c32eeC54D32b133' │ 'SAFE' │ │ arbitrum │ '0x03fD5BE9DF85F0017dC7F4DC3068dDF64fffF25e' │ 'SAFE' │ │ astar │ '0x6b241544eBa7d89B51b72DF85a0342dAa37371Ca' │ 'ICA' │ │ astarzkevm │ '0x526c6DAee1175A1A2337E703B63593acb327Dde4' │ 'ICA' │ │ avalanche │ '0x5bE94B17112B8F18eA9Ac8e559377B467556a3c3' │ 'SAFE' │ │ base │ '0x3949eD0CD036D9FF662d97BD7aC1686051c4aeBF' │ 'SAFE' │ │ bitlayer │ '0xe6239316cA60814229E801fF0B9DD71C9CA29008' │ 'ICA' │ │ blast │ '0xaCD1865B262C89Fb0b50dcc8fB095330ae8F35b5' │ 'SAFE' │ │ bob │ '0x9e2fe7723b018d02cDE4f5cC1A9bC9C65b922Fc8' │ 'SAFE' │ │ bsc │ '0x7bB2ADeDdC342ffb611dDC073095cc4B8C547170' │ 'SAFE' │ │ celo │ '0x879038d6Fc9F6D5e2BA73188bd078486d77e1156' │ 'SAFE' │ │ cheesechain │ '0xEe2C5320BE9bC7A1492187cfb289953b53E3ff1b' │ 'ICA' │ │ coredao │ '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F' │ 'ICA' │ │ cyber │ '0x984Fe5a45Ac4aaeC4E4655b50f776aB79c9Be19F' │ 'ICA' │ │ degenchain │ '0x22d952d3b9F493442731a3c7660aCaD98e55C00A' │ 'ICA' │ │ dogechain │ '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F' │ 'ICA' │ │ endurance │ '0xaCD1865B262C89Fb0b50dcc8fB095330ae8F35b5' │ 'SAFE' │ │ ethereum │ '0x3965AC3D295641E452E0ea896a086A9cD7C6C5b6' │ 'SAFE' │ │ everclear │ '0x63B2075372D6d0565F51210D0A296D3c8a773aB6' │ 'ICA' │ │ flare │ '0x689b8DaBBF2f9Fd83D37427A062B30edF463e20b' │ 'ICA' │ │ fraxtal │ '0x66e9f52800E9F89F0569fddc594Acd5EE609f762' │ 'SAFE' │ │ fusemainnet │ '0x29a526227CB864C90Cf078d03872da913B473139' │ 'SAFE' │ │ gnosis │ '0x0Ac72fBc82c9c39F81242229631dfC38aA13031B' │ 'SAFE' │ │ inevm │ '0xFDF9EDcb2243D51f5f317b9CEcA8edD2bEEE036e' │ 'ICA' │ │ kroma │ '0xc1e20A0D78E79B94D71d4bDBC8FD0Af7c856Dd7A' │ 'ICA' │ │ linea │ '0xaCD1865B262C89Fb0b50dcc8fB095330ae8F35b5' │ 'SAFE' │ │ lisk │ '0x22d952d3b9F493442731a3c7660aCaD98e55C00A' │ 'ICA' │ │ lukso │ '0xc1e20A0D78E79B94D71d4bDBC8FD0Af7c856Dd7A' │ 'ICA' │ │ mantapacific │ '0x03ed2D65f2742193CeD99D48EbF1F1D6F12345B6' │ 'SAFE' │ │ mantle │ '0x8aFE6EECc6CcB02aA20DA8Fff7d29aadEBbc2DCd' │ 'SAFE' │ │ merlin │ '0xCf867cEaeeE8CBe65C680c734D29d26440931D5b' │ 'ICA' │ │ metis │ '0xb51e63CD0842D670a13c88B159fCFc268DA652A3' │ 'ICA' │ │ mint │ '0xb51e63CD0842D670a13c88B159fCFc268DA652A3' │ 'ICA' │ │ mode │ '0xaCD1865B262C89Fb0b50dcc8fB095330ae8F35b5' │ 'SAFE' │ │ molten │ '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F' │ 'ICA' │ │ moonbeam │ '0x594203849E52BF6ee0E511cD807Ca2D658893e37' │ 'SAFE' │ │ oortmainnet │ '0x7021D11F9fAe455AB2f45D72dbc2C64d116Cb657' │ 'ICA' │ │ optimism │ '0xbd7db3821806bc72D223F0AE521Bf82FcBd6Ef4d' │ 'SAFE' │ │ polygon │ '0xf9cFD440CfBCfAB8473cc156485B7eE753b2913E' │ 'SAFE' │ │ polygonzkevm │ '0x1610f578D4d77Fc4ae7ce2DD9AA0b98A5Cd0a9b2' │ 'SAFE' │ │ proofofplay │ '0xb51e63CD0842D670a13c88B159fCFc268DA652A3' │ 'ICA' │ │ real │ '0xc761e68BF3A94326FD0D305e3ccb4cdaab2edA19' │ 'ICA' │ │ redstone │ '0xa1a50ff5FD859558E1899fEC5C3064483177FA23' │ 'SAFE' │ │ sanko │ '0x5DAcd2f1AafC749F2935A160865Ab1568eC23752' │ 'ICA' │ │ scroll │ '0x6EeEbB9F7FB18DD5E59F82658c59B846715eD4F7' │ 'SAFE' │ │ sei │ '0xCed197FBc360C26C19889745Cf73511b71D03d5D' │ 'SAFE' │ │ shibarium │ '0x6348FAe3a8374dbAAaE84EEe5458AE4063Fe2be7' │ 'ICA' │ │ taiko │ '0xa4864301d3fa2a3e68256309F9F0F570270a1BD0' │ 'SAFE' │ │ tangle │ '0xCC2aeb692197C7894E561d31ADFE8F79746f7d9F' │ 'ICA' │ │ viction │ '0x23ed65DE22ac29Ec1C16E75EddB0cE3A187357b4' │ 'ICA' │ │ worldchain │ '0x1996DbFcFB433737fE404F58D2c32A7f5f334210' │ 'ICA' │ │ xai │ '0x22d952d3b9F493442731a3c7660aCaD98e55C00A' │ 'ICA' │ │ xlayer │ '0x1571c482fe9E76bbf50829912b1c746792966369' │ 'ICA' │ │ zetachain │ '0x9d399876522Fc5C044D048594de399A2349d6026' │ 'SAFE' │ │ zircuit │ '0x9e2fe7723b018d02cDE4f5cC1A9bC9C65b922Fc8' │ 'SAFE' │ │ zoramainnet │ '0xF87018025575552889062De4b05bBC3DAe35Cd96' │ 'SAFE' │ └──────────────┴──────────────────────────────────────────────┴────────┘ Total chains: 56 ┌─────────┬────────────────┬─────────────┐ │ (index) │ Owner Type │ Chain Count │ ├─────────┼────────────────┼─────────────┤ │ 0 │ 'ICA' │ 28 │ │ 1 │ 'SAFE' │ 28 │ │ 2 │ 'DEPLOYER KEY' │ 0 │ │ 3 │ 'UNKNOWN' │ 0 │ └─────────┴────────────────┴─────────────┘ ``` testnet4: ``` ┌──────────────────────┬──────────────────────────────────────────────┬────────────────┐ │ (index) │ address │ owner │ ├──────────────────────┼──────────────────────────────────────────────┼────────────────┤ │ alfajores │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ arbitrumsepolia │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ basesepolia │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ bsctestnet │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ connextsepolia │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ ecotestnet │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ fuji │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ holesky │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ optimismsepolia │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ polygonamoy │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ scrollsepolia │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ sepolia │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ │ superpositiontestnet │ '0xfaD1C94469700833717Fa8a3017278BC1cA8031C' │ 'DEPLOYER KEY' │ └──────────────────────┴──────────────────────────────────────────────┴────────────────┘ Total chains: 13 ┌─────────┬────────────────┬─────────────┐ │ (index) │ Owner Type │ Chain Count │ ├─────────┼────────────────┼─────────────┤ │ 0 │ 'ICA' │ 0 │ │ 1 │ 'SAFE' │ 0 │ │ 2 │ 'DEPLOYER KEY' │ 13 │ │ 3 │ 'UNKNOWN' │ 0 │ └─────────┴────────────────┴─────────────┘ ``` --- .../config/environments/mainnet3/owners.ts | 5 + .../scripts/{ => check}/check-owner-ica.ts | 7 +- .../scripts/{ => check}/check-rpc-urls.ts | 7 +- .../{ => check}/check-validator-announce.ts | 7 +- .../infra/scripts/print-mailbox-owner.ts | 139 ++++++++++++++++++ 5 files changed, 153 insertions(+), 12 deletions(-) rename typescript/infra/scripts/{ => check}/check-owner-ica.ts (89%) rename typescript/infra/scripts/{ => check}/check-rpc-urls.ts (85%) rename typescript/infra/scripts/{ => check}/check-validator-announce.ts (94%) create mode 100644 typescript/infra/scripts/print-mailbox-owner.ts diff --git a/typescript/infra/config/environments/mainnet3/owners.ts b/typescript/infra/config/environments/mainnet3/owners.ts index c0a1e34d9..66cd8d17d 100644 --- a/typescript/infra/config/environments/mainnet3/owners.ts +++ b/typescript/infra/config/environments/mainnet3/owners.ts @@ -99,6 +99,11 @@ export const icas: Partial< flare: '0x689b8DaBBF2f9Fd83D37427A062B30edF463e20b', molten: '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F', shibarium: '0x6348FAe3a8374dbAAaE84EEe5458AE4063Fe2be7', + + // Sep 9, 2024 batch + // ---------------------------- + everclear: '0x63B2075372D6d0565F51210D0A296D3c8a773aB6', + oortmainnet: '0x7021D11F9fAe455AB2f45D72dbc2C64d116Cb657', } as const; export const DEPLOYER = '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba'; diff --git a/typescript/infra/scripts/check-owner-ica.ts b/typescript/infra/scripts/check/check-owner-ica.ts similarity index 89% rename from typescript/infra/scripts/check-owner-ica.ts rename to typescript/infra/scripts/check/check-owner-ica.ts index 1866eeb10..15d053628 100644 --- a/typescript/infra/scripts/check-owner-ica.ts +++ b/typescript/infra/scripts/check/check-owner-ica.ts @@ -1,10 +1,9 @@ import { AccountConfig, InterchainAccount } from '@hyperlane-xyz/sdk'; import { Address, eqAddress } from '@hyperlane-xyz/utils'; -import { icas } from '../config/environments/mainnet3/owners.js'; - -import { getArgs as getEnvArgs } from './agent-utils.js'; -import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js'; +import { icas } from '../../config/environments/mainnet3/owners.js'; +import { getArgs as getEnvArgs } from '../agent-utils.js'; +import { getEnvironmentConfig, getHyperlaneCore } from '../core-utils.js'; function getArgs() { return getEnvArgs().option('ownerChain', { diff --git a/typescript/infra/scripts/check-rpc-urls.ts b/typescript/infra/scripts/check/check-rpc-urls.ts similarity index 85% rename from typescript/infra/scripts/check-rpc-urls.ts rename to typescript/infra/scripts/check/check-rpc-urls.ts index 307e4515c..7382a3007 100644 --- a/typescript/infra/scripts/check-rpc-urls.ts +++ b/typescript/infra/scripts/check/check-rpc-urls.ts @@ -2,10 +2,9 @@ import { ethers } from 'ethers'; import { rootLogger } from '@hyperlane-xyz/utils'; -import { getSecretRpcEndpoints } from '../src/agents/index.js'; - -import { getArgs } from './agent-utils.js'; -import { getEnvironmentConfig } from './core-utils.js'; +import { getSecretRpcEndpoints } from '../../src/agents/index.js'; +import { getArgs } from '../agent-utils.js'; +import { getEnvironmentConfig } from '../core-utils.js'; async function main() { const { environment } = await getArgs().argv; diff --git a/typescript/infra/scripts/check-validator-announce.ts b/typescript/infra/scripts/check/check-validator-announce.ts similarity index 94% rename from typescript/infra/scripts/check-validator-announce.ts rename to typescript/infra/scripts/check/check-validator-announce.ts index 2857ceab4..fec2f2e07 100644 --- a/typescript/infra/scripts/check-validator-announce.ts +++ b/typescript/infra/scripts/check/check-validator-announce.ts @@ -1,10 +1,9 @@ import { ChainMap, defaultMultisigConfigs } from '@hyperlane-xyz/sdk'; import { eqAddress } from '@hyperlane-xyz/utils'; -import { isEthereumProtocolChain } from '../src/utils/utils.js'; - -import { getArgs, withChains } from './agent-utils.js'; -import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js'; +import { isEthereumProtocolChain } from '../../src/utils/utils.js'; +import { getArgs, withChains } from '../agent-utils.js'; +import { getEnvironmentConfig, getHyperlaneCore } from '../core-utils.js'; const minimumValidatorCount = 3; diff --git a/typescript/infra/scripts/print-mailbox-owner.ts b/typescript/infra/scripts/print-mailbox-owner.ts new file mode 100644 index 000000000..78b4fea93 --- /dev/null +++ b/typescript/infra/scripts/print-mailbox-owner.ts @@ -0,0 +1,139 @@ +import { ethers } from 'ethers'; + +import { ChainAddresses } from '@hyperlane-xyz/registry'; +import { + ChainMap, + CoreFactories, + HyperlaneContracts, + HyperlaneCore, +} from '@hyperlane-xyz/sdk'; +import { + Address, + eqAddressEvm, + objFilter, + objMap, + promiseObjAll, +} from '@hyperlane-xyz/utils'; + +import { Contexts } from '../config/contexts.js'; +import { DeployEnvironment } from '../src/config/environment.js'; +import { Role } from '../src/roles.js'; +import { + filterRemoteDomainMetadata, + isEthereumProtocolChain, +} from '../src/utils/utils.js'; + +import { + Modules, + getAddresses, + getArgs, + withAgentRoles, + withChains, + withContext, +} from './agent-utils.js'; +import { getEnvironmentConfig } from './core-utils.js'; + +const DEPLOYERS: Record = { + mainnet3: '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba', + testnet4: '0xfaD1C94469700833717Fa8a3017278BC1cA8031C', + test: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', +}; + +export enum Owner { + ICA = 'ICA', + SAFE = 'SAFE', + DEPLOYER = 'DEPLOYER KEY', + UNKNOWN = 'UNKNOWN', +} + +async function main() { + const { + context = Contexts.Hyperlane, + environment, + chains, + } = await withContext(withChains(withAgentRoles(getArgs()))).argv; + + const envConfig = getEnvironmentConfig(environment); + const chainsToCheck = ( + chains?.length ? chains : envConfig.supportedChainNames + ).filter(isEthereumProtocolChain); + + const multiProvider = await envConfig.getMultiProvider( + context, + Role.Deployer, + true, + chainsToCheck, + ); + + // Get the addresses for the environment + const addressesMap = getAddresses( + environment, + Modules.CORE, + ) as ChainMap; + + const addressesForEnv = filterRemoteDomainMetadata(addressesMap); + const core = HyperlaneCore.fromAddressesMap(addressesForEnv, multiProvider); + + const evmContractsMap = objFilter( + core.contractsMap, + (chain, _): _ is HyperlaneContracts => + isEthereumProtocolChain(chain), + ); + + const deployer = DEPLOYERS[environment]; + + const mailboxOwners = await promiseObjAll( + objMap( + evmContractsMap, + async (chain: string, contracts: HyperlaneContracts) => { + // get possible owners from config + const ownerConfig = envConfig.owners[chain]; + const safeAddress = + ownerConfig.ownerOverrides?._safeAddress ?? + ethers.constants.AddressZero; + const icaAddress = + ownerConfig.ownerOverrides?._icaAddress ?? + ethers.constants.AddressZero; + + // get actual onchain owner + const ownerAddress = await contracts.mailbox.owner(); + + // determine owner type + let ownerType = Owner.UNKNOWN; + if (eqAddressEvm(ownerAddress, deployer)) { + ownerType = Owner.DEPLOYER; + } else if (eqAddressEvm(ownerAddress, safeAddress)) { + ownerType = Owner.SAFE; + } else if (eqAddressEvm(ownerAddress, icaAddress)) { + ownerType = Owner.ICA; + } + + return { + address: ownerAddress, + owner: ownerType, + }; + }, + ), + ); + + console.table(mailboxOwners); + + const totalChains = Object.keys(mailboxOwners).length; + console.log(`\nTotal chains: ${totalChains}`); + + console.table( + Object.values(Owner).map((ownerType) => ({ + 'Owner Type': ownerType, + 'Chain Count': Object.values(mailboxOwners).filter( + ({ owner }) => owner === ownerType, + ).length, + })), + ); +} + +main() + .then() + .catch((e) => { + console.error(e); + process.exit(1); + }); From b92b154af0dd60b9dadc28ff5f722c94bdeb22a8 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Tue, 17 Sep 2024 12:14:20 +0100 Subject: [PATCH 033/224] chore: deploy relayer to testnet4 and mainnet3 (#4498) ### Description - Updates the relayer deployments on mainnet3 (hyperlane & neutron contexts) & testnet4 (hyperlane) - Includes a couple recent relayer impacting PRs: #4489 and #4495 ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/infra/config/environments/mainnet3/agent.ts | 6 +++--- typescript/infra/config/environments/testnet4/agent.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 961e8637f..ca61148df 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -378,7 +378,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '9c056c7-20240911-154357', + tag: '5a0d68b-20240916-144115', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -412,7 +412,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '9c056c7-20240911-154357', + tag: '5a0d68b-20240916-144115', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. @@ -445,7 +445,7 @@ const neutron: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '74a592e-20240906-191210', + tag: '5a0d68b-20240916-144115', }, gasPaymentEnforcement: [ { diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index ed709a5e4..f1c5d0ad6 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -177,7 +177,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '73c232b-20240912-124300', + tag: '5a0d68b-20240916-144115', }, blacklist: [...releaseCandidateHelloworldMatchingList, ...relayBlacklist], gasPaymentEnforcement, @@ -223,7 +223,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '73c232b-20240912-124300', + tag: '5a0d68b-20240916-144115', }, whitelist: [...releaseCandidateHelloworldMatchingList], blacklist: relayBlacklist, From cd13f6c08fe08ace98b75d409627c977a330673f Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Tue, 17 Sep 2024 14:10:52 +0100 Subject: [PATCH 034/224] fix: fix VERGEN_GIT_SHA population in Docker image (#4503) ### Description Was accidentally removed in #4438. Wonder if there's an easy way to have tests fail if this doesn't work? ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --------- Co-authored-by: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> --- .github/workflows/rust-skipped.yml | 8 ++++---- rust/Dockerfile | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust-skipped.yml b/.github/workflows/rust-skipped.yml index e4d00219a..4c58de50b 100644 --- a/.github/workflows/rust-skipped.yml +++ b/.github/workflows/rust-skipped.yml @@ -5,15 +5,15 @@ on: push: branches: [main] paths-ignore: - - 'rust/**' + - 'rust/main/**' + - 'rust/sealevel/**' - .github/workflows/rust.yml pull_request: branches: [main] paths-ignore: - - 'rust/**' + - 'rust/main/**' + - 'rust/sealevel/**' - .github/workflows/rust.yml - # Support for merge queues - merge_group: env: CARGO_TERM_COLOR: always diff --git a/rust/Dockerfile b/rust/Dockerfile index 156144ab9..98f638bb4 100644 --- a/rust/Dockerfile +++ b/rust/Dockerfile @@ -25,6 +25,8 @@ COPY rust/sealevel rust/sealevel COPY rust/main/Cargo.toml rust/main/. COPY rust/main/Cargo.lock rust/main/. +# Required for VERGEN_GIT_SHA to be populated +COPY .git .git WORKDIR /usr/src/rust/main From 815542dd78caa17483be74ee9113792727ca519f Mon Sep 17 00:00:00 2001 From: J M Rossy Date: Tue, 17 Sep 2024 16:25:27 +0100 Subject: [PATCH 035/224] fix: Sealevel hyp token adapter fixes (#4500) ### Description - Fix arg validation for Sealevel HypNative adapters - Increase Token.ts test coverage to Sealevel adapters - Swallow getBalance errors for non-existent SVM accounts - Allow extra properties in ChainMetadata objects ### Related issues https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4499 ### Backward compatibility Yes ### Testing Tested in Warp UI --- .changeset/young-moose-march.md | 6 ++ .../sdk/src/metadata/chainMetadataTypes.ts | 9 ++- typescript/sdk/src/token/Token.test.ts | 60 +++++++++++++----- typescript/sdk/src/token/Token.ts | 50 ++++++++------- .../token/adapters/SealevelTokenAdapter.ts | 63 ++++++++++++------- 5 files changed, 125 insertions(+), 63 deletions(-) create mode 100644 .changeset/young-moose-march.md diff --git a/.changeset/young-moose-march.md b/.changeset/young-moose-march.md new file mode 100644 index 000000000..54b531a40 --- /dev/null +++ b/.changeset/young-moose-march.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Fix arg validation for Sealevel HypNative adapters +Allow extra properties in ChainMetadata objects diff --git a/typescript/sdk/src/metadata/chainMetadataTypes.ts b/typescript/sdk/src/metadata/chainMetadataTypes.ts index 3abb48cf8..b83b3f8c6 100644 --- a/typescript/sdk/src/metadata/chainMetadataTypes.ts +++ b/typescript/sdk/src/metadata/chainMetadataTypes.ts @@ -248,8 +248,11 @@ export const ChainMetadataSchemaObject = z.object({ .describe('Properties to include when forming transaction requests.'), }); +// Passthrough allows for extra fields to remain in the object (such as extensions consumers may want like `mailbox`) +const ChainMetadataSchemaExtensible = ChainMetadataSchemaObject.passthrough(); + // Add refinements to the object schema to conditionally validate certain fields -export const ChainMetadataSchema = ChainMetadataSchemaObject.refine( +export const ChainMetadataSchema = ChainMetadataSchemaExtensible.refine( (metadata) => { if ( [ProtocolType.Ethereum, ProtocolType.Sealevel].includes( @@ -333,7 +336,9 @@ export const ChainMetadataSchema = ChainMetadataSchemaObject.refine( }, ); -export type ChainMetadata = z.infer & +export type ChainMetadata = z.infer< + typeof ChainMetadataSchemaObject +> & Ext; export type BlockExplorer = Exclude< diff --git a/typescript/sdk/src/token/Token.test.ts b/typescript/sdk/src/token/Token.test.ts index 8fe6ec332..cd232ebf7 100644 --- a/typescript/sdk/src/token/Token.test.ts +++ b/typescript/sdk/src/token/Token.test.ts @@ -1,4 +1,5 @@ /* eslint-disable no-console */ +import { SystemProgram } from '@solana/web3.js'; import { expect } from 'chai'; import { ethers } from 'ethers'; @@ -109,9 +110,32 @@ const STANDARD_TO_TOKEN: Record = { }, [TokenStandard.SealevelNative]: Token.FromChainMetadataNativeToken(testSealevelChain), - [TokenStandard.SealevelHypNative]: null, - [TokenStandard.SealevelHypCollateral]: null, - [TokenStandard.SealevelHypSynthetic]: null, + [TokenStandard.SealevelHypNative]: { + chainName: testSealevelChain.name, + standard: TokenStandard.SealevelHypNative, + addressOrDenom: '4UMNyNWW75zo69hxoJaRX5iXNUa5FdRPZZa9vDVCiESg', + decimals: 9, + symbol: 'SOL', + name: 'SOL', + }, + [TokenStandard.SealevelHypCollateral]: { + chainName: testSealevelChain.name, + standard: TokenStandard.SealevelHypCollateral, + addressOrDenom: 'Fefw54S6NDdwNbPngPePvW4tiFTFQDT7gBPvFoDFeGqg', + collateralAddressOrDenom: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', + decimals: 6, + symbol: 'USDC', + name: 'USDC', + }, + [TokenStandard.SealevelHypSynthetic]: { + chainName: testSealevelChain.name, + standard: TokenStandard.SealevelHypSynthetic, + addressOrDenom: 'GLpdg3jt6w4eVYiCMhokVZ4mX6hmRvPhcL5RoCjzGr5k', + collateralAddressOrDenom: '8SuhHnSEogAN2udZsoychjTafnaGgM9MCidYZEP8vuVY', + decimals: 9, + symbol: 'SOL', + name: 'SOL', + }, // Cosmos [TokenStandard.CosmosIcs20]: null, @@ -161,18 +185,19 @@ const STANDARD_TO_TOKEN: Record = { [TokenStandard.CwHypSynthetic]: null, }; -const PROTOCOL_TO_ADDRESS: Partial> = { +const PROTOCOL_TO_ADDRESS_FOR_BALANCE_CHECK: Partial< + Record +> = { [ProtocolType.Ethereum]: ethers.constants.AddressZero, [ProtocolType.Cosmos]: 'neutron13we0myxwzlpx8l5ark8elw5gj5d59dl6cjkzmt80c5q5cv5rt54qvzkv2a', + [ProtocolType.Sealevel]: 'EK6cs8jNnu2d9pmKTGf1Bvre9oW2xNhcCKNdLKx6t74w', }; -const STANDARD_TO_ADDRESS: Partial> = { +const STANDARD_TO_ADDRESS_FOR_BALANCE_CHECK: Partial< + Record +> = { [TokenStandard.SealevelSpl]: 'HVSZJ2juJnMxd6yCNarTL56YmgUqzfUiwM7y7LtTXKHR', - [TokenStandard.SealevelSpl2022]: - 'EK6cs8jNnu2d9pmKTGf1Bvre9oW2xNhcCKNdLKx6t74w', - [TokenStandard.SealevelNative]: - 'EK6cs8jNnu2d9pmKTGf1Bvre9oW2xNhcCKNdLKx6t74w', [TokenStandard.CwHypNative]: 'inj1fl48vsnmsdzcv85q5d2q4z5ajdha8yu3lj7tt0', }; @@ -181,16 +206,21 @@ describe('Token', () => { if (!tokenArgs) continue; it(`Handles ${tokenArgs.standard} standard`, async () => { const multiProvider = - MultiProtocolProvider.createTestMultiProtocolProvider(); + MultiProtocolProvider.createTestMultiProtocolProvider<{ + mailbox?: string; + }>(); + // A placeholder mailbox address for the sealevel chain + multiProvider.metadata[testSealevelChain.name].mailbox = + SystemProgram.programId.toBase58(); console.debug('Testing token standard', tokenArgs.standard); const token = new Token(tokenArgs); expect(token.standard).to.eql(tokenArgs.standard); const adapter = token.getAdapter(multiProvider); - const address = - STANDARD_TO_ADDRESS[token.standard] ?? - PROTOCOL_TO_ADDRESS[token.protocol]; - if (!address) + const balanceCheckAddress = + STANDARD_TO_ADDRESS_FOR_BALANCE_CHECK[token.standard] ?? + PROTOCOL_TO_ADDRESS_FOR_BALANCE_CHECK[token.protocol]; + if (!balanceCheckAddress) throw new Error(`No address for standard ${tokenArgs.standard}`); const sandbox = stubMultiProtocolProvider(multiProvider); @@ -199,7 +229,7 @@ describe('Token', () => { balanceOf: async () => '100', }; - const balance = await adapter.getBalance(address); + const balance = await adapter.getBalance(balanceCheckAddress); expect(typeof balance).to.eql('bigint'); sandbox.restore(); }); diff --git a/typescript/sdk/src/token/Token.ts b/typescript/sdk/src/token/Token.ts index 1f24d6b5e..e2541db6b 100644 --- a/typescript/sdk/src/token/Token.ts +++ b/typescript/sdk/src/token/Token.ts @@ -170,13 +170,8 @@ export class Token implements IToken { multiProvider: MultiProtocolProvider<{ mailbox?: Address }>, destination?: ChainName, ): IHypTokenAdapter { - const { - protocol, - standard, - chainName, - addressOrDenom, - collateralAddressOrDenom, - } = this; + const { standard, chainName, addressOrDenom, collateralAddressOrDenom } = + this; const chainMetadata = multiProvider.tryGetChainMetadata(chainName); const mailbox = chainMetadata?.mailbox; @@ -190,19 +185,6 @@ export class Token implements IToken { `Token chain ${chainName} not found in multiProvider`, ); - let sealevelAddresses; - if (protocol === ProtocolType.Sealevel) { - assert(mailbox, `Mailbox required for Sealevel hyp tokens`); - assert( - collateralAddressOrDenom, - `collateralAddressOrDenom required for Sealevel hyp tokens`, - ); - sealevelAddresses = { - warpRouter: addressOrDenom, - token: collateralAddressOrDenom, - mailbox, - }; - } if (standard === TokenStandard.EvmHypNative) { return new EvmHypNativeAdapter(chainName, multiProvider, { token: addressOrDenom, @@ -232,24 +214,46 @@ export class Token implements IToken { token: addressOrDenom, }); } else if (standard === TokenStandard.SealevelHypNative) { + assert(mailbox, `Mailbox required for Sealevel hyp tokens`); return new SealevelHypNativeAdapter( chainName, multiProvider, - sealevelAddresses!, + { + warpRouter: addressOrDenom, + mailbox, + }, false, ); } else if (standard === TokenStandard.SealevelHypCollateral) { + assert(mailbox, `Mailbox required for Sealevel hyp tokens`); + assert( + collateralAddressOrDenom, + `collateralAddressOrDenom required for Sealevel hyp collateral tokens`, + ); return new SealevelHypCollateralAdapter( chainName, multiProvider, - sealevelAddresses!, + { + warpRouter: addressOrDenom, + token: collateralAddressOrDenom, + mailbox, + }, false, ); } else if (standard === TokenStandard.SealevelHypSynthetic) { + assert(mailbox, `Mailbox required for Sealevel hyp tokens`); + assert( + collateralAddressOrDenom, + `collateralAddressOrDenom required for Sealevel hyp synthetic tokens`, + ); return new SealevelHypSyntheticAdapter( chainName, multiProvider, - sealevelAddresses!, + { + warpRouter: addressOrDenom, + token: collateralAddressOrDenom, + mailbox, + }, false, ); } else if (standard === TokenStandard.CwHypNative) { diff --git a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts index 5cae1811f..9529eb4bc 100644 --- a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts @@ -20,7 +20,6 @@ import { Domain, addressToBytes, eqAddress, - isZeroishAddress, } from '@hyperlane-xyz/utils'; import { BaseSealevelAdapter } from '../../app/MultiProtocolApp.js'; @@ -50,7 +49,8 @@ import { SealevelTransferRemoteSchema, } from './serialization.js'; -// author @tkporter @jmrossy +const NON_EXISTENT_ACCOUNT_ERROR = 'could not find account'; + // Interacts with native currencies export class SealevelNativeTokenAdapter extends BaseSealevelAdapter @@ -109,10 +109,15 @@ export class SealevelTokenAdapter async getBalance(owner: Address): Promise { const tokenPubKey = this.deriveAssociatedTokenAccount(new PublicKey(owner)); - const response = await this.getProvider().getTokenAccountBalance( - tokenPubKey, - ); - return BigInt(response.value.amount); + try { + const response = await this.getProvider().getTokenAccountBalance( + tokenPubKey, + ); + return BigInt(response.value.amount); + } catch (error: any) { + if (error.message?.includes(NON_EXISTENT_ACCOUNT_ERROR)) return 0n; + throw error; + } } async getMetadata(_isNft?: boolean): Promise { @@ -162,6 +167,12 @@ export class SealevelTokenAdapter } } +interface HypTokenAddresses { + token: Address; + warpRouter: Address; + mailbox: Address; +} + // The compute limit to set for the transfer remote instruction. // This is typically around ~160k, but can be higher depending on // the index in the merkle tree, which can result in more moderately @@ -175,23 +186,17 @@ export abstract class SealevelHypTokenAdapter implements IHypTokenAdapter { public readonly warpProgramPubKey: PublicKey; + public readonly addresses: HypTokenAddresses; protected cachedTokenAccountData: SealevelHyperlaneTokenData | undefined; constructor( public readonly chainName: ChainName, public readonly multiProvider: MultiProtocolProvider, - public readonly addresses: { - token: Address; - warpRouter: Address; - mailbox: Address; - }, + addresses: HypTokenAddresses, public readonly isSpl2022: boolean = false, ) { - // Pass in placeholder address to avoid errors for native token addresses (which as represented here as 0s) - const superTokenProgramId = isZeroishAddress(addresses.token) - ? SystemProgram.programId.toBase58() - : addresses.token; - super(chainName, multiProvider, { token: superTokenProgramId }, isSpl2022); + super(chainName, multiProvider, { token: addresses.token }, isSpl2022); + this.addresses = addresses; this.warpProgramPubKey = new PublicKey(addresses.warpRouter); } @@ -488,14 +493,21 @@ export class SealevelHypNativeAdapter extends SealevelHypTokenAdapter { constructor( public readonly chainName: ChainName, public readonly multiProvider: MultiProtocolProvider, - public readonly addresses: { - token: Address; + addresses: { + // A 'token' address is not required for hyp native tokens (e.g. hypSOL) + token?: Address; warpRouter: Address; mailbox: Address; }, public readonly isSpl2022: boolean = false, ) { - super(chainName, multiProvider, addresses, isSpl2022); + // Pass in placeholder address for 'token' to avoid errors in the parent classes + super( + chainName, + multiProvider, + { ...addresses, token: SystemProgram.programId.toBase58() }, + isSpl2022, + ); this.wrappedNative = new SealevelNativeTokenAdapter( chainName, multiProvider, @@ -606,10 +618,15 @@ export class SealevelHypSyntheticAdapter extends SealevelHypTokenAdapter { override async getBalance(owner: Address): Promise { const tokenPubKey = this.deriveAssociatedTokenAccount(new PublicKey(owner)); - const response = await this.getProvider().getTokenAccountBalance( - tokenPubKey, - ); - return BigInt(response.value.amount); + try { + const response = await this.getProvider().getTokenAccountBalance( + tokenPubKey, + ); + return BigInt(response.value.amount); + } catch (error: any) { + if (error.message?.includes(NON_EXISTENT_ACCOUNT_ERROR)) return 0n; + throw error; + } } deriveMintAuthorityAccount(): PublicKey { From 040f7efd7f8c950c7b7047681c115832e7ec5aea Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Tue, 17 Sep 2024 16:53:11 +0100 Subject: [PATCH 036/224] chore: Remove pined dependencies on cargo-platform and predicates-core (#4502) ### Description Remove pined dependencies on cargo-platform and predicates-core since the pins are not needed. ### Backward compatibility Yes ### Testing Run E2E Tests Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- rust/main/Cargo.lock | 10 ++++++---- rust/main/Cargo.toml | 10 ---------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index d6f99c489..9364cf598 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -1070,8 +1070,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.6" -source = "git+https://github.com/rust-lang/cargo?tag=0.76.0#1d8b05cdd1287c64467306cf3ca2c8ac60c11eb0" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -6367,8 +6368,9 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" -source = "git+https://github.com/assert-rs/predicates-rs?tag=predicates-core-v1.0.6#7b72b706abbf1509fc74ee18e363d2bc7e8520a6" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" diff --git a/rust/main/Cargo.toml b/rust/main/Cargo.toml index dab1d9cc4..06619dcd4 100644 --- a/rust/main/Cargo.toml +++ b/rust/main/Cargo.toml @@ -231,16 +231,6 @@ features = ["aws"] git = "https://github.com/hyperlane-xyz/ethers-rs" tag = "2024-04-25" -[patch.crates-io.cargo-platform] -git = "https://github.com/rust-lang/cargo" -tag = "0.76.0" -version = "=0.1.6" - -[patch.crates-io.predicates-core] -git = "https://github.com/assert-rs/predicates-rs" -tag = "predicates-core-v1.0.6" -version = "=1.0.6" - [patch.crates-io.curve25519-dalek] branch = "v3.2.2-relax-zeroize" git = "https://github.com/Eclipse-Laboratories-Inc/curve25519-dalek" From 59b5e12e1bb41460292682cf5185731d047c6cb4 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:02:10 -0400 Subject: [PATCH 037/224] fix: Reduce proxy PR to minor (#4505) ### Description This prevents the version from becoming a major update (v6) --- .changeset/famous-ants-tan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/famous-ants-tan.md b/.changeset/famous-ants-tan.md index 927bdc346..d81e23d38 100644 --- a/.changeset/famous-ants-tan.md +++ b/.changeset/famous-ants-tan.md @@ -1,5 +1,5 @@ --- -'@hyperlane-xyz/github-proxy': major +'@hyperlane-xyz/github-proxy': minor --- Add github proxy to reduce github API load From 3113807e3d42740f9a286f6177c194f4fa90a8ce Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:59:01 -0400 Subject: [PATCH 038/224] fix: Add recursive query string (#4507) ### Description - Adds `recursive=true` query string to the url in github-proxy --- .changeset/loud-elephants-reflect.md | 5 +++++ typescript/github-proxy/README.md | 23 +++++++++++++++++++++++ typescript/github-proxy/src/index.ts | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 .changeset/loud-elephants-reflect.md create mode 100644 typescript/github-proxy/README.md diff --git a/.changeset/loud-elephants-reflect.md b/.changeset/loud-elephants-reflect.md new file mode 100644 index 000000000..717cabc98 --- /dev/null +++ b/.changeset/loud-elephants-reflect.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/github-proxy': minor +--- + +Add recursive=true query string to Github Proxy to allow nested tree search diff --git a/typescript/github-proxy/README.md b/typescript/github-proxy/README.md new file mode 100644 index 000000000..498b204ca --- /dev/null +++ b/typescript/github-proxy/README.md @@ -0,0 +1,23 @@ +# Github Proxy + +## Overview + +Github Proxy is a CloudFlare Worker that makes a Github API requests using an API key. This authenticated method allows higher limits than the non-authenticated mode. + +## Keys + +Acquire a Github api key by creating a new [fine-grained personal access token](https://github.com/settings/tokens). + +## Local Development + +Prerequisites: Copy the `.dev.vars.example` and add the Github API key. + +Development is managed by the Wrangler CLI. To start dev mode execute `yarn dev`. This will start a local server. + +## Testing + +Unit tests can be executed using `yarn test`. + +## Deployment + +Execute `yarn deploy` to deploy to production. Note that the deployment requires permissions. To deploy to a staging environment use `yarn deploy:staging`. Use `yarn deploy:key` to attach the Github key to the Worker. diff --git a/typescript/github-proxy/src/index.ts b/typescript/github-proxy/src/index.ts index 500c96426..e1de8a2c5 100644 --- a/typescript/github-proxy/src/index.ts +++ b/typescript/github-proxy/src/index.ts @@ -12,7 +12,7 @@ export default { return new Response(DISALLOWED_URL_MSG, { status: 401 }); } - const apiUrl = new URL(`${GITPUB_API_HOST}${apiUrlPath}`); + const apiUrl = new URL(`${GITPUB_API_HOST}${apiUrlPath}?recursive=true`); return fetch(apiUrl, { method: 'GET', headers: { From 69f17d99a28a8d39765574ddc7d368c26f504d79 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:17:53 +0100 Subject: [PATCH 039/224] fix: obtain default multisend address correctly (#4506) fix: obtain default multisend address correctly - should help decoding if we're using the expect set of multisend addresses - also marks our multisend with `onlyCalls: true` > The reason we can't use `defaultAddress` is because it's fixed to either `canonical` or `eip155` depending on the setting for `ethereum`, regardless of which actually is preferred for each given chain. however, the `networkAddresses` record has items in the correct order. > See https://github.com/safe-global/safe-deployments/blob/b17349df0eb91cf3683eeae882c07f19188421d9/src/utils.ts#L29 for the implementation. drive-by: - bump up to latest safe-deployments patch | Before | After | |--------|-------| | ![Before 1](https://github.com/user-attachments/assets/60b235c1-920b-4c18-b7d8-d50117f3c212) | ![After 1](https://github.com/user-attachments/assets/94cb1feb-04df-49cd-9b29-382917fb5731) | | ![Before 2](https://github.com/user-attachments/assets/d5fd63e7-2b32-4095-9471-8dbbc8d516a3) | ![After 2](https://github.com/user-attachments/assets/17a04cd7-5fa8-4eae-9d4f-365233b8b39b) | --- .changeset/mighty-scissors-unite.md | 5 +++++ typescript/infra/src/govern/multisend.ts | 1 + typescript/infra/src/utils/safe.ts | 2 ++ typescript/sdk/package.json | 2 +- typescript/sdk/src/utils/gnosisSafe.js | 9 ++++----- yarn.lock | 10 +++++----- 6 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 .changeset/mighty-scissors-unite.md diff --git a/.changeset/mighty-scissors-unite.md b/.changeset/mighty-scissors-unite.md new file mode 100644 index 000000000..0e19e46a3 --- /dev/null +++ b/.changeset/mighty-scissors-unite.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Fix to correctly infer the default set of multisend addresses for a given chain, and update to latest safe-deployments patch release diff --git a/typescript/infra/src/govern/multisend.ts b/typescript/infra/src/govern/multisend.ts index 01b05b293..41e989018 100644 --- a/typescript/infra/src/govern/multisend.ts +++ b/typescript/infra/src/govern/multisend.ts @@ -115,6 +115,7 @@ export class SafeMultiSend extends MultiSend { safeService, this.safeAddress, safeTransactionData, + true, ); await this.proposeSafeTransaction(safeSdk, safeService, safeTransaction); } diff --git a/typescript/infra/src/utils/safe.ts b/typescript/infra/src/utils/safe.ts index 512727493..47d851dc1 100644 --- a/typescript/infra/src/utils/safe.ts +++ b/typescript/infra/src/utils/safe.ts @@ -42,10 +42,12 @@ export async function createSafeTransaction( safeService: SafeApiKit.default, safeAddress: Address, safeTransactionData: MetaTransactionData[], + onlyCalls?: boolean, ): Promise { const nextNonce = await safeService.getNextNonce(safeAddress); return safeSdk.createTransaction({ safeTransactionData, + onlyCalls, options: { nonce: nextNonce }, }); } diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index d7bd4235a..36e3197c8 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -11,7 +11,7 @@ "@hyperlane-xyz/utils": "5.1.0", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", - "@safe-global/safe-deployments": "1.37.3", + "@safe-global/safe-deployments": "1.37.8", "@solana/spl-token": "^0.3.8", "@solana/web3.js": "^1.78.0", "@types/coingecko-api": "^1.0.10", diff --git a/typescript/sdk/src/utils/gnosisSafe.js b/typescript/sdk/src/utils/gnosisSafe.js index 148650e76..400931043 100644 --- a/typescript/sdk/src/utils/gnosisSafe.js +++ b/typescript/sdk/src/utils/gnosisSafe.js @@ -67,12 +67,10 @@ export async function getSafe(chain, multiProvider, safeAddress) { multiSend = getMultiSendDeployment({ version: multiSendVersion, network: domainId, - released: true, }); multiSendCallOnly = getMultiSendCallOnlyDeployment({ version: multiSendCallOnlyVersion, network: domainId, - released: true, }); } @@ -80,12 +78,13 @@ export async function getSafe(chain, multiProvider, safeAddress) { ethAdapter, safeAddress, contractNetworks: { + // DomainId == ChainId for EVM Chains [domainId]: { // Use the safe address for multiSendAddress and multiSendCallOnlyAddress - // if the contract is not deployed or if the version is not found - multiSendAddress: multiSend?.defaultAddress || safeAddress, + // if the contract is not deployed or if the version is not found. + multiSendAddress: multiSend?.networkAddresses[domainId] || safeAddress, multiSendCallOnlyAddress: - multiSendCallOnly?.defaultAddress || safeAddress, + multiSendCallOnly?.networkAddresses[domainId] || safeAddress, }, }, }); diff --git a/yarn.lock b/yarn.lock index 31d1ea72a..a2669136b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7814,7 +7814,7 @@ __metadata: "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" "@safe-global/protocol-kit": "npm:1.3.0" - "@safe-global/safe-deployments": "npm:1.37.3" + "@safe-global/safe-deployments": "npm:1.37.8" "@solana/spl-token": "npm:^0.3.8" "@solana/web3.js": "npm:^1.78.0" "@types/coingecko-api": "npm:^1.0.10" @@ -10788,12 +10788,12 @@ __metadata: languageName: node linkType: hard -"@safe-global/safe-deployments@npm:1.37.3": - version: 1.37.3 - resolution: "@safe-global/safe-deployments@npm:1.37.3" +"@safe-global/safe-deployments@npm:1.37.8": + version: 1.37.8 + resolution: "@safe-global/safe-deployments@npm:1.37.8" dependencies: semver: "npm:^7.6.2" - checksum: 3d1fcaac850a1d1100eaa5ff753c88c9bb889c678bb09248323c6b0c9d6228225a88be47973a89bb32829fe2d13ed17c21f854b9fdc29cc1b3c734021761f15c + checksum: bc8fce2c4d557e547a6cceebb611f9584d998dfb459cd50cf338409de986bed247ebca9425b0984a6e1a6accab42c7c4d1c68811e09cc981756183ba50a5e5a9 languageName: node linkType: hard From 87a0b377ffe9b4a025abf9be74ccf4f8886a673c Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:50:37 +0100 Subject: [PATCH 040/224] feat: USDC warp route config (Solana <> Eclipse) (#4430) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../warp-routes/eclipsesol/token-config.json | 2 +- .../warp-routes/eclipseusdc/program-ids.json | 14 +++++++++++ .../warp-routes/eclipseusdc/token-config.json | 23 +++++++++++++++++++ .../environments/mainnet3/gasPrices.json | 4 ++-- 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json index 7cff0b401..dfd9b9c98 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json @@ -9,7 +9,7 @@ "decimals": 9, "name": "Solana", "symbol": "SOL", - "uri": "https://github.com/hyperlane-xyz/hyperlane-registry/blob/b661127dd3dce5ea98b78ae0051fbd10c384b173/deployments/warp_routes/SOL/eclipse/metadata.json", + "uri": "https://github.com/hyperlane-xyz/hyperlane-registry/blob/33a13d304d3f08be79aad29ed47e7baeeea97db0/deployments/warp_routes/SOL/metadata.json", "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" } } diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json new file mode 100644 index 000000000..9a5d4f868 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json @@ -0,0 +1,14 @@ +{ + "solanamainnet": { + "hex": "0xd9aa20b2eb8965db1c5ac0af8608dd1f1e223838b4c0324767728a4a250f95cb", + "base58": "Fefw54S6NDdwNbPngPePvW4tiFTFQDT7gBPvFoDFeGqg" + }, + "ethereum": { + "hex": "0x000000000000000000000000fc8f5272d690cf19732a7ed6f246adf5fb8708db", + "base58": "1111111111114X5Wp5Z6aWk6v7FMSteKXMS6myvi" + }, + "eclipsemainnet": { + "hex": "0xb3c4dfa7156aada50e24f6e5c5630a246265ad2fd9a5856233481e8ed52c9f84", + "base58": "D6k6T3G74ij6atCtBiWBs5TbFa1hFVcrFUSGZHuV7q3Z" + } +} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json new file mode 100644 index 000000000..8d3579307 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json @@ -0,0 +1,23 @@ +{ + "solanamainnet": { + "type": "collateral", + "decimals": 6, + "interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF", + "token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "splTokenProgram": "token" + }, + "eclipsemainnet": { + "type": "synthetic", + "decimals": 6, + "name": "USD Coin", + "symbol": "USDC", + "uri": "https://github.com/hyperlane-xyz/hyperlane-registry/blob/33a13d304d3f08be79aad29ed47e7baeeea97db0/deployments/warp_routes/USDC/metadata.json", + "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" + }, + "ethereum": { + "type": "collateral", + "decimals": 6, + "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "foreignDeployment": "0xFc8F5272d690cf19732a7eD6f246aDF5fB8708dB" + } +} diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 3542719f7..01ea5465c 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -64,8 +64,8 @@ "decimals": 9 }, "eclipsemainnet": { - "amount": "0.001", - "decimals": 9 + "amount": "0.0000001", + "decimals": 1 }, "endurance": { "amount": "1.500000007", From 728f5de4589e9d6edecdcff2f2b252c1c41fa0b3 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Wed, 18 Sep 2024 12:35:49 +0100 Subject: [PATCH 041/224] chore: update SVM ISMs (#4509) ### Description - Updates the enrolled sets on the default ISMs of eclipsemainnet and solanamainnet ### Drive-by changes - stopped reading `type` completely for the multisig ISM configs -- this isn't needed whatsoever and caused issues bc the sealevel tooling would expect a number but infra would generate a string w/ the ISM type name - to support string chain_ids (the case on Cosmos), added some logic - removed `testnet3`, not needed anymore ### Related issues ### Backward compatibility ### Testing --- rust/sealevel/client/src/multisig_ism.rs | 6 +- rust/sealevel/client/src/router.rs | 17 +- .../environments/mainnet3/chain-config.json | 96 ++++++++- .../hyperlane/multisig-config.json | 123 ++++++++--- .../hyperlane/multisig-config.json | 122 ++++++++--- .../environments/testnet3/chain-config.json | 196 ------------------ .../testnet3/gas-oracle-configs.json | 20 -- .../hyperlane/helloworld-config.json | 20 -- ...ane_sealevel_hello_world-solanadevnet.json | 1 - .../helloworld/hyperlane/program-ids.json | 26 --- .../helloworld/rc/helloworld-config.json | 20 -- ...ane_sealevel_hello_world-solanadevnet.json | 1 - .../testnet3/helloworld/rc/program-ids.json | 26 --- .../hyperlane/multisig-config.json | 56 ----- ...level_multisig_ism_message_id-keypair.json | 1 - .../solanadevnet/rc/multisig-config.json | 27 --- .../solanadevnet/rc/program-ids.json | 3 - .../keys/hyperlane_sealevel_igp-keypair.json | 1 - .../hyperlane_sealevel_mailbox-keypair.json | 1 - ...level_multisig_ism_message_id-keypair.json | 1 - ...e_sealevel_validator_announce-keypair.json | 1 - .../solanadevnet/core/program-ids.json | 8 - ...ealevel_token_collateral-solanadevnet.json | 1 - .../collateraltest/program-ids.json | 10 - .../collateraltest/token-config.json | 17 -- ...ne_sealevel_token_native-solanadevnet.json | 1 - .../warp-routes/nativetest/program-ids.json | 10 - .../warp-routes/nativetest/token-config.json | 13 -- ...ealevel_token_collateral-solanadevnet.json | 1 - .../warp-routes/proteustest/program-ids.json | 14 -- .../warp-routes/proteustest/token-config.json | 22 -- 31 files changed, 297 insertions(+), 565 deletions(-) delete mode 100644 rust/sealevel/environments/testnet3/chain-config.json delete mode 100644 rust/sealevel/environments/testnet3/gas-oracle-configs.json delete mode 100644 rust/sealevel/environments/testnet3/helloworld/hyperlane/helloworld-config.json delete mode 100644 rust/sealevel/environments/testnet3/helloworld/hyperlane/keys/hyperlane_sealevel_hello_world-solanadevnet.json delete mode 100644 rust/sealevel/environments/testnet3/helloworld/hyperlane/program-ids.json delete mode 100644 rust/sealevel/environments/testnet3/helloworld/rc/helloworld-config.json delete mode 100644 rust/sealevel/environments/testnet3/helloworld/rc/keys/hyperlane_sealevel_hello_world-solanadevnet.json delete mode 100644 rust/sealevel/environments/testnet3/helloworld/rc/program-ids.json delete mode 100644 rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/hyperlane/multisig-config.json delete mode 100644 rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json delete mode 100644 rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/multisig-config.json delete mode 100644 rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/program-ids.json delete mode 100644 rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_igp-keypair.json delete mode 100644 rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_mailbox-keypair.json delete mode 100644 rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json delete mode 100644 rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_validator_announce-keypair.json delete mode 100644 rust/sealevel/environments/testnet3/solanadevnet/core/program-ids.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/collateraltest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/collateraltest/program-ids.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/collateraltest/token-config.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/nativetest/keys/hyperlane_sealevel_token_native-solanadevnet.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/nativetest/program-ids.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/nativetest/token-config.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/proteustest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/proteustest/program-ids.json delete mode 100644 rust/sealevel/environments/testnet3/warp-routes/proteustest/token-config.json diff --git a/rust/sealevel/client/src/multisig_ism.rs b/rust/sealevel/client/src/multisig_ism.rs index 8911bedfc..9f1f2c5c8 100644 --- a/rust/sealevel/client/src/multisig_ism.rs +++ b/rust/sealevel/client/src/multisig_ism.rs @@ -27,8 +27,10 @@ pub(crate) struct MultisigIsmConfig { /// Note this type is ignored in this tooling. It'll always assume this /// relates to a multisig-ism-message-id variant, which is the only type /// implemented in Sealevel. - #[serde(rename = "type")] - pub module_type: u8, + /// Commenting out for now until this is needed, and due to `infra` + /// generating non-numeric types at the moment. + // #[serde(rename = "type")] + // pub module_type: u8, pub validators: Vec, pub threshold: u8, } diff --git a/rust/sealevel/client/src/router.rs b/rust/sealevel/client/src/router.rs index c2826f240..ad7ee3695 100644 --- a/rust/sealevel/client/src/router.rs +++ b/rust/sealevel/client/src/router.rs @@ -111,7 +111,8 @@ pub struct RpcUrlConfig { #[derive(Debug, Deserialize, Serialize, Clone)] #[serde(rename_all = "camelCase")] pub struct ChainMetadata { - chain_id: u32, + // Can be a string or a number + chain_id: serde_json::Value, /// Hyperlane domain, only required if differs from id above domain_id: Option, name: String, @@ -125,7 +126,19 @@ impl ChainMetadata { } pub fn domain_id(&self) -> u32 { - self.domain_id.unwrap_or(self.chain_id) + self.domain_id.unwrap_or_else(|| { + // Try to parse as a number, otherwise panic, as the domain ID must + // be specified if the chain id is not a number. + self.chain_id + .as_u64() + .and_then(|v| v.try_into().ok()) + .unwrap_or_else(|| { + panic!( + "Unable to get domain ID for chain {:?}: domain_id is undefined and could not fall back to chain_id {:?}", + self.name, self.chain_id + ) + }) + }) } } diff --git a/rust/sealevel/environments/mainnet3/chain-config.json b/rust/sealevel/environments/mainnet3/chain-config.json index 363b99621..e21c91ccc 100644 --- a/rust/sealevel/environments/mainnet3/chain-config.json +++ b/rust/sealevel/environments/mainnet3/chain-config.json @@ -647,6 +647,14 @@ ] }, "eclipsemainnet": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.eclipse.xyz/api", + "family": "other", + "name": "Eclipse Explorer", + "url": "https://explorer.eclipse.xyz/" + } + ], "blocks": { "confirmations": 1, "estimateBlockTime": 0.4, @@ -758,6 +766,45 @@ "maxPriorityFeePerGas": 5000000000 } }, + "everclear": { + "blockExplorers": [ + { + "apiUrl": "https://everclear.cloud.blockscout.com/api", + "family": "blockscout", + "name": "Everclear Explorer", + "url": "https://everclear.cloud.blockscout.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 0 + }, + "chainId": 25327, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Everclear", + "domainId": 25327, + "gasCurrencyCoinGeckoId": "ethereum", + "index": { + "from": 37 + }, + "name": "everclear", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.everclear.raas.gelato.cloud" + } + ], + "technicalStack": "arbitrumnitro" + }, "flare": { "blockExplorers": [ { @@ -977,7 +1024,7 @@ "estimateBlockTime": 1, "reorgPeriod": 10 }, - "chainId": 6909546, + "chainId": "injective-1", "deployer": { "name": "Abacus Works", "url": "https://www.hyperlane.xyz" @@ -1497,7 +1544,7 @@ "estimateBlockTime": 3, "reorgPeriod": 1 }, - "chainId": 1853125230, + "chainId": "neutron-1", "deployer": { "name": "Abacus Works", "url": "https://www.hyperlane.xyz" @@ -1537,6 +1584,41 @@ "gasPrice": "0.0075" } }, + "oortmainnet": { + "blockExplorers": [ + { + "apiUrl": "https://mainnet-scan.oortech.com/api", + "family": "other", + "name": "Oort Olympus Explorer", + "url": "https://mainnet-scan.oortech.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 0 + }, + "chainId": 970, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Oort", + "domainId": 970, + "gasCurrencyCoinGeckoId": "oort", + "name": "oortmainnet", + "nativeToken": { + "decimals": 18, + "name": "Oort", + "symbol": "OORT" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet-rpc.oortech.com" + } + ] + }, "optimism": { "blockExplorers": [ { @@ -1588,7 +1670,7 @@ "estimateBlockTime": 3, "reorgPeriod": 1 }, - "chainId": 875, + "chainId": "osmosis-1", "deployer": { "name": "Mitosis", "url": "https://mitosis.org" @@ -1646,13 +1728,13 @@ }, "displayName": "Polygon", "domainId": 137, - "gasCurrencyCoinGeckoId": "matic-network", + "gasCurrencyCoinGeckoId": "polygon-ecosystem-token", "gnosisSafeTransactionServiceUrl": "https://safe-transaction-polygon.safe.global/", "name": "polygon", "nativeToken": { "decimals": 18, - "name": "Matic", - "symbol": "MATIC" + "name": "Polygon Ecosystem Token", + "symbol": "POL" }, "protocol": "ethereum", "rpcUrls": [ @@ -1879,7 +1961,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 1 + "reorgPeriod": 30 }, "chainId": 534352, "deployer": { diff --git a/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json b/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json index d6e5aae1d..595a33b03 100644 --- a/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json +++ b/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json @@ -20,13 +20,21 @@ "type": 3 }, "astar": { - "threshold": 1, - "validators": ["0x4d1b2cade01ee3493f44304653d8e352c66ec3e7"], + "threshold": 2, + "validators": [ + "0x4d1b2cade01ee3493f44304653d8e352c66ec3e7", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "astarzkevm": { - "threshold": 1, - "validators": ["0x89ecdd6caf138934bf3a2fb7b323984d72fd66de"], + "threshold": 2, + "validators": [ + "0x89ecdd6caf138934bf3a2fb7b323984d72fd66de", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "avalanche": { @@ -50,8 +58,12 @@ "type": 3 }, "bitlayer": { - "threshold": 1, - "validators": ["0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f"], + "threshold": 2, + "validators": [ + "0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "blast": { @@ -102,8 +114,12 @@ "type": 3 }, "coredao": { - "threshold": 1, - "validators": ["0xbd6e158a3f5830d99d7d2bce192695bc4a148de2"], + "threshold": 2, + "validators": [ + "0xbd6e158a3f5830d99d7d2bce192695bc4a148de2", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "cyber": { @@ -125,8 +141,12 @@ "type": 3 }, "dogechain": { - "threshold": 1, - "validators": ["0xe43f742c37858746e6d7e458bc591180d0cba440"], + "threshold": 2, + "validators": [ + "0xe43f742c37858746e6d7e458bc591180d0cba440", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "endurance": { @@ -151,16 +171,30 @@ ], "type": 3 }, + "everclear": { + "threshold": 2, + "validators": [ + "0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0xD79DFbF56ee2268f061cc613027a44A880f61Ba2" + ], + "type": 3 + }, "flare": { - "threshold": 1, - "validators": ["0xb65e52be342dba3ab2c088ceeb4290c744809134"], + "threshold": 2, + "validators": [ + "0xb65e52be342dba3ab2c088ceeb4290c744809134", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "fraxtal": { "threshold": 2, "validators": [ "0x4bce180dac6da60d0f3a2bdf036ffe9004f944c1", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x25b3a88f7cfd3c9f7d7e32b295673a16a6ddbd91" ], "type": 3 }, @@ -232,7 +266,8 @@ "threshold": 2, "validators": [ "0xa5e953701dcddc5b958b5defb677a829d908df6d", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x101cE77261245140A0871f9407d6233C8230Ec47" ], "type": 3 }, @@ -286,16 +321,22 @@ "type": 3 }, "mode": { - "threshold": 2, + "threshold": 3, "validators": [ "0x7eb2e1920a4166c19d6884c1cec3d2cf356fc9b7", - "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36", + "0x7e29608c6e5792bbf9128599ca309be0728af7b4", + "0x101cE77261245140A0871f9407d6233C8230Ec47" ], "type": 3 }, "molten": { - "threshold": 1, - "validators": ["0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f"], + "threshold": 2, + "validators": [ + "0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "moonbeam": { @@ -321,6 +362,15 @@ ], "type": 3 }, + "oortmainnet": { + "threshold": 2, + "validators": [ + "0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36", + "0x032dE4f94676bF9314331e7D83E8Db4aC74c9E21" + ], + "type": 3 + }, "optimism": { "threshold": 3, "validators": [ @@ -334,7 +384,9 @@ }, "osmosis": { "threshold": 1, - "validators": ["0xea483af11c19fa41b16c31d1534c2a486a92bcac"], + "validators": [ + "0xea483af11c19fa41b16c31d1534c2a486a92bcac" + ], "type": 3 }, "polygon": { @@ -378,7 +430,8 @@ "threshold": 2, "validators": [ "0x1400b9737007f7978d8b4bbafb4a69c83f0641a7", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], "type": 3 }, @@ -402,21 +455,33 @@ "type": 3 }, "sei": { - "threshold": 2, + "threshold": 3, "validators": [ "0x9920d2dbf6c85ffc228fdc2e810bf895732c6aa5", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x101cE77261245140A0871f9407d6233C8230Ec47", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], "type": 3 }, "shibarium": { - "threshold": 1, - "validators": ["0xfa33391ee38597cbeef72ccde8c9e13e01e78521"], + "threshold": 2, + "validators": [ + "0xfa33391ee38597cbeef72ccde8c9e13e01e78521", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "solanamainnet": { - "threshold": 1, - "validators": ["0x28464752829b3ea59a497fca0bdff575c534c3ff"], + "threshold": 3, + "validators": [ + "0x28464752829b3ea59a497fca0bdff575c534c3ff", + "0x2b7514a2f77bd86bbf093fe6bb67d8611f51c659", + "0xd90ea26ff731d967c5ea660851f7d63cb04ab820", + "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", + "0xcb6bcbd0de155072a7ff486d9d7286b0f71dcc2d" + ], "type": 3 }, "taiko": { @@ -475,10 +540,12 @@ "type": 3 }, "zetachain": { - "threshold": 2, + "threshold": 3, "validators": [ "0xa3bca0b80317dbf9c7dce16a16ac89f4ff2b23ef", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x101cE77261245140A0871f9407d6233C8230Ec47", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], "type": 3 }, diff --git a/rust/sealevel/environments/mainnet3/multisig-ism-message-id/solanamainnet/hyperlane/multisig-config.json b/rust/sealevel/environments/mainnet3/multisig-ism-message-id/solanamainnet/hyperlane/multisig-config.json index c82bf6eb8..7ae8ee840 100644 --- a/rust/sealevel/environments/mainnet3/multisig-ism-message-id/solanamainnet/hyperlane/multisig-config.json +++ b/rust/sealevel/environments/mainnet3/multisig-ism-message-id/solanamainnet/hyperlane/multisig-config.json @@ -20,13 +20,21 @@ "type": 3 }, "astar": { - "threshold": 1, - "validators": ["0x4d1b2cade01ee3493f44304653d8e352c66ec3e7"], + "threshold": 2, + "validators": [ + "0x4d1b2cade01ee3493f44304653d8e352c66ec3e7", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "astarzkevm": { - "threshold": 1, - "validators": ["0x89ecdd6caf138934bf3a2fb7b323984d72fd66de"], + "threshold": 2, + "validators": [ + "0x89ecdd6caf138934bf3a2fb7b323984d72fd66de", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "avalanche": { @@ -50,8 +58,12 @@ "type": 3 }, "bitlayer": { - "threshold": 1, - "validators": ["0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f"], + "threshold": 2, + "validators": [ + "0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "blast": { @@ -102,8 +114,12 @@ "type": 3 }, "coredao": { - "threshold": 1, - "validators": ["0xbd6e158a3f5830d99d7d2bce192695bc4a148de2"], + "threshold": 2, + "validators": [ + "0xbd6e158a3f5830d99d7d2bce192695bc4a148de2", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "cyber": { @@ -125,13 +141,22 @@ "type": 3 }, "dogechain": { - "threshold": 1, - "validators": ["0xe43f742c37858746e6d7e458bc591180d0cba440"], + "threshold": 2, + "validators": [ + "0xe43f742c37858746e6d7e458bc591180d0cba440", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "eclipsemainnet": { - "threshold": 1, - "validators": ["0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0"], + "threshold": 3, + "validators": [ + "0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0", + "0x3571223e745dc0fcbdefa164c9b826b90c0d2dac", + "0xea83086a62617a7228ce4206fae2ea8b0ab23513", + "0x4d4629f5bfeabe66edc7a78da26ef5273c266f97" + ], "type": 3 }, "endurance": { @@ -156,16 +181,30 @@ ], "type": 3 }, + "everclear": { + "threshold": 2, + "validators": [ + "0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0xD79DFbF56ee2268f061cc613027a44A880f61Ba2" + ], + "type": 3 + }, "flare": { - "threshold": 1, - "validators": ["0xb65e52be342dba3ab2c088ceeb4290c744809134"], + "threshold": 2, + "validators": [ + "0xb65e52be342dba3ab2c088ceeb4290c744809134", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "fraxtal": { "threshold": 2, "validators": [ "0x4bce180dac6da60d0f3a2bdf036ffe9004f944c1", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x25b3a88f7cfd3c9f7d7e32b295673a16a6ddbd91" ], "type": 3 }, @@ -237,7 +276,8 @@ "threshold": 2, "validators": [ "0xa5e953701dcddc5b958b5defb677a829d908df6d", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x101cE77261245140A0871f9407d6233C8230Ec47" ], "type": 3 }, @@ -291,16 +331,22 @@ "type": 3 }, "mode": { - "threshold": 2, + "threshold": 3, "validators": [ "0x7eb2e1920a4166c19d6884c1cec3d2cf356fc9b7", - "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36", + "0x7e29608c6e5792bbf9128599ca309be0728af7b4", + "0x101cE77261245140A0871f9407d6233C8230Ec47" ], "type": 3 }, "molten": { - "threshold": 1, - "validators": ["0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f"], + "threshold": 2, + "validators": [ + "0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "moonbeam": { @@ -326,6 +372,15 @@ ], "type": 3 }, + "oortmainnet": { + "threshold": 2, + "validators": [ + "0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36", + "0x032dE4f94676bF9314331e7D83E8Db4aC74c9E21" + ], + "type": 3 + }, "optimism": { "threshold": 3, "validators": [ @@ -339,7 +394,9 @@ }, "osmosis": { "threshold": 1, - "validators": ["0xea483af11c19fa41b16c31d1534c2a486a92bcac"], + "validators": [ + "0xea483af11c19fa41b16c31d1534c2a486a92bcac" + ], "type": 3 }, "polygon": { @@ -383,7 +440,8 @@ "threshold": 2, "validators": [ "0x1400b9737007f7978d8b4bbafb4a69c83f0641a7", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], "type": 3 }, @@ -407,16 +465,22 @@ "type": 3 }, "sei": { - "threshold": 2, + "threshold": 3, "validators": [ "0x9920d2dbf6c85ffc228fdc2e810bf895732c6aa5", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x101cE77261245140A0871f9407d6233C8230Ec47", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], "type": 3 }, "shibarium": { - "threshold": 1, - "validators": ["0xfa33391ee38597cbeef72ccde8c9e13e01e78521"], + "threshold": 2, + "validators": [ + "0xfa33391ee38597cbeef72ccde8c9e13e01e78521", + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], "type": 3 }, "taiko": { @@ -475,10 +539,12 @@ "type": 3 }, "zetachain": { - "threshold": 2, + "threshold": 3, "validators": [ "0xa3bca0b80317dbf9c7dce16a16ac89f4ff2b23ef", - "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" + "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", + "0x101cE77261245140A0871f9407d6233C8230Ec47", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], "type": 3 }, diff --git a/rust/sealevel/environments/testnet3/chain-config.json b/rust/sealevel/environments/testnet3/chain-config.json deleted file mode 100644 index 5b278c0a0..000000000 --- a/rust/sealevel/environments/testnet3/chain-config.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "alfajores": { - "chainId": 44787, - "domainId": 44787, - "name": "alfajores", - "protocol": "ethereum", - "displayName": "Alfajores", - "nativeToken": { - "decimals": 18, - "name": "CELO", - "symbol": "CELO" - }, - "rpcUrls": [ - { - "http": "https://alfajores-forno.celo-testnet.org" - } - ], - "blockExplorers": [ - { - "name": "CeloScan", - "url": "https://alfajores.celoscan.io", - "apiUrl": "https://api-alfajores.celoscan.io/api", - "family": "etherscan" - }, - { - "name": "Blockscout", - "url": "https://explorer.celo.org/alfajores", - "apiUrl": "https://explorer.celo.org/alfajores/api", - "family": "blockscout" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 0, - "estimateBlockTime": 5 - }, - "isTestnet": true - }, - "fuji": { - "chainId": 43113, - "domainId": 43113, - "name": "fuji", - "protocol": "ethereum", - "displayName": "Fuji", - "nativeToken": { - "decimals": 18, - "name": "Avalanche", - "symbol": "AVAX" - }, - "rpcUrls": [ - { - "http": "https://api.avax-test.network/ext/bc/C/rpc", - "pagination": { - "maxBlockRange": 2048 - } - } - ], - "blockExplorers": [ - { - "name": "SnowTrace", - "url": "https://testnet.snowtrace.io", - "apiUrl": "https://api-testnet.snowtrace.io/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 3, - "reorgPeriod": 3, - "estimateBlockTime": 2 - }, - "isTestnet": true - }, - "bsctestnet": { - "chainId": 97, - "domainId": 97, - "name": "bsctestnet", - "protocol": "ethereum", - "displayName": "BSC Testnet", - "nativeToken": { - "decimals": 18, - "name": "BNB", - "symbol": "BNB" - }, - "rpcUrls": [ - { - "http": "https://data-seed-prebsc-1-s3.binance.org:8545" - } - ], - "blockExplorers": [ - { - "name": "BscScan", - "url": "https://testnet.bscscan.com", - "apiUrl": "https://api-testnet.bscscan.com/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 9, - "estimateBlockTime": 3 - }, - "isTestnet": true - }, - "moonbasealpha": { - "chainId": 1287, - "domainId": 1287, - "name": "moonbasealpha", - "protocol": "ethereum", - "displayName": "Moonbase Alpha", - "displayNameShort": "Moonbase", - "nativeToken": { - "decimals": 18, - "name": "DEV", - "symbol": "DEV" - }, - "rpcUrls": [ - { - "http": "https://rpc.api.moonbase.moonbeam.network" - } - ], - "blockExplorers": [ - { - "name": "MoonScan", - "url": "https://moonbase.moonscan.io", - "apiUrl": "https://api-moonbase.moonscan.io/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 1, - "estimateBlockTime": 12 - }, - "isTestnet": true - }, - "sepolia": { - "chainId": 11155111, - "domainId": 11155111, - "name": "sepolia", - "protocol": "ethereum", - "displayName": "Sepolia", - "nativeToken": { - "name": "Ether", - "symbol": "ETH", - "decimals": 18 - }, - "rpcUrls": [ - { - "http": "https://endpoints.omniatech.io/v1/eth/sepolia/public" - }, - { - "http": "https://rpc.sepolia.org" - } - ], - "blockExplorers": [ - { - "name": "Etherscan", - "url": "https://sepolia.etherscan.io", - "apiUrl": "https://api-sepolia.etherscan.io/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 2, - "estimateBlockTime": 13 - }, - "isTestnet": true - }, - "solanadevnet": { - "chainId": 1399811151, - "name": "solanadevnet", - "rpcUrls": [ - { - "http": "https://api.devnet.solana.com" - } - ] - }, - "proteustestnet": { - "chainId": 88002, - "domainId": 88002, - "name": "proteustestnet", - "protocol": "ethereum", - "displayName": "Proteus Testnet", - "nativeToken": { - "name": "Zebec", - "symbol": "ZBC", - "decimals": 18 - }, - "rpcUrls": [ - { - "http": "https://api.proteus.nautchain.xyz/solana" - } - ] - } -} diff --git a/rust/sealevel/environments/testnet3/gas-oracle-configs.json b/rust/sealevel/environments/testnet3/gas-oracle-configs.json deleted file mode 100644 index 093327911..000000000 --- a/rust/sealevel/environments/testnet3/gas-oracle-configs.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "domain": 97, - "gasOracle": { - "type": "remoteGasData", - "tokenExchangeRate": "10000000000000000000", - "gasPrice": "15000000000", - "tokenDecimals": 18 - } - }, - { - "domain": 88002, - "gasOracle": { - "type": "remoteGasData", - "tokenExchangeRate": "10000000000000000000", - "gasPrice": "1000000000", - "tokenDecimals": 18 - } - } -] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/helloworld/hyperlane/helloworld-config.json b/rust/sealevel/environments/testnet3/helloworld/hyperlane/helloworld-config.json deleted file mode 100644 index 425a8209e..000000000 --- a/rust/sealevel/environments/testnet3/helloworld/hyperlane/helloworld-config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "solanadevnet": { - "interchainSecurityModule": "64xkGhsZbxgP5rBJfpPcpmzkzTGkpSVHiDLcMKS5gmQw" - }, - "alfajores": { - "foreignDeployment": "0x477D860f8F41bC69dDD32821F2Bf2C2Af0243F16" - }, - "fuji": { - "foreignDeployment": "0x5da3b8d6F73dF6003A490072106730218c475AAd" - }, - "bsctestnet": { - "foreignDeployment": "0xE09BF59dCA6e622efC33f6fbd8EF85dE45233388" - }, - "moonbasealpha": { - "foreignDeployment": "0x89e02C3C7b97bCBa63279E10E2a44e6cEF69E6B2" - }, - "sepolia": { - "foreignDeployment": "0x5d56B8a669F50193b54319442c6EEE5edD662381" - } -} diff --git a/rust/sealevel/environments/testnet3/helloworld/hyperlane/keys/hyperlane_sealevel_hello_world-solanadevnet.json b/rust/sealevel/environments/testnet3/helloworld/hyperlane/keys/hyperlane_sealevel_hello_world-solanadevnet.json deleted file mode 100644 index db75227a7..000000000 --- a/rust/sealevel/environments/testnet3/helloworld/hyperlane/keys/hyperlane_sealevel_hello_world-solanadevnet.json +++ /dev/null @@ -1 +0,0 @@ -[42,226,42,33,87,42,251,0,57,248,173,166,139,84,91,50,218,150,183,254,74,195,88,116,92,195,145,231,63,39,9,98,171,58,146,166,209,139,158,82,151,114,58,235,5,25,129,244,219,192,239,35,53,229,191,115,243,59,174,210,94,26,161,101] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/helloworld/hyperlane/program-ids.json b/rust/sealevel/environments/testnet3/helloworld/hyperlane/program-ids.json deleted file mode 100644 index fc338a6fb..000000000 --- a/rust/sealevel/environments/testnet3/helloworld/hyperlane/program-ids.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "bsctestnet": { - "hex": "0x000000000000000000000000e09bf59dca6e622efc33f6fbd8ef85de45233388", - "base58": "11111111111148VaL9DFuVc9DbDjRR7c3qyCEjyy" - }, - "fuji": { - "hex": "0x0000000000000000000000005da3b8d6f73df6003a490072106730218c475aad", - "base58": "1111111111112JfXZf7EYaEMM1st6wFZbcLN2uwA" - }, - "solanadevnet": { - "hex": "0xab3a92a6d18b9e5297723aeb051981f4dbc0ef2335e5bf73f33baed25e1aa165", - "base58": "CXQX54kdkU5GqdRJjCmHpwHfEMgFb5SeBmMWntP2Ds7J" - }, - "alfajores": { - "hex": "0x000000000000000000000000477d860f8f41bc69ddd32821f2bf2c2af0243f16", - "base58": "111111111111zmUjMVNXAe5bcqPR8cvaPz5SrQu" - }, - "sepolia": { - "hex": "0x0000000000000000000000005d56b8a669f50193b54319442c6eee5edd662381", - "base58": "1111111111112JRRxgtLh6eyMDsTHUehn6bJcPJ8" - }, - "moonbasealpha": { - "hex": "0x00000000000000000000000089e02c3c7b97bcba63279e10e2a44e6cef69e6b2", - "base58": "1111111111112vQhuwgKwhQ7SM1HZEm6yXQkzCau" - } -} diff --git a/rust/sealevel/environments/testnet3/helloworld/rc/helloworld-config.json b/rust/sealevel/environments/testnet3/helloworld/rc/helloworld-config.json deleted file mode 100644 index 0af4a8161..000000000 --- a/rust/sealevel/environments/testnet3/helloworld/rc/helloworld-config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "solanadevnet": { - "interchainSecurityModule": "2NE6Y1rXp1Kpp6vBNqDHYL7HNk7iqh8BKmvCoZtUcZLn" - }, - "alfajores": { - "foreignDeployment": "0x40Adcb03F3C58170b4751c4140636FC6085Ff475" - }, - "fuji": { - "foreignDeployment": "0xAc003FcDD0EE223664F2A000B5A59D082745700b" - }, - "bsctestnet": { - "foreignDeployment": "0xd259b0e793535325786675542aB296c451535c27" - }, - "moonbasealpha": { - "foreignDeployment": "0xE9D6317a10860340f035f3d09052D9d376855bE8" - }, - "sepolia": { - "foreignDeployment": "0x6AD4DEBA8A147d000C09de6465267a9047d1c217" - } -} diff --git a/rust/sealevel/environments/testnet3/helloworld/rc/keys/hyperlane_sealevel_hello_world-solanadevnet.json b/rust/sealevel/environments/testnet3/helloworld/rc/keys/hyperlane_sealevel_hello_world-solanadevnet.json deleted file mode 100644 index 341933a08..000000000 --- a/rust/sealevel/environments/testnet3/helloworld/rc/keys/hyperlane_sealevel_hello_world-solanadevnet.json +++ /dev/null @@ -1 +0,0 @@ -[158,232,241,234,223,84,236,122,65,31,146,220,11,236,43,97,184,113,181,80,237,157,204,188,166,199,112,171,77,38,68,13,187,162,244,131,230,66,68,157,10,57,239,229,249,96,63,124,85,148,35,172,235,211,200,84,208,117,96,204,208,67,146,40] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/helloworld/rc/program-ids.json b/rust/sealevel/environments/testnet3/helloworld/rc/program-ids.json deleted file mode 100644 index 305c614b9..000000000 --- a/rust/sealevel/environments/testnet3/helloworld/rc/program-ids.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "sepolia": { - "hex": "0x0000000000000000000000006ad4deba8a147d000c09de6465267a9047d1c217", - "base58": "1111111111112VKnX2KMsqSTDw9YoXRsZJTwTcUW" - }, - "solanadevnet": { - "hex": "0xbba2f483e642449d0a39efe5f9603f7c559423acebd3c854d07560ccd0439228", - "base58": "DdTMkk9nuqH5LnD56HLkPiKMV3yB3BNEYSQfgmJHa5i7" - }, - "fuji": { - "hex": "0x000000000000000000000000ac003fcdd0ee223664f2a000b5a59d082745700b", - "base58": "1111111111113Pz2bmxxVNgkKkZPpxgouHiZAjTx" - }, - "moonbasealpha": { - "hex": "0x000000000000000000000000e9d6317a10860340f035f3d09052d9d376855be8", - "base58": "1111111111114Fx2onL6wvVgGmyjgzGhy48HzCZM" - }, - "bsctestnet": { - "hex": "0x000000000000000000000000d259b0e793535325786675542ab296c451535c27", - "base58": "1111111111113vyKMMTb6aSQDhDLqEvqcPBcTtRC" - }, - "alfajores": { - "hex": "0x00000000000000000000000040adcb03f3c58170b4751c4140636fc6085ff475", - "base58": "111111111111uGFbQYrmpk8K5cfeu9x438LAGiQ" - }, -} diff --git a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/hyperlane/multisig-config.json b/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/hyperlane/multisig-config.json deleted file mode 100644 index 1f21eb8ce..000000000 --- a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/hyperlane/multisig-config.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "alfajores": { - "type": 3, - "threshold": 2, - "validators": [ - "0xe6072396568e73ce6803b12b7e04164e839f1e54", - "0x9f177f51289b22515f41f95872e1511391b8e105", - "0x15f77400845eb1c971ad08de050861d5508cad6c" - ] - }, - "fuji": { - "type": 3, - "threshold": 2, - "validators": [ - "0x9fa19ead5ec76e437948b35e227511b106293c40", - "0x227e7d6507762ece0c94678f8c103eff9d682476", - "0x2379e43740e4aa4fde48cf4f00a3106df1d8420d" - ] - }, - "bsctestnet": { - "type": 3, - "threshold": 2, - "validators": [ - "0x23338c8714976dd4a57eaeff17cbd26d7e275c08", - "0x85a618d7450ebc37e0d682371f08dac94eec7a76", - "0x95b76562e4ba1791a27ba4236801271c9115b141" - ] - }, - "sepolia": { - "type": 3, - "threshold": 2, - "validators": [ - "0xbc748ee311f5f2d1975d61cdf531755ce8ce3066", - "0xc4233b2bfe5aec08964a94b403052abb3eafcf07", - "0x6b36286c19f5c10bdc139ea9ee7f82287303f61d" - ] - }, - "moonbasealpha": { - "type": 3, - "threshold": 2, - "validators": [ - "0x890c2aeac157c3f067f3e42b8afc797939c59a32", - "0x1b06d6fe69b972ed7420c83599d5a5c0fc185904", - "0xe70b85206a968a99a597581f0fa09c99e7681093" - ] - }, - "proteustestnet": { - "type": 3, - "threshold": 2, - "validators": [ - "0x79fc73656abb9eeaa5ee853c4569124f5bdaf9d8", - "0x72840388d5ab57323bc4f6e6d3ddedfd5cc911f0", - "0xd4b2a50c53fc6614bb3cd3198e0fdc03f5da973f" - ] - } -} diff --git a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json b/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json deleted file mode 100644 index 8542855f6..000000000 --- a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json +++ /dev/null @@ -1 +0,0 @@ -[187,239,78,162,24,178,190,184,243,9,66,169,19,139,40,129,55,222,218,2,184,14,122,68,163,6,144,157,76,14,169,237,20,75,176,226,241,81,96,106,31,68,222,130,94,67,105,175,112,84,241,60,117,11,107,135,95,48,20,213,115,123,100,3] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/multisig-config.json b/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/multisig-config.json deleted file mode 100644 index 59851ab71..000000000 --- a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/multisig-config.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "alfajores": { - "type": 3, - "threshold": 1, - "validators": ["0x45e5c228b38e1cf09e9a3423ed0cf4862c4bf3de"] - }, - "fuji": { - "type": 3, - "threshold": 1, - "validators": ["0xd81ba169170a9b582812cf0e152d2c168572e21f"] - }, - "bsctestnet": { - "type": 3, - "threshold": 1, - "validators": ["0x77f80ef5b18977e15d81aea8dd3a88e7df4bc0eb"] - }, - "sepolia": { - "type": 3, - "threshold": 1, - "validators": ["0x183f15924f3a464c54c9393e8d268eb44d2b208c"] - }, - "moonbasealpha": { - "type": 3, - "threshold": 1, - "validators": ["0xbeaf158f85d7b64ced36b8aea0bbc4cd0f2d1a5d"] - } -} diff --git a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/program-ids.json b/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/program-ids.json deleted file mode 100644 index e615b252e..000000000 --- a/rust/sealevel/environments/testnet3/multisig-ism-message-id/solanadevnet/rc/program-ids.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "program_id": "2NE6Y1rXp1Kpp6vBNqDHYL7HNk7iqh8BKmvCoZtUcZLn" -} \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_igp-keypair.json b/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_igp-keypair.json deleted file mode 100644 index dc81bbd76..000000000 --- a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_igp-keypair.json +++ /dev/null @@ -1 +0,0 @@ -[69,85,36,249,122,60,137,0,166,230,31,176,52,206,13,94,109,64,6,255,11,230,27,197,206,56,53,158,119,12,119,62,252,44,216,245,197,34,23,174,214,41,164,131,127,248,232,97,32,106,180,79,142,12,207,167,241,75,125,139,200,78,190,177] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_mailbox-keypair.json b/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_mailbox-keypair.json deleted file mode 100644 index 1d037e6a7..000000000 --- a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_mailbox-keypair.json +++ /dev/null @@ -1 +0,0 @@ -[41,66,119,0,251,5,86,239,146,22,239,71,92,242,131,74,187,171,216,223,119,184,174,19,60,191,221,113,245,239,17,122,58,40,14,132,102,210,107,196,225,165,211,209,126,115,247,179,7,192,130,21,109,208,255,191,140,95,154,231,85,6,214,241] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json b/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json deleted file mode 100644 index d86f1638c..000000000 --- a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_multisig_ism_message_id-keypair.json +++ /dev/null @@ -1 +0,0 @@ -[247,149,169,2,196,128,74,124,111,206,244,112,63,16,180,19,219,212,45,229,21,114,33,11,202,148,12,47,22,26,192,78,75,78,53,149,190,51,57,253,29,141,136,215,159,45,181,164,239,148,140,163,30,108,158,76,94,113,11,4,142,0,192,20] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_validator_announce-keypair.json b/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_validator_announce-keypair.json deleted file mode 100644 index 5ddd8b30e..000000000 --- a/rust/sealevel/environments/testnet3/solanadevnet/core/keys/hyperlane_sealevel_validator_announce-keypair.json +++ /dev/null @@ -1 +0,0 @@ -[68,92,27,29,32,175,172,214,16,253,88,245,2,84,255,5,186,178,191,163,136,96,18,168,23,83,232,216,205,114,154,143,168,162,161,239,196,33,75,35,20,61,227,247,44,133,46,222,78,227,191,3,46,2,248,246,206,141,64,183,75,184,121,191] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/solanadevnet/core/program-ids.json b/rust/sealevel/environments/testnet3/solanadevnet/core/program-ids.json deleted file mode 100644 index ab3f1f593..000000000 --- a/rust/sealevel/environments/testnet3/solanadevnet/core/program-ids.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "mailbox": "4v25Dz9RccqUrTzmfHzJMsjd1iVoNrWzeJ4o6GYuJrVn", - "validator_announce": "CMHKvdq4CopDf7qXnDCaTybS15QekQeRt4oUB219yxsp", - "multisig_ism_message_id": "64xkGhsZbxgP5rBJfpPcpmzkzTGkpSVHiDLcMKS5gmQw", - "igp_program_id": "HyPQPLfGXDTAQTxzGp7r1uy18KxS89GKgreSHpjeuYDn", - "overhead_igp_account": "AR4hjWPqXEobLvzmv8MTh5k4Se49iTDzbvNX4DpdQGJZ", - "igp_account": "7hMPEGdgBQFsjEz3aaNwZp8WMFHs615zAM3erXBDJuJR" -} \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/collateraltest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json b/rust/sealevel/environments/testnet3/warp-routes/collateraltest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json deleted file mode 100644 index dbfcba9d8..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/collateraltest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json +++ /dev/null @@ -1 +0,0 @@ -[98,129,191,177,102,138,233,60,156,241,236,62,216,72,254,103,183,93,70,101,75,216,137,204,55,192,74,81,77,235,129,248,250,176,128,150,198,17,155,33,251,185,183,201,212,28,44,194,220,95,98,92,146,8,192,17,20,32,3,58,184,37,56,85] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/collateraltest/program-ids.json b/rust/sealevel/environments/testnet3/warp-routes/collateraltest/program-ids.json deleted file mode 100644 index c2baa7da5..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/collateraltest/program-ids.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "fuji": { - "hex": "0x000000000000000000000000a97f4eacbc363f82d25a540440afc6f78920299b", - "base58": "1111111111113Mxh1B6fskiQrE2FY7RuvZDF7PfQ" - }, - "solanadevnet": { - "hex": "0xfab08096c6119b21fbb9b7c9d41c2cc2dc5f625c9208c0111420033ab8253855", - "base58": "Hsb2PdnUvd7VvZJ1svS8TrVLfsRDdDTWoHK5r2RwGZBS" - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/collateraltest/token-config.json b/rust/sealevel/environments/testnet3/warp-routes/collateraltest/token-config.json deleted file mode 100644 index 7f3109652..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/collateraltest/token-config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "solanadevnet": { - "type": "collateral", - "token": "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr", - "splTokenProgram": "token", - "decimals": 6, - "name": "USD Coin Dev", - "symbol": "USDC" - }, - "fuji": { - "type": "synthetic", - "decimals": 6, - "name": "USD Coin Dev", - "symbol": "USDC", - "foreignDeployment": "0xa97F4eACbc363f82D25a540440AFC6F78920299b" - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/nativetest/keys/hyperlane_sealevel_token_native-solanadevnet.json b/rust/sealevel/environments/testnet3/warp-routes/nativetest/keys/hyperlane_sealevel_token_native-solanadevnet.json deleted file mode 100644 index 0d2df675e..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/nativetest/keys/hyperlane_sealevel_token_native-solanadevnet.json +++ /dev/null @@ -1 +0,0 @@ -[211,130,122,136,147,203,98,25,35,161,148,152,75,119,132,211,228,27,148,224,200,130,204,186,108,89,180,204,61,134,31,201,42,140,185,95,186,218,14,12,41,76,133,231,57,34,111,23,173,172,165,221,240,26,185,158,14,250,248,167,59,227,33,3] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/nativetest/program-ids.json b/rust/sealevel/environments/testnet3/warp-routes/nativetest/program-ids.json deleted file mode 100644 index a72aaccd1..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/nativetest/program-ids.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "fuji": { - "hex": "0x000000000000000000000000ddd2e6d7cc3fa4599de681376690c8ba538dab51", - "base58": "11111111111146F2zy7DPHvybUST2mVP2A8mFRDi" - }, - "solanadevnet": { - "hex": "0x2a8cb95fbada0e0c294c85e739226f17adaca5ddf01ab99e0efaf8a73be32103", - "base58": "3s6afZYk3EmjsZQ33N9yPTdSk4cY5CKeQ5wtoBcWjFUn" - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/nativetest/token-config.json b/rust/sealevel/environments/testnet3/warp-routes/nativetest/token-config.json deleted file mode 100644 index ea5c90fdc..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/nativetest/token-config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "solanadevnet": { - "type": "native", - "decimals": 9 - }, - "fuji": { - "type": "synthetic", - "decimals": 9, - "name": "Solana (solanadevnet)", - "symbol": "SOL", - "foreignDeployment": "0xDDD2E6d7cC3Fa4599dE681376690c8ba538DaB51" - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/proteustest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json b/rust/sealevel/environments/testnet3/warp-routes/proteustest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json deleted file mode 100644 index 4b523b6c5..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/proteustest/keys/hyperlane_sealevel_token_collateral-solanadevnet.json +++ /dev/null @@ -1 +0,0 @@ -[133,28,132,175,210,67,108,229,84,248,196,16,163,131,6,22,86,131,0,142,107,175,93,123,37,242,27,80,72,191,116,37,5,182,80,43,29,145,198,12,160,192,208,171,32,161,110,196,12,102,242,85,155,236,199,136,138,79,195,192,206,255,249,165] \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/proteustest/program-ids.json b/rust/sealevel/environments/testnet3/warp-routes/proteustest/program-ids.json deleted file mode 100644 index f2372bc90..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/proteustest/program-ids.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "solanadevnet": { - "hex": "0x05b6502b1d91c60ca0c0d0ab20a16ec40c66f2559becc7888a4fc3c0cefff9a5", - "base58": "PJH5QAbxAqrrnSXfH3GHR8icua8CDFZmo97z91xmpvx" - }, - "proteustestnet": { - "hex": "0x00000000000000000000000034a9af13c5555bad0783c220911b9ef59cfdbcef", - "base58": "111111111111jZ775N1rpEpJ2M8RAzLNNr9Lh7U" - }, - "bsctestnet": { - "hex": "0x00000000000000000000000031b5234a896fbc4b3e2f7237592d054716762131", - "base58": "111111111111hAc1aTgvQGRBFHrYpXpfUqGyqgk" - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/testnet3/warp-routes/proteustest/token-config.json b/rust/sealevel/environments/testnet3/warp-routes/proteustest/token-config.json deleted file mode 100644 index c2424796a..000000000 --- a/rust/sealevel/environments/testnet3/warp-routes/proteustest/token-config.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "solanadevnet": { - "type": "collateral", - "decimals": 6, - "remoteDecimals": 18, - "token": "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr", - "splTokenProgram": "token" - }, - "bsctestnet": { - "type": "collateral", - "decimals": 18, - "token": "0x64544969ed7ebf5f083679233325356ebe738930", - "name": "USDC", - "symbol": "USDC", - "foreignDeployment": "0x31b5234A896FbC4b3e2F7237592D054716762131" - }, - "proteustestnet": { - "type": "native", - "decimals": 18, - "foreignDeployment": "0x34A9af13c5555BAD0783C220911b9ef59CfDBCEf" - } -} \ No newline at end of file From 96ee728788cb4231bd7ecc95cfa714093d56701a Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:25:40 +0100 Subject: [PATCH 042/224] feat: turbo eth warp route (#4514) --- .../agents/relayer/src/msg/gas_payment/mod.rs | 1 + .../warp-routes/eclipsesol/token-config.json | 2 +- .../warp-routes/eclipseteth/program-ids.json | 10 ++++++++++ .../warp-routes/eclipseteth/token-config.json | 17 +++++++++++++++++ .../warp-routes/eclipseusdc/token-config.json | 2 +- 5 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json diff --git a/rust/main/agents/relayer/src/msg/gas_payment/mod.rs b/rust/main/agents/relayer/src/msg/gas_payment/mod.rs index 0a4684863..a13d0d26e 100644 --- a/rust/main/agents/relayer/src/msg/gas_payment/mod.rs +++ b/rust/main/agents/relayer/src/msg/gas_payment/mod.rs @@ -124,6 +124,7 @@ impl GasPaymentEnforcer { ?policy, ?current_payment, ?current_expenditure, + ?tx_cost_estimate, "Evaluating if message meets gas payment requirement", ); return policy diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json index dfd9b9c98..af41b5393 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json @@ -9,7 +9,7 @@ "decimals": 9, "name": "Solana", "symbol": "SOL", - "uri": "https://github.com/hyperlane-xyz/hyperlane-registry/blob/33a13d304d3f08be79aad29ed47e7baeeea97db0/deployments/warp_routes/SOL/metadata.json", + "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/77a04c0b7e214ae17853215467f8ddea5e0ac710/deployments/warp_routes/SOL/metadata.json", "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" } } diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json new file mode 100644 index 000000000..5b816e08e --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json @@ -0,0 +1,10 @@ +{ + "ethereum": { + "hex": "0x0000000000000000000000003ac6a6cca0b49c3f3f06d12f46e8d88eefbb7415", + "base58": "111111111111pVc7hF6xGk4TFPJAr7cTknNSZit" + }, + "eclipsemainnet": { + "hex": "0x99151bae88c2a4620b24ede803232e0cedb5f762dbc11b8c65761b93df22d791", + "base58": "BJa3fPvvjKx8gRCWunoSrWBbsmieub37gsGpjp4BfTfW" + } +} diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json new file mode 100644 index 000000000..921cad451 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json @@ -0,0 +1,17 @@ +{ + "eclipsemainnet": { + "type": "synthetic", + "decimals": 9, + "remoteDecimals": 18, + "name": "Turbo ETH", + "symbol": "tETH", + "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/77a04c0b7e214ae17853215467f8ddea5e0ac710/deployments/warp_routes/tETH/metadata.json", + "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" + }, + "ethereum": { + "type": "collateral", + "decimals": 18, + "token": "0x19e099B7aEd41FA52718D780dDA74678113C0b32", + "foreignDeployment": "0x3Ac6A6Cca0b49C3f3f06D12F46e8d88EEfbB7415" + } +} diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json index 8d3579307..d5eb85403 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json @@ -11,7 +11,7 @@ "decimals": 6, "name": "USD Coin", "symbol": "USDC", - "uri": "https://github.com/hyperlane-xyz/hyperlane-registry/blob/33a13d304d3f08be79aad29ed47e7baeeea97db0/deployments/warp_routes/USDC/metadata.json", + "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/77a04c0b7e214ae17853215467f8ddea5e0ac710/deployments/warp_routes/USDC/metadata.json", "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" }, "ethereum": { From 3d116132b87d36af9576d6b116f31a53d680db4a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:02:36 +0000 Subject: [PATCH 043/224] Version Packages (#4366) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/core@5.2.0 ### Minor Changes - 203084df2: Added sdk support for Stake weighted ISM - 445b6222c: ArbL2ToL1Ism handles value via the executeTransaction branch ### Patch Changes - Updated dependencies [d6de34ad5] - Updated dependencies [291c5fe36] - @hyperlane-xyz/utils@5.2.0 ## @hyperlane-xyz/cli@5.2.0 ### Minor Changes - a5afd20f3: Add CLI e2e typescript tests - 203084df2: Added sdk support for Stake weighted ISM - a46fe434a: Add hyperlane registry rpc and addresses --contract utils - f2783c03b: Add ChainSubmissionStrategySchema - 3c07ded5b: Add Safe submit functionality to warp apply ### Patch Changes - Updated dependencies [a19e882fd] - Updated dependencies [d6de34ad5] - Updated dependencies [518a1bef9] - Updated dependencies [203084df2] - Updated dependencies [74a592e58] - Updated dependencies [739af9a34] - Updated dependencies [44588c31d] - Updated dependencies [2bd540e0f] - Updated dependencies [291c5fe36] - Updated dependencies [69f17d99a] - Updated dependencies [3ad5918da] - Updated dependencies [291c5fe36] - Updated dependencies [9563a8beb] - Updated dependencies [73c232b3a] - Updated dependencies [445b6222c] - Updated dependencies [d6de34ad5] - Updated dependencies [2e6176f67] - Updated dependencies [f2783c03b] - Updated dependencies [2ffb78f5c] - Updated dependencies [3c07ded5b] - Updated dependencies [815542dd7] - @hyperlane-xyz/sdk@5.2.0 - @hyperlane-xyz/utils@5.2.0 ## @hyperlane-xyz/github-proxy@5.2.0 ### Minor Changes - 0e2f94ba1: Add github proxy to reduce github API load - 3113807e3: Add recursive=true query string to Github Proxy to allow nested tree search ## @hyperlane-xyz/helloworld@5.2.0 ### Minor Changes - 291c5fe36: Use addBufferToGasLimit from @hyperlane-xyz/utils ### Patch Changes - Updated dependencies [a19e882fd] - Updated dependencies [518a1bef9] - Updated dependencies [203084df2] - Updated dependencies [74a592e58] - Updated dependencies [739af9a34] - Updated dependencies [44588c31d] - Updated dependencies [2bd540e0f] - Updated dependencies [291c5fe36] - Updated dependencies [69f17d99a] - Updated dependencies [3ad5918da] - Updated dependencies [9563a8beb] - Updated dependencies [73c232b3a] - Updated dependencies [445b6222c] - Updated dependencies [d6de34ad5] - Updated dependencies [2e6176f67] - Updated dependencies [f2783c03b] - Updated dependencies [2ffb78f5c] - Updated dependencies [3c07ded5b] - Updated dependencies [815542dd7] - @hyperlane-xyz/sdk@5.2.0 - @hyperlane-xyz/core@5.2.0 ## @hyperlane-xyz/sdk@5.2.0 ### Minor Changes - a19e882fd: Improve Router Checker/Governor tooling to support enrolling multiple routers for missing domains - 203084df2: Added sdk support for Stake weighted ISM - 74a592e58: Adds OwnerCollateral to token mapping which will output the correct standard to the warp deploy artifact. - 739af9a34: Support providing multiple chains for checking in HyperlaneAppChecker - 44588c31d: Enroll new validators for cyber degenchain kroma lisk lukso merlin metis mint proofofplay real sanko tangle xai taiko - 291c5fe36: Use addBufferToGasLimit from @hyperlane-xyz/utils - 69f17d99a: Fix to correctly infer the default set of multisend addresses for a given chain, and update to latest safe-deployments patch release - 9563a8beb: Sorted cwNative funds by denom in transfer tx - 73c232b3a: Deploy to oortmainnet - 445b6222c: ArbL2ToL1Ism handles value via the executeTransaction branch - d6de34ad5: Sort values in EvmModuleDeployer.deployStaticAddressSet - 2e6176f67: Deploy to everclear mainnet - f2783c03b: Add ChainSubmissionStrategySchema - 3c07ded5b: Add Safe submit functionality to warp apply ### Patch Changes - 518a1bef9: add 10% gas bump to initialize call in EvmModuleDeployer - 2bd540e0f: Estimate and add 10% gas bump for ICA initialization and enrollment - 3ad5918da: Support DefaultFallbackRoutingIsm in metadata builder - 2ffb78f5c: Improved check for mailbox initialization - 815542dd7: Fix arg validation for Sealevel HypNative adapters Allow extra properties in ChainMetadata objects - Updated dependencies [d6de34ad5] - Updated dependencies [203084df2] - Updated dependencies [291c5fe36] - Updated dependencies [445b6222c] - @hyperlane-xyz/utils@5.2.0 - @hyperlane-xyz/core@5.2.0 ## @hyperlane-xyz/utils@5.2.0 ### Minor Changes - d6de34ad5: Add sortArraysInConfig method, normalizeConfig implementation to call sortArraysInConfig after current behavior - 291c5fe36: Add addBufferToGasLimit for gas limit buffer calculations ## @hyperlane-xyz/widgets@5.2.0 ### Patch Changes - Updated dependencies [a19e882fd] - Updated dependencies [518a1bef9] - Updated dependencies [203084df2] - Updated dependencies [74a592e58] - Updated dependencies [739af9a34] - Updated dependencies [44588c31d] - Updated dependencies [2bd540e0f] - Updated dependencies [291c5fe36] - Updated dependencies [69f17d99a] - Updated dependencies [3ad5918da] - Updated dependencies [9563a8beb] - Updated dependencies [73c232b3a] - Updated dependencies [445b6222c] - Updated dependencies [d6de34ad5] - Updated dependencies [2e6176f67] - Updated dependencies [f2783c03b] - Updated dependencies [2ffb78f5c] - Updated dependencies [3c07ded5b] - Updated dependencies [815542dd7] - @hyperlane-xyz/sdk@5.2.0 ## @hyperlane-xyz/infra@5.2.0 ### Minor Changes - 203084df2: Added sdk support for Stake weighted ISM ### Patch Changes - 5a0d68bdc: replace import console module with direct console - Updated dependencies [a19e882fd] - Updated dependencies [d6de34ad5] - Updated dependencies [518a1bef9] - Updated dependencies [203084df2] - Updated dependencies [74a592e58] - Updated dependencies [739af9a34] - Updated dependencies [44588c31d] - Updated dependencies [2bd540e0f] - Updated dependencies [291c5fe36] - Updated dependencies [69f17d99a] - Updated dependencies [3ad5918da] - Updated dependencies [291c5fe36] - Updated dependencies [9563a8beb] - Updated dependencies [73c232b3a] - Updated dependencies [445b6222c] - Updated dependencies [d6de34ad5] - Updated dependencies [2e6176f67] - Updated dependencies [f2783c03b] - Updated dependencies [2ffb78f5c] - Updated dependencies [3c07ded5b] - Updated dependencies [815542dd7] - @hyperlane-xyz/sdk@5.2.0 - @hyperlane-xyz/utils@5.2.0 - @hyperlane-xyz/helloworld@5.2.0 ## @hyperlane-xyz/ccip-server@5.2.0 ### Patch Changes - 5a0d68bdc: replace import console module with direct console Co-authored-by: github-actions[bot] --- .changeset/chatty-glasses-buy.md | 5 ---- .changeset/chatty-plums-invite.md | 5 ---- .changeset/chilled-coats-boil.md | 5 ---- .changeset/curvy-ligers-drive.md | 5 ---- .changeset/dull-days-yell.md | 8 ------ .changeset/eighty-candles-press.md | 5 ---- .changeset/famous-ants-tan.md | 5 ---- .changeset/flat-seals-prove.md | 5 ---- .changeset/giant-items-suffer.md | 5 ---- .changeset/gorgeous-dragons-swim.md | 5 ---- .changeset/gorgeous-owls-kiss.md | 6 ----- .changeset/gorgeous-panthers-switch.md | 6 ----- .changeset/loud-elephants-reflect.md | 5 ---- .changeset/mighty-scissors-unite.md | 5 ---- .changeset/nice-deers-tan.md | 5 ---- .changeset/pink-paws-fry.md | 5 ---- .changeset/quick-students-cover.md | 5 ---- .changeset/red-nails-trade.md | 5 ---- .changeset/slimy-humans-glow.md | 5 ---- .changeset/stale-planets-dance.md | 6 ----- .changeset/tender-fishes-sniff.md | 5 ---- .changeset/tender-moles-mate.md | 5 ---- .changeset/tricky-horses-repair.md | 6 ----- .changeset/warm-grapes-talk.md | 5 ---- .changeset/wicked-knives-care.md | 6 ----- .changeset/young-moose-march.md | 6 ----- solidity/CHANGELOG.md | 13 ++++++++++ solidity/package.json | 4 +-- typescript/ccip-server/CHANGELOG.md | 6 +++++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 36 ++++++++++++++++++++++++++ typescript/cli/package.json | 6 ++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 8 ++++++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 30 +++++++++++++++++++++ typescript/helloworld/package.json | 6 ++--- typescript/infra/CHANGELOG.md | 34 ++++++++++++++++++++++++ typescript/infra/package.json | 8 +++--- typescript/sdk/CHANGELOG.md | 34 ++++++++++++++++++++++++ typescript/sdk/package.json | 6 ++--- typescript/utils/CHANGELOG.md | 7 +++++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 25 ++++++++++++++++++ typescript/widgets/package.json | 4 +-- yarn.lock | 30 ++++++++++----------- 46 files changed, 229 insertions(+), 175 deletions(-) delete mode 100644 .changeset/chatty-glasses-buy.md delete mode 100644 .changeset/chatty-plums-invite.md delete mode 100644 .changeset/chilled-coats-boil.md delete mode 100644 .changeset/curvy-ligers-drive.md delete mode 100644 .changeset/dull-days-yell.md delete mode 100644 .changeset/eighty-candles-press.md delete mode 100644 .changeset/famous-ants-tan.md delete mode 100644 .changeset/flat-seals-prove.md delete mode 100644 .changeset/giant-items-suffer.md delete mode 100644 .changeset/gorgeous-dragons-swim.md delete mode 100644 .changeset/gorgeous-owls-kiss.md delete mode 100644 .changeset/gorgeous-panthers-switch.md delete mode 100644 .changeset/loud-elephants-reflect.md delete mode 100644 .changeset/mighty-scissors-unite.md delete mode 100644 .changeset/nice-deers-tan.md delete mode 100644 .changeset/pink-paws-fry.md delete mode 100644 .changeset/quick-students-cover.md delete mode 100644 .changeset/red-nails-trade.md delete mode 100644 .changeset/slimy-humans-glow.md delete mode 100644 .changeset/stale-planets-dance.md delete mode 100644 .changeset/tender-fishes-sniff.md delete mode 100644 .changeset/tender-moles-mate.md delete mode 100644 .changeset/tricky-horses-repair.md delete mode 100644 .changeset/warm-grapes-talk.md delete mode 100644 .changeset/wicked-knives-care.md delete mode 100644 .changeset/young-moose-march.md create mode 100644 typescript/github-proxy/CHANGELOG.md diff --git a/.changeset/chatty-glasses-buy.md b/.changeset/chatty-glasses-buy.md deleted file mode 100644 index 1f9cd06cc..000000000 --- a/.changeset/chatty-glasses-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor ---- - -Add CLI e2e typescript tests diff --git a/.changeset/chatty-plums-invite.md b/.changeset/chatty-plums-invite.md deleted file mode 100644 index e610e8836..000000000 --- a/.changeset/chatty-plums-invite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Improve Router Checker/Governor tooling to support enrolling multiple routers for missing domains diff --git a/.changeset/chilled-coats-boil.md b/.changeset/chilled-coats-boil.md deleted file mode 100644 index 6ec43005e..000000000 --- a/.changeset/chilled-coats-boil.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/utils': minor ---- - -Add sortArraysInConfig method, normalizeConfig implementation to call sortArraysInConfig after current behavior diff --git a/.changeset/curvy-ligers-drive.md b/.changeset/curvy-ligers-drive.md deleted file mode 100644 index 45778d7c2..000000000 --- a/.changeset/curvy-ligers-drive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -add 10% gas bump to initialize call in EvmModuleDeployer diff --git a/.changeset/dull-days-yell.md b/.changeset/dull-days-yell.md deleted file mode 100644 index 4ad4fb61d..000000000 --- a/.changeset/dull-days-yell.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@hyperlane-xyz/infra': minor -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor -'@hyperlane-xyz/core': minor ---- - -Added sdk support for Stake weighted ISM diff --git a/.changeset/eighty-candles-press.md b/.changeset/eighty-candles-press.md deleted file mode 100644 index 5f397e18a..000000000 --- a/.changeset/eighty-candles-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Adds OwnerCollateral to token mapping which will output the correct standard to the warp deploy artifact. diff --git a/.changeset/famous-ants-tan.md b/.changeset/famous-ants-tan.md deleted file mode 100644 index d81e23d38..000000000 --- a/.changeset/famous-ants-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/github-proxy': minor ---- - -Add github proxy to reduce github API load diff --git a/.changeset/flat-seals-prove.md b/.changeset/flat-seals-prove.md deleted file mode 100644 index a51d5ef68..000000000 --- a/.changeset/flat-seals-prove.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Support providing multiple chains for checking in HyperlaneAppChecker diff --git a/.changeset/giant-items-suffer.md b/.changeset/giant-items-suffer.md deleted file mode 100644 index 53b286689..000000000 --- a/.changeset/giant-items-suffer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Enroll new validators for cyber degenchain kroma lisk lukso merlin metis mint proofofplay real sanko tangle xai taiko diff --git a/.changeset/gorgeous-dragons-swim.md b/.changeset/gorgeous-dragons-swim.md deleted file mode 100644 index 4888ca7e1..000000000 --- a/.changeset/gorgeous-dragons-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Estimate and add 10% gas bump for ICA initialization and enrollment diff --git a/.changeset/gorgeous-owls-kiss.md b/.changeset/gorgeous-owls-kiss.md deleted file mode 100644 index 0355a25b4..000000000 --- a/.changeset/gorgeous-owls-kiss.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/ccip-server': patch -'@hyperlane-xyz/infra': patch ---- - -replace import console module with direct console diff --git a/.changeset/gorgeous-panthers-switch.md b/.changeset/gorgeous-panthers-switch.md deleted file mode 100644 index df3bbe95d..000000000 --- a/.changeset/gorgeous-panthers-switch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/helloworld': minor -'@hyperlane-xyz/sdk': minor ---- - -Use addBufferToGasLimit from @hyperlane-xyz/utils diff --git a/.changeset/loud-elephants-reflect.md b/.changeset/loud-elephants-reflect.md deleted file mode 100644 index 717cabc98..000000000 --- a/.changeset/loud-elephants-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/github-proxy': minor ---- - -Add recursive=true query string to Github Proxy to allow nested tree search diff --git a/.changeset/mighty-scissors-unite.md b/.changeset/mighty-scissors-unite.md deleted file mode 100644 index 0e19e46a3..000000000 --- a/.changeset/mighty-scissors-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Fix to correctly infer the default set of multisend addresses for a given chain, and update to latest safe-deployments patch release diff --git a/.changeset/nice-deers-tan.md b/.changeset/nice-deers-tan.md deleted file mode 100644 index 1acc20ce1..000000000 --- a/.changeset/nice-deers-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Support DefaultFallbackRoutingIsm in metadata builder diff --git a/.changeset/pink-paws-fry.md b/.changeset/pink-paws-fry.md deleted file mode 100644 index a4a48f737..000000000 --- a/.changeset/pink-paws-fry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor ---- - -Add hyperlane registry rpc and addresses --contract utils diff --git a/.changeset/quick-students-cover.md b/.changeset/quick-students-cover.md deleted file mode 100644 index 00ce3a8e0..000000000 --- a/.changeset/quick-students-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/utils': minor ---- - -Add addBufferToGasLimit for gas limit buffer calculations diff --git a/.changeset/red-nails-trade.md b/.changeset/red-nails-trade.md deleted file mode 100644 index 42981e08f..000000000 --- a/.changeset/red-nails-trade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Sorted cwNative funds by denom in transfer tx diff --git a/.changeset/slimy-humans-glow.md b/.changeset/slimy-humans-glow.md deleted file mode 100644 index b9360bc88..000000000 --- a/.changeset/slimy-humans-glow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Deploy to oortmainnet diff --git a/.changeset/stale-planets-dance.md b/.changeset/stale-planets-dance.md deleted file mode 100644 index 5da4b82e7..000000000 --- a/.changeset/stale-planets-dance.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor -'@hyperlane-xyz/core': minor ---- - -ArbL2ToL1Ism handles value via the executeTransaction branch diff --git a/.changeset/tender-fishes-sniff.md b/.changeset/tender-fishes-sniff.md deleted file mode 100644 index 9582272a5..000000000 --- a/.changeset/tender-fishes-sniff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Sort values in EvmModuleDeployer.deployStaticAddressSet diff --git a/.changeset/tender-moles-mate.md b/.changeset/tender-moles-mate.md deleted file mode 100644 index 09b5e628e..000000000 --- a/.changeset/tender-moles-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Deploy to everclear mainnet diff --git a/.changeset/tricky-horses-repair.md b/.changeset/tricky-horses-repair.md deleted file mode 100644 index b54639407..000000000 --- a/.changeset/tricky-horses-repair.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Add ChainSubmissionStrategySchema diff --git a/.changeset/warm-grapes-talk.md b/.changeset/warm-grapes-talk.md deleted file mode 100644 index 75c996c8b..000000000 --- a/.changeset/warm-grapes-talk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Improved check for mailbox initialization diff --git a/.changeset/wicked-knives-care.md b/.changeset/wicked-knives-care.md deleted file mode 100644 index 04e60a98e..000000000 --- a/.changeset/wicked-knives-care.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Add Safe submit functionality to warp apply diff --git a/.changeset/young-moose-march.md b/.changeset/young-moose-march.md deleted file mode 100644 index 54b531a40..000000000 --- a/.changeset/young-moose-march.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Fix arg validation for Sealevel HypNative adapters -Allow extra properties in ChainMetadata objects diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index 9b4b798c4..72b14534c 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,18 @@ # @hyperlane-xyz/core +## 5.2.0 + +### Minor Changes + +- 203084df2: Added sdk support for Stake weighted ISM +- 445b6222c: ArbL2ToL1Ism handles value via the executeTransaction branch + +### Patch Changes + +- Updated dependencies [d6de34ad5] +- Updated dependencies [291c5fe36] + - @hyperlane-xyz/utils@5.2.0 + ## 5.1.0 ### Minor Changes diff --git a/solidity/package.json b/solidity/package.json index 2b74b1d4d..e5a765129 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.1.0", + "version": "5.2.0", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.1.0", + "@hyperlane-xyz/utils": "5.2.0", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index 6ac6fea3f..4d088d0f4 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,11 @@ # @hyperlane-xyz/ccip-server +## 5.2.0 + +### Patch Changes + +- 5a0d68bdc: replace import console module with direct console + ## 5.1.0 ## 5.0.0 diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index faaaf2cbb..ff457a5d7 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.1.0", + "version": "5.2.0", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index 85209edd1..eaa4970b2 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,41 @@ # @hyperlane-xyz/cli +## 5.2.0 + +### Minor Changes + +- a5afd20f3: Add CLI e2e typescript tests +- 203084df2: Added sdk support for Stake weighted ISM +- a46fe434a: Add hyperlane registry rpc and addresses --contract utils +- f2783c03b: Add ChainSubmissionStrategySchema +- 3c07ded5b: Add Safe submit functionality to warp apply + +### Patch Changes + +- Updated dependencies [a19e882fd] +- Updated dependencies [d6de34ad5] +- Updated dependencies [518a1bef9] +- Updated dependencies [203084df2] +- Updated dependencies [74a592e58] +- Updated dependencies [739af9a34] +- Updated dependencies [44588c31d] +- Updated dependencies [2bd540e0f] +- Updated dependencies [291c5fe36] +- Updated dependencies [69f17d99a] +- Updated dependencies [3ad5918da] +- Updated dependencies [291c5fe36] +- Updated dependencies [9563a8beb] +- Updated dependencies [73c232b3a] +- Updated dependencies [445b6222c] +- Updated dependencies [d6de34ad5] +- Updated dependencies [2e6176f67] +- Updated dependencies [f2783c03b] +- Updated dependencies [2ffb78f5c] +- Updated dependencies [3c07ded5b] +- Updated dependencies [815542dd7] + - @hyperlane-xyz/sdk@5.2.0 + - @hyperlane-xyz/utils@5.2.0 + ## 5.1.0 ### Minor Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index b44e7fb50..1d0e23a2b 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.1.0", + "version": "5.2.0", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.1.0", - "@hyperlane-xyz/sdk": "5.1.0", - "@hyperlane-xyz/utils": "5.1.0", + "@hyperlane-xyz/sdk": "5.2.0", + "@hyperlane-xyz/utils": "5.2.0", "@inquirer/prompts": "^3.0.0", "asn1.js": "^5.4.1", "bignumber.js": "^9.1.1", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index 86fb165ea..52ba2c39c 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.1.0'; +export const VERSION = '5.2.0'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md new file mode 100644 index 000000000..ceff61e23 --- /dev/null +++ b/typescript/github-proxy/CHANGELOG.md @@ -0,0 +1,8 @@ +# @hyperlane-xyz/github-proxy + +## 5.2.0 + +### Minor Changes + +- 0e2f94ba1: Add github proxy to reduce github API load +- 3113807e3: Add recursive=true query string to Github Proxy to allow nested tree search diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index c46453777..827228b33 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.1.0", + "version": "5.2.0", "scripts": { "deploy": "wrangler deploy", "deploy:staging": "wrangler deploy --env staging", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index f5595889a..15f464849 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,35 @@ # @hyperlane-xyz/helloworld +## 5.2.0 + +### Minor Changes + +- 291c5fe36: Use addBufferToGasLimit from @hyperlane-xyz/utils + +### Patch Changes + +- Updated dependencies [a19e882fd] +- Updated dependencies [518a1bef9] +- Updated dependencies [203084df2] +- Updated dependencies [74a592e58] +- Updated dependencies [739af9a34] +- Updated dependencies [44588c31d] +- Updated dependencies [2bd540e0f] +- Updated dependencies [291c5fe36] +- Updated dependencies [69f17d99a] +- Updated dependencies [3ad5918da] +- Updated dependencies [9563a8beb] +- Updated dependencies [73c232b3a] +- Updated dependencies [445b6222c] +- Updated dependencies [d6de34ad5] +- Updated dependencies [2e6176f67] +- Updated dependencies [f2783c03b] +- Updated dependencies [2ffb78f5c] +- Updated dependencies [3c07ded5b] +- Updated dependencies [815542dd7] + - @hyperlane-xyz/sdk@5.2.0 + - @hyperlane-xyz/core@5.2.0 + ## 5.1.0 ### Minor Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index b3fc92a52..b7de18159 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.1.0", + "version": "5.2.0", "dependencies": { - "@hyperlane-xyz/core": "5.1.0", + "@hyperlane-xyz/core": "5.2.0", "@hyperlane-xyz/registry": "4.1.0", - "@hyperlane-xyz/sdk": "5.1.0", + "@hyperlane-xyz/sdk": "5.2.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index b4c93fc44..21886a78f 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,39 @@ # @hyperlane-xyz/infra +## 5.2.0 + +### Minor Changes + +- 203084df2: Added sdk support for Stake weighted ISM + +### Patch Changes + +- 5a0d68bdc: replace import console module with direct console +- Updated dependencies [a19e882fd] +- Updated dependencies [d6de34ad5] +- Updated dependencies [518a1bef9] +- Updated dependencies [203084df2] +- Updated dependencies [74a592e58] +- Updated dependencies [739af9a34] +- Updated dependencies [44588c31d] +- Updated dependencies [2bd540e0f] +- Updated dependencies [291c5fe36] +- Updated dependencies [69f17d99a] +- Updated dependencies [3ad5918da] +- Updated dependencies [291c5fe36] +- Updated dependencies [9563a8beb] +- Updated dependencies [73c232b3a] +- Updated dependencies [445b6222c] +- Updated dependencies [d6de34ad5] +- Updated dependencies [2e6176f67] +- Updated dependencies [f2783c03b] +- Updated dependencies [2ffb78f5c] +- Updated dependencies [3c07ded5b] +- Updated dependencies [815542dd7] + - @hyperlane-xyz/sdk@5.2.0 + - @hyperlane-xyz/utils@5.2.0 + - @hyperlane-xyz/helloworld@5.2.0 + ## 5.1.0 ### Minor Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 174906ae1..9b4fc4362 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.1.0", + "version": "5.2.0", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.1.0", + "@hyperlane-xyz/helloworld": "5.2.0", "@hyperlane-xyz/registry": "4.1.0", - "@hyperlane-xyz/sdk": "5.1.0", - "@hyperlane-xyz/utils": "5.1.0", + "@hyperlane-xyz/sdk": "5.2.0", + "@hyperlane-xyz/utils": "5.2.0", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index 72fdc1a2a..1bcdb4c7f 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,39 @@ # @hyperlane-xyz/sdk +## 5.2.0 + +### Minor Changes + +- a19e882fd: Improve Router Checker/Governor tooling to support enrolling multiple routers for missing domains +- 203084df2: Added sdk support for Stake weighted ISM +- 74a592e58: Adds OwnerCollateral to token mapping which will output the correct standard to the warp deploy artifact. +- 739af9a34: Support providing multiple chains for checking in HyperlaneAppChecker +- 44588c31d: Enroll new validators for cyber degenchain kroma lisk lukso merlin metis mint proofofplay real sanko tangle xai taiko +- 291c5fe36: Use addBufferToGasLimit from @hyperlane-xyz/utils +- 69f17d99a: Fix to correctly infer the default set of multisend addresses for a given chain, and update to latest safe-deployments patch release +- 9563a8beb: Sorted cwNative funds by denom in transfer tx +- 73c232b3a: Deploy to oortmainnet +- 445b6222c: ArbL2ToL1Ism handles value via the executeTransaction branch +- d6de34ad5: Sort values in EvmModuleDeployer.deployStaticAddressSet +- 2e6176f67: Deploy to everclear mainnet +- f2783c03b: Add ChainSubmissionStrategySchema +- 3c07ded5b: Add Safe submit functionality to warp apply + +### Patch Changes + +- 518a1bef9: add 10% gas bump to initialize call in EvmModuleDeployer +- 2bd540e0f: Estimate and add 10% gas bump for ICA initialization and enrollment +- 3ad5918da: Support DefaultFallbackRoutingIsm in metadata builder +- 2ffb78f5c: Improved check for mailbox initialization +- 815542dd7: Fix arg validation for Sealevel HypNative adapters + Allow extra properties in ChainMetadata objects +- Updated dependencies [d6de34ad5] +- Updated dependencies [203084df2] +- Updated dependencies [291c5fe36] +- Updated dependencies [445b6222c] + - @hyperlane-xyz/utils@5.2.0 + - @hyperlane-xyz/core@5.2.0 + ## 5.1.0 ### Minor Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 36e3197c8..65f69ed3e 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.1.0", + "version": "5.2.0", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.1.0", - "@hyperlane-xyz/utils": "5.1.0", + "@hyperlane-xyz/core": "5.2.0", + "@hyperlane-xyz/utils": "5.2.0", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index 8692aac9b..6a19cc8b5 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @hyperlane-xyz/utils +## 5.2.0 + +### Minor Changes + +- d6de34ad5: Add sortArraysInConfig method, normalizeConfig implementation to call sortArraysInConfig after current behavior +- 291c5fe36: Add addBufferToGasLimit for gas limit buffer calculations + ## 5.1.0 ## 5.0.0 diff --git a/typescript/utils/package.json b/typescript/utils/package.json index 958e419be..e87aef47d 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.1.0", + "version": "5.2.0", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index 14bd5608e..a085fab2b 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,30 @@ # @hyperlane-xyz/widgets +## 5.2.0 + +### Patch Changes + +- Updated dependencies [a19e882fd] +- Updated dependencies [518a1bef9] +- Updated dependencies [203084df2] +- Updated dependencies [74a592e58] +- Updated dependencies [739af9a34] +- Updated dependencies [44588c31d] +- Updated dependencies [2bd540e0f] +- Updated dependencies [291c5fe36] +- Updated dependencies [69f17d99a] +- Updated dependencies [3ad5918da] +- Updated dependencies [9563a8beb] +- Updated dependencies [73c232b3a] +- Updated dependencies [445b6222c] +- Updated dependencies [d6de34ad5] +- Updated dependencies [2e6176f67] +- Updated dependencies [f2783c03b] +- Updated dependencies [2ffb78f5c] +- Updated dependencies [3c07ded5b] +- Updated dependencies [815542dd7] + - @hyperlane-xyz/sdk@5.2.0 + ## 5.1.0 ### Minor Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 373917e0e..96fab9262 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.1.0", + "version": "5.2.0", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@hyperlane-xyz/registry": "4.1.0", - "@hyperlane-xyz/sdk": "5.1.0" + "@hyperlane-xyz/sdk": "5.2.0" }, "devDependencies": { "@storybook/addon-essentials": "^7.6.14", diff --git a/yarn.lock b/yarn.lock index a2669136b..2f9482755 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7591,8 +7591,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.1.0" - "@hyperlane-xyz/sdk": "npm:5.1.0" - "@hyperlane-xyz/utils": "npm:5.1.0" + "@hyperlane-xyz/sdk": "npm:5.2.0" + "@hyperlane-xyz/utils": "npm:5.2.0" "@inquirer/prompts": "npm:^3.0.0" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:^18.14.5" @@ -7622,13 +7622,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.1.0, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.2.0, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.1.0" + "@hyperlane-xyz/utils": "npm:5.2.0" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7678,13 +7678,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.1.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.2.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.1.0" + "@hyperlane-xyz/core": "npm:5.2.0" "@hyperlane-xyz/registry": "npm:4.1.0" - "@hyperlane-xyz/sdk": "npm:5.1.0" + "@hyperlane-xyz/sdk": "npm:5.2.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7731,10 +7731,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.1.0" + "@hyperlane-xyz/helloworld": "npm:5.2.0" "@hyperlane-xyz/registry": "npm:4.1.0" - "@hyperlane-xyz/sdk": "npm:5.1.0" - "@hyperlane-xyz/utils": "npm:5.1.0" + "@hyperlane-xyz/sdk": "npm:5.2.0" + "@hyperlane-xyz/utils": "npm:5.2.0" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -7800,7 +7800,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.1.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.2.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -7808,8 +7808,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.1.0" - "@hyperlane-xyz/utils": "npm:5.1.0" + "@hyperlane-xyz/core": "npm:5.2.0" + "@hyperlane-xyz/utils": "npm:5.2.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -7850,7 +7850,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.1.0, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.2.0, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -7875,7 +7875,7 @@ __metadata: resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: "@hyperlane-xyz/registry": "npm:4.1.0" - "@hyperlane-xyz/sdk": "npm:5.1.0" + "@hyperlane-xyz/sdk": "npm:5.2.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From 5c0d179cd748468f81d9824de69645473785b888 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:31:42 +0100 Subject: [PATCH 044/224] feat: improve call logging in check-deploy (#4511) resolves https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4493 feat: improve call logging in check-deploy - refactors inference of call submission types - more clearly calls out ICA calls - using `chalk` in more places for easier reading in terminal drive-by: - update logging in multisend + safe utils updated router enrollment logging: ![image](https://github.com/user-attachments/assets/3cb7ef64-26dd-4b53-84e2-05d8c247a5b9) updated ICA call logging: ![image](https://github.com/user-attachments/assets/dd5f26d3-e8b2-43e3-888f-36c6bf773912) --- .../infra/src/govern/HyperlaneAppGovernor.ts | 441 +++++++++++------- .../infra/src/govern/HyperlaneCoreGovernor.ts | 3 +- .../infra/src/govern/ProxiedRouterGovernor.ts | 7 +- typescript/infra/src/govern/multisend.ts | 9 +- typescript/infra/src/utils/safe.ts | 31 +- 5 files changed, 310 insertions(+), 181 deletions(-) diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index f8464f3a6..6df9d3551 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -1,3 +1,4 @@ +import chalk from 'chalk'; import { BigNumber } from 'ethers'; import prompts from 'prompts'; @@ -41,12 +42,15 @@ export enum SubmissionType { export type AnnotatedCallData = CallData & { submissionType?: SubmissionType; description: string; + expandedDescription?: string; + icaTargetChain?: ChainName; }; export type InferredCall = { type: SubmissionType; chain: ChainName; call: AnnotatedCallData; + icaTargetChain?: ChainName; }; export abstract class HyperlaneAppGovernor< @@ -112,14 +116,33 @@ export abstract class HyperlaneAppGovernor< } console.log( - `> ${callsForSubmissionType.length} calls will be submitted via ${SubmissionType[submissionType]}`, + `${SubmissionType[submissionType]} calls: ${callsForSubmissionType.length}`, + ); + callsForSubmissionType.map( + ({ icaTargetChain, description, expandedDescription, ...call }) => { + // Print a blank line to separate calls + console.log(''); + + // Print the ICA call header if it exists + if (icaTargetChain) { + console.log( + chalk.bold( + `> INTERCHAIN ACCOUNT CALL: ${chain} -> ${icaTargetChain}`, + ), + ); + } + + // Print the call details + console.log(chalk.bold(`> ${description.trimEnd()}`)); + if (expandedDescription) { + console.info(chalk.gray(`${expandedDescription.trimEnd()}`)); + } + + console.info(chalk.gray(`to: ${call.to}`)); + console.info(chalk.gray(`data: ${call.data}`)); + console.info(chalk.gray(`value: ${call.value}`)); + }, ); - callsForSubmissionType.map((c) => { - console.log(`> > ${c.description.trim()}`); - console.log(`> > > to: ${c.to}`); - console.log(`> > > data: ${c.data}`); - console.log(`> > > value: ${c.value}`); - }); if (!requestConfirmation) return true; const { value: confirmed } = await prompts({ @@ -138,13 +161,16 @@ export abstract class HyperlaneAppGovernor< ) => { const callsForSubmissionType = filterCalls(submissionType) || []; if (callsForSubmissionType.length > 0) { + this.printSeparator(); const confirmed = await summarizeCalls( submissionType, callsForSubmissionType, ); if (confirmed) { - console.log( - `Submitting calls on ${chain} via ${SubmissionType[submissionType]}`, + console.info( + chalk.italic( + `Submitting calls on ${chain} via ${SubmissionType[submissionType]}`, + ), ); try { await multiSend.sendTransactions( @@ -155,11 +181,15 @@ export abstract class HyperlaneAppGovernor< })), ); } catch (error) { - console.error(`Error submitting calls on ${chain}: ${error}`); + console.error( + chalk.red(`Error submitting calls on ${chain}: ${error}`), + ); } } else { - console.log( - `Skipping submission of calls on ${chain} via ${SubmissionType[submissionType]}`, + console.info( + chalk.italic( + `Skipping submission of calls on ${chain} via ${SubmissionType[submissionType]}`, + ), ); } } @@ -184,6 +214,14 @@ export abstract class HyperlaneAppGovernor< } await sendCallsForType(SubmissionType.MANUAL, new ManualMultiSend(chain)); + + this.printSeparator(); + } + + private printSeparator() { + console.log( + `-------------------------------------------------------------------------------------------------------------------`, + ); } protected pushCall(chain: ChainName, call: AnnotatedCallData) { @@ -224,6 +262,7 @@ export abstract class HyperlaneAppGovernor< newCalls[inferredCall.chain] = newCalls[inferredCall.chain] || []; newCalls[inferredCall.chain].push({ submissionType: inferredCall.type, + icaTargetChain: inferredCall.icaTargetChain, ...inferredCall.call, }); }; @@ -236,7 +275,9 @@ export abstract class HyperlaneAppGovernor< } } catch (error) { console.error( - `Error inferring call submission types for chain ${chain}: ${error}`, + chalk.red( + `Error inferring call submission types for chain ${chain}: ${error}`, + ), ); } } @@ -244,78 +285,131 @@ export abstract class HyperlaneAppGovernor< this.calls = newCalls; } + /** + * Infers the submission type for a call that may be encoded for an Interchain Account (ICA). + * + * This function performs the following steps: + * 1. Checks if an ICA exists. If not, defaults to manual submission. + * 2. Retrieves the owner of the target contract. + * 3. Verifies if the owner is the ICA router. If not, defaults to manual submission. + * 4. Fetches the ICA configuration to determine the origin chain. + * 5. Prepares the call for remote execution via the ICA if all conditions are met. + * + * @param chain The chain where the call is to be executed + * @param call The call data to be executed + * @returns An InferredCall object with the appropriate submission type and details + */ protected async inferICAEncodedSubmissionType( chain: ChainName, call: AnnotatedCallData, ): Promise { const multiProvider = this.checker.multiProvider; const signer = multiProvider.getSigner(chain); - if (this.interchainAccount) { - const ownableAddress = call.to; - const ownable = Ownable__factory.connect(ownableAddress, signer); - const account = Ownable__factory.connect(await ownable.owner(), signer); - const localOwner = await account.owner(); - if (eqAddress(localOwner, this.interchainAccount.routerAddress(chain))) { - const accountConfig = await this.interchainAccount.getAccountConfig( - chain, - account.address, - ); - const origin = this.interchainAccount.multiProvider.getChainName( - accountConfig.origin, - ); - console.log( - `Inferred call for ICA remote owner ${bytes32ToAddress( - accountConfig.owner, - )} on ${origin}`, - ); - const callRemote = await this.interchainAccount.getCallRemote({ - chain: origin, - destination: chain, - innerCalls: [ - { - to: call.to, - data: call.data, - value: call.value?.toString() || '0', - }, - ], - config: accountConfig, - }); - if (!callRemote.to || !callRemote.data) { - return { - type: SubmissionType.MANUAL, - chain, - call, - }; - } - const encodedCall: AnnotatedCallData = { - to: callRemote.to, - data: callRemote.data, - value: callRemote.value, - description: `${call.description} - interchain account call from ${origin} to ${chain}`, - }; - const { type: subType } = await this.inferCallSubmissionType( - origin, - encodedCall, - (chain: ChainName, submitterAddress: Address) => { - // Require the submitter to be the owner of the ICA on the origin chain. - return ( - chain === origin && - eqAddress(bytes32ToAddress(accountConfig.owner), submitterAddress) - ); - }, - true, // Flag this as an ICA call + + // If there is no ICA, default to manual submission + if (!this.interchainAccount) { + return { + type: SubmissionType.MANUAL, + chain, + call, + }; + } + + // Get the account's owner + const ownableAddress = call.to; + const ownable = Ownable__factory.connect(ownableAddress, signer); + const account = Ownable__factory.connect(await ownable.owner(), signer); + const localOwner = await account.owner(); + + // If the account's owner is not the ICA router, default to manual submission + if (!eqAddress(localOwner, this.interchainAccount.routerAddress(chain))) { + console.info( + chalk.gray( + `Account's owner ${localOwner} is not ICA router. Defaulting to manual submission.`, + ), + ); + return { + type: SubmissionType.MANUAL, + chain, + call, + }; + } + + // Get the account's config + const accountConfig = await this.interchainAccount.getAccountConfig( + chain, + account.address, + ); + const origin = this.interchainAccount.multiProvider.getChainName( + accountConfig.origin, + ); + console.info( + chalk.gray( + `Inferred call for ICA remote owner ${bytes32ToAddress( + accountConfig.owner, + )} on ${origin} to ${chain}`, + ), + ); + + // Get the encoded call to the remote ICA + const callRemote = await this.interchainAccount.getCallRemote({ + chain: origin, + destination: chain, + innerCalls: [ + { + to: call.to, + data: call.data, + value: call.value?.toString() || '0', + }, + ], + config: accountConfig, + }); + + // If the call to the remote ICA is not valid, default to manual submission + if (!callRemote.to || !callRemote.data) { + return { + type: SubmissionType.MANUAL, + chain, + call, + }; + } + + // If the call to the remote ICA is valid, infer the submission type + const { description, expandedDescription } = call; + const encodedCall: AnnotatedCallData = { + to: callRemote.to, + data: callRemote.data, + value: callRemote.value, + description, + expandedDescription, + }; + + // Try to infer the submission type for the ICA call + const { type: subType } = await this.inferCallSubmissionType( + origin, + encodedCall, + (chain: ChainName, submitterAddress: Address) => { + // Require the submitter to be the owner of the ICA on the origin chain. + return ( + chain === origin && + eqAddress(bytes32ToAddress(accountConfig.owner), submitterAddress) ); - if (subType !== SubmissionType.MANUAL) { - return { - type: subType, - chain: origin, - call: encodedCall, - }; - } - } else { - console.log(`Account's owner ${localOwner} is not ICA router`); - } + }, + true, // Flag this as an ICA call + ); + + // If returned submission type is not MANUAL + // we'll return the inferred call with the ICA target chain + if (subType !== SubmissionType.MANUAL) { + return { + type: subType, + chain: origin, + call: encodedCall, + icaTargetChain: chain, + }; } + + // Else, default to manual submission return { type: SubmissionType.MANUAL, chain, @@ -323,6 +417,21 @@ export abstract class HyperlaneAppGovernor< }; } + /** + * Infers the submission type for a call. + * + * This function performs the following steps: + * 1. Checks if the transaction will succeed with the SIGNER. + * 2. Checks if the transaction will succeed with a SAFE. + * 3. If not already an ICA call, tries to infer an ICA call. + * 4. If the transaction will not succeed with SIGNER, SAFE, or ICA, defaults to MANUAL submission. + * + * @param chain The chain where the call is to be executed + * @param call The call data to be executed + * @param additionalTxSuccessCriteria An optional function to check additional success criteria for the transaction + * @param isICACall Flag to indicate if the call is already an ICA call + * @returns An InferredCall object with the appropriate submission type and details + */ protected async inferCallSubmissionType( chain: ChainName, call: AnnotatedCallData, @@ -336,120 +445,120 @@ export abstract class HyperlaneAppGovernor< const signer = multiProvider.getSigner(chain); const signerAddress = await signer.getAddress(); - const transactionSucceedsFromSender = async ( + // Check if the transaction will succeed with a given submitter address + const checkTransactionSuccess = async ( chain: ChainName, submitterAddress: Address, ): Promise => { - // The submitter needs to have enough balance to pay for the call. - // Surface a warning if the submitter's balance is insufficient, as this - // can result in fooling the tooling into thinking otherwise valid submission - // types are invalid. + // Check if the transaction has a value and if the submitter has enough balance if (call.value !== undefined) { - const submitterBalance = await multiProvider - .getProvider(chain) - .getBalance(submitterAddress); - if (submitterBalance.lt(call.value)) { - console.warn( - `Submitter ${submitterAddress} has an insufficient balance for the call and is likely to fail. Balance:`, - submitterBalance, - 'Balance required:', - call.value, - ); - } + await this.checkSubmitterBalance(chain, submitterAddress, call.value); + } + + // Check if the transaction has additional success criteria + if ( + additionalTxSuccessCriteria && + !additionalTxSuccessCriteria(chain, submitterAddress) + ) { + return false; } + // Check if the transaction will succeed with the signer try { - if ( - additionalTxSuccessCriteria && - !additionalTxSuccessCriteria(chain, submitterAddress) - ) { - return false; - } - // Will throw if the transaction fails await multiProvider.estimateGas(chain, call, submitterAddress); return true; - } catch (e) {} // eslint-disable-line no-empty - return false; + } catch (e) { + return false; + } }; - if (await transactionSucceedsFromSender(chain, signerAddress)) { - return { - type: SubmissionType.SIGNER, - chain, - call, - }; + // Check if the transaction will succeed with the SIGNER + if (await checkTransactionSuccess(chain, signerAddress)) { + return { type: SubmissionType.SIGNER, chain, call }; } - // 2. Check if the call will succeed via Gnosis Safe. + // Check if the transaction will succeed with a SAFE const safeAddress = this.checker.configMap[chain].ownerOverrides?._safeAddress; - if (typeof safeAddress === 'string') { - // 2a. Confirm that the signer is a Safe owner or delegate. - // This should implicitly check whether or not the owner is a gnosis - // safe. - if (!this.canPropose[chain].has(safeAddress)) { - try { - const canPropose = await canProposeSafeTransactions( - signerAddress, - chain, - multiProvider, - safeAddress, - ); - this.canPropose[chain].set(safeAddress, canPropose); - } catch (error) { - // if we hit this error, it's likely a custom safe chain - // so let's fallback to a manual submission - if ( - error instanceof Error && - (error.message.includes('Invalid MultiSend contract address') || - error.message.includes( - 'Invalid MultiSendCallOnly contract address', - )) - ) { - console.warn(`${error.message}: Setting submission type to MANUAL`); - return { - type: SubmissionType.MANUAL, - chain, - call, - }; - } else { - console.error( - `Failed to determine if signer can propose safe transactions on ${chain}. Setting submission type to MANUAL. Error: ${error}`, - ); - return { - type: SubmissionType.MANUAL, - chain, - call, - }; - } - } - } - - // 2b. Check if calling from the owner/safeAddress will succeed. + // Check if the safe can propose transactions + const canProposeSafe = await this.checkSafeProposalEligibility( + chain, + signerAddress, + safeAddress, + ); if ( - this.canPropose[chain].get(safeAddress) && - (await transactionSucceedsFromSender(chain, safeAddress)) + canProposeSafe && + (await checkTransactionSuccess(chain, safeAddress)) ) { - return { - type: SubmissionType.SAFE, - chain, - call, - }; + // If the transaction will succeed with the safe, return the inferred call + return { type: SubmissionType.SAFE, chain, call }; } } - // Only try ICA encoding if this isn't already an ICA call + // If we're not already an ICA call, try to infer an ICA call if (!isICACall) { return this.inferICAEncodedSubmissionType(chain, call); } - // If it is an ICA call and we've reached this point, default to manual submission - return { - type: SubmissionType.MANUAL, - chain, - call, - }; + // If the transaction will not succeed with SIGNER, SAFE or ICA, default to MANUAL submission + return { type: SubmissionType.MANUAL, chain, call }; + } + + private async checkSubmitterBalance( + chain: ChainName, + submitterAddress: Address, + requiredValue: BigNumber, + ): Promise { + const submitterBalance = await this.checker.multiProvider + .getProvider(chain) + .getBalance(submitterAddress); + if (submitterBalance.lt(requiredValue)) { + console.warn( + chalk.yellow( + `Submitter ${submitterAddress} has an insufficient balance for the call and is likely to fail. Balance: ${submitterBalance}, Balance required: ${requiredValue}`, + ), + ); + } + } + + private async checkSafeProposalEligibility( + chain: ChainName, + signerAddress: Address, + safeAddress: string, + ): Promise { + if (!this.canPropose[chain].has(safeAddress)) { + try { + const canPropose = await canProposeSafeTransactions( + signerAddress, + chain, + this.checker.multiProvider, + safeAddress, + ); + this.canPropose[chain].set(safeAddress, canPropose); + } catch (error) { + if ( + error instanceof Error && + (error.message.includes('Invalid MultiSend contract address') || + error.message.includes( + 'Invalid MultiSendCallOnly contract address', + )) + ) { + console.warn( + chalk.yellow(`${error.message}: Setting submission type to MANUAL`), + ); + return false; + } else { + console.error( + chalk.red( + `Failed to determine if signer can propose safe transactions on ${chain}. Setting submission type to MANUAL. Error: ${error}`, + ), + ); + return false; + } + } + } + return this.canPropose[chain].get(safeAddress) || false; } handleOwnerViolation(violation: OwnerViolation) { diff --git a/typescript/infra/src/govern/HyperlaneCoreGovernor.ts b/typescript/infra/src/govern/HyperlaneCoreGovernor.ts index 61152058a..b6df69f4f 100644 --- a/typescript/infra/src/govern/HyperlaneCoreGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneCoreGovernor.ts @@ -1,3 +1,4 @@ +import chalk from 'chalk'; import { BigNumber } from 'ethers'; import { @@ -76,7 +77,7 @@ export class HyperlaneCoreGovernor extends HyperlaneAppGovernor< return this.handleMailboxViolation(violation as MailboxViolation); } case CoreViolationType.ValidatorAnnounce: { - console.warn('Ignoring ValidatorAnnounce violation'); + console.warn(chalk.yellow('Ignoring ValidatorAnnounce violation')); return undefined; } case ViolationType.ProxyAdmin: { diff --git a/typescript/infra/src/govern/ProxiedRouterGovernor.ts b/typescript/infra/src/govern/ProxiedRouterGovernor.ts index 304f20761..d07c55395 100644 --- a/typescript/infra/src/govern/ProxiedRouterGovernor.ts +++ b/typescript/infra/src/govern/ProxiedRouterGovernor.ts @@ -75,9 +75,10 @@ export class ProxiedRouterGovernor< [expectedDomains, expectedAddresses], ), value: BigNumber.from(0), - description: `Updating routers in ${violation.contract.address} for ${ - expectedDomains.length - } remote chains:\n${stringifyObject(violation.routerDiff, 'yaml')}`, + description: `Updating routers in ${violation.contract.address} for ${expectedDomains.length} remote chains`, + expandedDescription: `Updating routers for chains ${Object.keys( + violation.routerDiff, + ).join(', ')}:\n${stringifyObject(violation.routerDiff)}`, }, }; } diff --git a/typescript/infra/src/govern/multisend.ts b/typescript/infra/src/govern/multisend.ts index 41e989018..0b3792424 100644 --- a/typescript/infra/src/govern/multisend.ts +++ b/typescript/infra/src/govern/multisend.ts @@ -1,6 +1,7 @@ import SafeApiKit from '@safe-global/api-kit'; import Safe from '@safe-global/protocol-kit'; import { SafeTransaction } from '@safe-global/safe-core-sdk-types'; +import chalk from 'chalk'; import { ChainName, MultiProvider } from '@hyperlane-xyz/sdk'; import { @@ -36,7 +37,7 @@ export class SignerMultiSend extends MultiSend { gasLimit: addBufferToGasLimit(estimate), ...call, }); - console.log(`confirmed tx ${receipt.transactionHash}`); + console.log(chalk.green(`Confirmed tx ${receipt.transactionHash}`)); } } } @@ -74,8 +75,10 @@ export class SafeMultiSend extends MultiSend { // If the multiSend address is the same as the safe address, we need to // propose the transactions individually. See: gnosisSafe.js in the SDK. if (eqAddress(safeSdk.getMultiSendAddress(), this.safeAddress)) { - console.log( - `MultiSend contract not deployed on ${this.chain}. Proposing transactions individually.`, + console.info( + chalk.gray( + `MultiSend contract not deployed on ${this.chain}. Proposing transactions individually.`, + ), ); await this.proposeIndividualTransactions(calls, safeSdk, safeService); } else { diff --git a/typescript/infra/src/utils/safe.ts b/typescript/infra/src/utils/safe.ts index 47d851dc1..ad2104ddb 100644 --- a/typescript/infra/src/utils/safe.ts +++ b/typescript/infra/src/utils/safe.ts @@ -5,6 +5,7 @@ import { MetaTransactionData, SafeTransaction, } from '@safe-global/safe-core-sdk-types'; +import chalk from 'chalk'; import { ethers } from 'ethers'; import { @@ -72,7 +73,9 @@ export async function proposeSafeTransaction( senderSignature: senderSignature.data, }); - console.log(`Proposed transaction on ${chain} with hash ${safeTxHash}`); + console.log( + chalk.green(`Proposed transaction on ${chain} with hash ${safeTxHash}`), + ); } export async function deleteAllPendingSafeTxs( @@ -91,7 +94,9 @@ export async function deleteAllPendingSafeTxs( }); if (!pendingTxsResponse.ok) { - console.error(`Failed to fetch pending transactions for ${safeAddress}`); + console.error( + chalk.red(`Failed to fetch pending transactions for ${safeAddress}`), + ); return; } @@ -126,7 +131,9 @@ export async function deleteSafeTx( }); if (!txDetailsResponse.ok) { - console.error(`Failed to fetch transaction details for ${safeTxHash}`); + console.error( + chalk.red(`Failed to fetch transaction details for ${safeTxHash}`), + ); return; } @@ -134,7 +141,7 @@ export async function deleteSafeTx( const proposer = txDetails.proposer; if (!proposer) { - console.error(`No proposer found for transaction ${safeTxHash}`); + console.error(chalk.red(`No proposer found for transaction ${safeTxHash}`)); return; } @@ -142,7 +149,9 @@ export async function deleteSafeTx( const signerAddress = await signer.getAddress(); if (proposer !== signerAddress) { console.log( - `Skipping deletion of transaction ${safeTxHash} proposed by ${proposer}`, + chalk.italic( + `Skipping deletion of transaction ${safeTxHash} proposed by ${proposer}`, + ), ); return; } @@ -192,17 +201,23 @@ export async function deleteSafeTx( }); if (res.status === 204) { - console.log(`Successfully deleted transaction ${safeTxHash} on ${chain}`); + console.log( + chalk.green( + `Successfully deleted transaction ${safeTxHash} on ${chain}`, + ), + ); return; } const errorBody = await res.text(); console.error( - `Failed to delete transaction ${safeTxHash} on ${chain}: Status ${res.status} ${res.statusText}. Response body: ${errorBody}`, + chalk.red( + `Failed to delete transaction ${safeTxHash} on ${chain}: Status ${res.status} ${res.statusText}. Response body: ${errorBody}`, + ), ); } catch (error) { console.error( - `Failed to delete transaction ${safeTxHash} on ${chain}:`, + chalk.red(`Failed to delete transaction ${safeTxHash} on ${chain}:`), error, ); } From 60ab32e88474ecdd21cf29b730034e9fa514fc18 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:48:44 +0100 Subject: [PATCH 045/224] feat: WIF warp route artifacts (#4517) --- .../warp-routes/eclipsewif/program-ids.json | 10 ++++++++++ .../warp-routes/eclipsewif/token-config.json | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/program-ids.json create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/token-config.json diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/program-ids.json new file mode 100644 index 000000000..b9bd29d58 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/program-ids.json @@ -0,0 +1,10 @@ +{ + "eclipsemainnet": { + "hex": "0x5766ab957c42d24f5071e32c56d07c4b5fcce7ccba0cc9a67b0025b863b65d7b", + "base58": "6tBGmKNxirxBYnm9khkaTtcr2fhJ9YviCgRm1RWM8NJv" + }, + "solanamainnet": { + "hex": "0xb0dda3a11775c3eebae6c89416039b3183e46964b72d82404d59f6f5e9e9c19f", + "base58": "CuQmsT4eSF4dYiiGUGYYQxJ7c58pUAD5ADE3BbFGzQKx" + } +} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/token-config.json new file mode 100644 index 000000000..5d5ab1a54 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipsewif/token-config.json @@ -0,0 +1,17 @@ +{ + "solanamainnet": { + "type": "collateral", + "decimals": 6, + "interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF", + "token": "EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm", + "splTokenProgram": "token" + }, + "eclipsemainnet": { + "type": "synthetic", + "decimals": 6, + "name": "dogwifhat", + "symbol": "WIF", + "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/9b9b07c9df8cd326e097d87aec67128832221407/deployments/warp_routes/WIF/metadata.json", + "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" + } +} From daa9cbc41c8163b519dc5a39234cf60549cd5baf Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:10:01 +0100 Subject: [PATCH 046/224] feat: SVM routes tooling (#4521) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/cli/package.json | 2 +- .../getEthereumEclipseTETHWarpConfig.ts | 33 ++++++++++++++++++ .../getEthereumEclipseUSDCWarpConfig.ts | 34 +++++++++++++++++++ typescript/infra/config/warp.ts | 6 ++++ typescript/infra/package.json | 2 +- typescript/widgets/package.json | 2 +- yarn.lock | 16 +++++++-- 7 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseTETHWarpConfig.ts create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseUSDCWarpConfig.ts diff --git a/typescript/cli/package.json b/typescript/cli/package.json index 1d0e23a2b..eca751c13 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -5,7 +5,7 @@ "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", - "@hyperlane-xyz/registry": "4.1.0", + "@hyperlane-xyz/registry": "4.3.2", "@hyperlane-xyz/sdk": "5.2.0", "@hyperlane-xyz/utils": "5.2.0", "@inquirer/prompts": "^3.0.0", diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseTETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseTETHWarpConfig.ts new file mode 100644 index 000000000..57ed42891 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseTETHWarpConfig.ts @@ -0,0 +1,33 @@ +import { ethers } from 'ethers'; + +import { + ChainMap, + RouterConfig, + TokenRouterConfig, + TokenType, +} from '@hyperlane-xyz/sdk'; + +import { DEPLOYER } from '../../owners.js'; + +export const getEthereumEclipseTETHWarpConfig = async ( + routerConfig: ChainMap, +): Promise> => { + // @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig + const eclipsemainnet: TokenRouterConfig = { + type: TokenType.synthetic, + foreignDeployment: 'BJa3fPvvjKx8gRCWunoSrWBbsmieub37gsGpjp4BfTfW', + gas: 300_000, + }; + + const ethereum: TokenRouterConfig = { + ...routerConfig.ethereum, + type: TokenType.collateral, + interchainSecurityModule: ethers.constants.AddressZero, + token: '0x19e099B7aEd41FA52718D780dDA74678113C0b32', + }; + + return { + eclipsemainnet, + ethereum, + }; +}; diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseUSDCWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseUSDCWarpConfig.ts new file mode 100644 index 000000000..1d39abb12 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumEclipseUSDCWarpConfig.ts @@ -0,0 +1,34 @@ +import { ethers } from 'ethers'; + +import { + ChainMap, + RouterConfig, + TokenRouterConfig, + TokenType, +} from '@hyperlane-xyz/sdk'; + +import { tokens } from '../../../../../src/config/warp.js'; +import { DEPLOYER } from '../../owners.js'; + +export const getEthereumEclipseUSDCWarpConfig = async ( + routerConfig: ChainMap, +): Promise> => { + // @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig + const eclipsemainnet: TokenRouterConfig = { + type: TokenType.synthetic, + foreignDeployment: 'D6k6T3G74ij6atCtBiWBs5TbFa1hFVcrFUSGZHuV7q3Z', + gas: 300_000, + }; + + const ethereum: TokenRouterConfig = { + ...routerConfig.ethereum, + type: TokenType.collateral, + interchainSecurityModule: ethers.constants.AddressZero, + token: tokens.ethereum.USDC, + }; + + return { + eclipsemainnet, + ethereum, + }; +}; diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 8f2ea0083..9f1e00879 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -11,6 +11,8 @@ import { EnvironmentConfig } from '../src/config/environment.js'; import { getAncient8EthereumUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getAncient8EthereumUSDCWarpConfig.js'; import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronEclipWarpConfig.js'; import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js'; +import { getEthereumEclipseTETHWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumEclipseTETHWarpConfig.js'; +import { getEthereumEclipseUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumEclipseUSDCWarpConfig.js'; import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js'; import { getEthereumInevmUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDTWarpConfig.js'; import { getEthereumVictionETHWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionETHWarpConfig.js'; @@ -27,6 +29,8 @@ export enum WarpRouteIds { ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', EthereumInevmUSDC = 'USDC/ethereum-inevm', EthereumInevmUSDT = 'USDT/ethereum-inevm', + EthereumEclipseTETH = 'tETH/eclipsemainnet-ethereum', + EthereumEclipseUSDC = 'USDC/eclipsemainnet-ethereum-solanamainnet', EthereumVictionETH = 'ETH/ethereum-viction', EthereumVictionUSDC = 'USDC/ethereum-viction', EthereumVictionUSDT = 'USDT/ethereum-viction', @@ -56,6 +60,8 @@ export const warpConfigGetterMap: Record< [WarpRouteIds.EthereumVictionUSDC]: getEthereumVictionUSDCWarpConfig, [WarpRouteIds.EthereumVictionUSDT]: getEthereumVictionUSDTWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, + [WarpRouteIds.EthereumEclipseTETH]: getEthereumEclipseTETHWarpConfig, + [WarpRouteIds.EthereumEclipseUSDC]: getEthereumEclipseUSDCWarpConfig, }; export async function getWarpConfig( diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 9b4fc4362..3ac5dfb8b 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -14,7 +14,7 @@ "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", "@hyperlane-xyz/helloworld": "5.2.0", - "@hyperlane-xyz/registry": "4.1.0", + "@hyperlane-xyz/registry": "4.3.2", "@hyperlane-xyz/sdk": "5.2.0", "@hyperlane-xyz/utils": "5.2.0", "@inquirer/prompts": "^5.3.8", diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 96fab9262..01e187ff9 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -7,7 +7,7 @@ "react-dom": "^18" }, "dependencies": { - "@hyperlane-xyz/registry": "4.1.0", + "@hyperlane-xyz/registry": "4.3.2", "@hyperlane-xyz/sdk": "5.2.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 2f9482755..b05360c35 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7590,7 +7590,7 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.577.0" "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" - "@hyperlane-xyz/registry": "npm:4.1.0" + "@hyperlane-xyz/registry": "npm:4.3.2" "@hyperlane-xyz/sdk": "npm:5.2.0" "@hyperlane-xyz/utils": "npm:5.2.0" "@inquirer/prompts": "npm:^3.0.0" @@ -7732,7 +7732,7 @@ __metadata: "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" "@hyperlane-xyz/helloworld": "npm:5.2.0" - "@hyperlane-xyz/registry": "npm:4.1.0" + "@hyperlane-xyz/registry": "npm:4.3.2" "@hyperlane-xyz/sdk": "npm:5.2.0" "@hyperlane-xyz/utils": "npm:5.2.0" "@inquirer/prompts": "npm:^5.3.8" @@ -7800,6 +7800,16 @@ __metadata: languageName: node linkType: hard +"@hyperlane-xyz/registry@npm:4.3.2": + version: 4.3.2 + resolution: "@hyperlane-xyz/registry@npm:4.3.2" + dependencies: + yaml: "npm:2.4.5" + zod: "npm:^3.21.2" + checksum: 7b1ff07074e4499f74a4c75dbbf0b7e641b3610bfc2a67785db724748d887d7b03c9dc9738b790cb56e008d6453789432c863f3b251498f77c931f196b9dab86 + languageName: node + linkType: hard + "@hyperlane-xyz/sdk@npm:5.2.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" @@ -7874,7 +7884,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: - "@hyperlane-xyz/registry": "npm:4.1.0" + "@hyperlane-xyz/registry": "npm:4.3.2" "@hyperlane-xyz/sdk": "npm:5.2.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" From c35b00554f9cba94032e0ab20fe9ba3047e4740e Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Thu, 19 Sep 2024 14:49:49 +0100 Subject: [PATCH 047/224] feat(infra): use latest image tag for the check-warp-deploy cron job config (#4416) ### Description - use latest image tag for the check-warp-deploy cron job config ### Testing Manual --- .../infra/config/environments/mainnet3/warp/checkWarpDeploy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts b/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts index 262e47278..866de41f9 100644 --- a/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts +++ b/typescript/infra/config/environments/mainnet3/warp/checkWarpDeploy.ts @@ -4,7 +4,7 @@ import { environment } from '../chains.js'; export const checkWarpDeployConfig: CheckWarpDeployConfig = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '7ce7aef-20240912-090321', + tag: 'main', }, namespace: environment, cronSchedule: '0 15 * * *', // set to 3pm utc every day From fd2c3aac26ad836bb04c0b6dc97151cb60de1454 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:21:19 +0100 Subject: [PATCH 048/224] chore: make github-proxy private (#4523) chore: make github-proxy private --- typescript/github-proxy/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index 827228b33..55c61baea 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -2,6 +2,7 @@ "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", "version": "5.2.0", + "private": true, "scripts": { "deploy": "wrangler deploy", "deploy:staging": "wrangler deploy --env staging", From f81294ac1661b4588b667b22c8491d0df1decb35 Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Thu, 19 Sep 2024 16:05:05 +0100 Subject: [PATCH 049/224] feat(infra): use private RPCs for warp monitor service (#4425) ### Description - support private RPCs for warp monitor service ### Backward compatibility Yes ### Testing Manual --- .../configGetters/getRenzoEZETHWarpConifg.ts | 5 +-- .../helm/warp-routes/templates/_helpers.tpl | 12 +++++ .../templates/env-var-external-secret.yaml | 44 +++++++++++++++++++ typescript/infra/helm/warp-routes/values.yaml | 3 ++ .../warp-routes/deploy-warp-monitor.ts | 13 ++++-- .../monitor-warp-routes-balances.ts | 36 ++++++++------- typescript/infra/src/utils/gcloud.ts | 3 ++ typescript/infra/src/warp/helm.ts | 7 ++- 8 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts index cd182e4c8..2203a8c42 100644 --- a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts @@ -1,14 +1,13 @@ import { ChainMap, IsmType, - RouterConfig, TokenRouterConfig, TokenType, buildAggregationIsmConfigs, } from '@hyperlane-xyz/sdk'; import { symmetricDifference } from '@hyperlane-xyz/utils'; -import { getRegistry } from '../../chains.js'; +import { getRegistry as getMainnet3Registry } from '../../chains.js'; const lockbox = '0xC8140dA31E6bCa19b287cC35531c2212763C2059'; const xERC20 = '0x2416092f143378750bb29b79eD961ab195CcEea5'; @@ -118,7 +117,7 @@ const ezEthSafes: Record = { export const getRenzoEZETHWarpConfig = async (): Promise< ChainMap > => { - const registry = await getRegistry(); + const registry = await getMainnet3Registry(); const validatorDiff = symmetricDifference( new Set(chainsToDeploy), diff --git a/typescript/infra/helm/warp-routes/templates/_helpers.tpl b/typescript/infra/helm/warp-routes/templates/_helpers.tpl index 17a9174d5..52bc42a86 100644 --- a/typescript/infra/helm/warp-routes/templates/_helpers.tpl +++ b/typescript/infra/helm/warp-routes/templates/_helpers.tpl @@ -53,6 +53,13 @@ app.kubernetes.io/name: {{ include "hyperlane.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} +{{/* +The name of the ClusterSecretStore +*/}} +{{- define "hyperlane.cluster-secret-store.name" -}} +{{- default "external-secrets-gcp-cluster-secret-store" .Values.externalSecrets.clusterSecretStore }} +{{- end }} + {{/* The warp-routes container */}} @@ -70,4 +77,9 @@ The warp-routes container - "10000" - -f - {{ .Values.configFilePath }} + - -e + - {{ .Values.environment}} + envFrom: + - secretRef: + name: {{ include "hyperlane.fullname" . }}-secret {{- end }} diff --git a/typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml b/typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml new file mode 100644 index 000000000..e7a74b714 --- /dev/null +++ b/typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml @@ -0,0 +1,44 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ include "hyperlane.fullname" . }}-external-secret + labels: + {{- include "hyperlane.labels" . | nindent 4 }} +spec: + secretStoreRef: + name: {{ include "hyperlane.cluster-secret-store.name" . }} + kind: ClusterSecretStore + refreshInterval: "1h" + # The secret that will be created + target: + name: {{ include "hyperlane.fullname" . }}-secret + template: + type: Opaque + metadata: + labels: + {{- include "hyperlane.labels" . | nindent 10 }} + annotations: + update-on-redeploy: "{{ now }}" + data: + GCP_SECRET_OVERRIDES_ENABLED: "true" +{{/* + * For each network, create an environment variable with the RPC endpoint. + * The templating of external-secrets will use the data section below to know how + * to replace the correct value in the created secret. + */}} + {{- range .Values.hyperlane.chains }} + GCP_SECRET_OVERRIDE_{{ $.Values.hyperlane.runEnv | upper }}_RPC_ENDPOINTS_{{ . | upper }}: {{ printf "'{{ .%s_rpcs | toString }}'" . }} + {{- end }} + data: + - secretKey: deployer_key + remoteRef: + key: {{ printf "hyperlane-%s-key-deployer" .Values.hyperlane.runEnv }} +{{/* + * For each network, load the secret in GCP secret manager with the form: environment-rpc-endpoint-network, + * and associate it with the secret key networkname_rpc. + */}} + {{- range .Values.hyperlane.chains }} + - secretKey: {{ printf "%s_rpcs" . }} + remoteRef: + key: {{ printf "%s-rpc-endpoints-%s" $.Values.hyperlane.runEnv . }} + {{- end }} diff --git a/typescript/infra/helm/warp-routes/values.yaml b/typescript/infra/helm/warp-routes/values.yaml index c5d7c35e7..a7a09d817 100644 --- a/typescript/infra/helm/warp-routes/values.yaml +++ b/typescript/infra/helm/warp-routes/values.yaml @@ -4,5 +4,8 @@ image: hyperlane: runEnv: mainnet3 context: hyperlane + chains: [] nameOverride: '' fullnameOverride: '' +externalSecrets: + clusterSecretStore: diff --git a/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts b/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts index 009323ad6..95a749ace 100644 --- a/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts +++ b/typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts @@ -1,8 +1,9 @@ import yargs from 'yargs'; +import { Contexts } from '../../config/contexts.js'; import { HelmCommand } from '../../src/utils/helm.js'; import { WarpRouteMonitorHelmManager } from '../../src/warp/helm.js'; -import { assertCorrectKubeContext } from '../agent-utils.js'; +import { assertCorrectKubeContext, getAgentConfig } from '../agent-utils.js'; import { getEnvironmentConfig } from '../core-utils.js'; async function main() { @@ -16,9 +17,15 @@ async function main() { .string('filePath') .parse(); - await assertCorrectKubeContext(getEnvironmentConfig('mainnet3')); + const environment = 'mainnet3'; + await assertCorrectKubeContext(getEnvironmentConfig(environment)); + const agentConfig = getAgentConfig(Contexts.Hyperlane, environment); - const helmManager = new WarpRouteMonitorHelmManager(filePath, 'mainnet3'); + const helmManager = new WarpRouteMonitorHelmManager( + filePath, + environment, + agentConfig.environmentChainNames, + ); await helmManager.runHelmCommand(HelmCommand.InstallOrUpgrade); } diff --git a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts index 478dfc232..e06031096 100644 --- a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts +++ b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts @@ -1,7 +1,6 @@ import { SystemProgram } from '@solana/web3.js'; import { ethers } from 'ethers'; import { Gauge, Registry } from 'prom-client'; -import yargs from 'yargs'; import { HypXERC20Lockbox__factory, @@ -12,6 +11,7 @@ import { import { ERC20__factory } from '@hyperlane-xyz/core'; import { ChainMap, + ChainMetadata, ChainName, CosmNativeTokenAdapter, CwNativeTokenAdapter, @@ -28,9 +28,10 @@ import { rootLogger, } from '@hyperlane-xyz/utils'; -import { getChainMetadata } from '../../config/registry.js'; import { startMetricsServer } from '../../src/utils/metrics.js'; import { readYaml } from '../../src/utils/utils.js'; +import { getArgs } from '../agent-utils.js'; +import { getEnvironmentConfig } from '../core-utils.js'; const logger = rootLogger.child({ module: 'warp-balance-monitor' }); @@ -76,7 +77,7 @@ export function readWarpRouteConfig(filePath: string) { } async function main(): Promise { - const { checkFrequency, filePath } = await yargs(process.argv.slice(2)) + const { checkFrequency, filePath, environment } = await getArgs() .describe('checkFrequency', 'frequency to check balances in ms') .demandOption('checkFrequency') .alias('v', 'checkFrequency') // v as in Greek letter nu @@ -95,6 +96,10 @@ async function main(): Promise { const tokenConfig: WarpRouteConfig = readWarpRouteConfig(filePath).data.config; + const envConfig = getEnvironmentConfig(environment); + const registry = await envConfig.getRegistry(); + const chainMetadata = await registry.getMetadata(); + // TODO: eventually support token balance checks for xERC20 token type also if ( Object.values(tokenConfig).some( @@ -103,9 +108,9 @@ async function main(): Promise { token.type === TokenType.XERC20Lockbox, ) ) { - await checkXERC20Limits(checkFrequency, tokenConfig); + await checkXERC20Limits(checkFrequency, tokenConfig, chainMetadata); } else { - await checkTokenBalances(checkFrequency, tokenConfig); + await checkTokenBalances(checkFrequency, tokenConfig, chainMetadata); } return true; @@ -299,8 +304,9 @@ export function updateXERC20LimitsMetrics(xERC20Limits: ChainMap) { async function getXERC20Limits( tokenConfig: WarpRouteConfig, + chainMetadata: ChainMap, ): Promise> { - const multiProtocolProvider = new MultiProtocolProvider(getChainMetadata()); + const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); const output = objMap( tokenConfig, @@ -330,17 +336,13 @@ async function getXERC20Limits( const xerc20 = IXERC20__factory.connect(xerc20Address, provider); return getXERC20Limit(routerAddress, xerc20, token.decimals); } + default: + throw new Error(`Unsupported token type ${token.type}`); } - break; } + default: + throw new Error(`Unsupported protocol type ${token.protocolType}`); } - return { - chain: chain, - mint: 0, - mintMax: 0, - burn: 0, - burnMax: 0, - }; }, ); @@ -367,10 +369,11 @@ const getXERC20Limit = async ( async function checkXERC20Limits( checkFrequency: number, tokenConfig: WarpRouteConfig, + chainMetadata: ChainMap, ) { setInterval(async () => { try { - const xERC20Limits = await getXERC20Limits(tokenConfig); + const xERC20Limits = await getXERC20Limits(tokenConfig, chainMetadata); logger.info('xERC20 Limits:', xERC20Limits); updateXERC20LimitsMetrics(xERC20Limits); } catch (e) { @@ -382,9 +385,10 @@ async function checkXERC20Limits( async function checkTokenBalances( checkFrequency: number, tokenConfig: WarpRouteConfig, + chainMetadata: ChainMap, ) { logger.info('Starting Warp Route balance monitor'); - const multiProtocolProvider = new MultiProtocolProvider(getChainMetadata()); + const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); setInterval(async () => { try { diff --git a/typescript/infra/src/utils/gcloud.ts b/typescript/infra/src/utils/gcloud.ts index 56d913b7c..3fc157b4c 100644 --- a/typescript/infra/src/utils/gcloud.ts +++ b/typescript/infra/src/utils/gcloud.ts @@ -35,6 +35,7 @@ export async function fetchGCPSecret( ); output = envVarOverride; } else { + debugLog(`Fetching GCP secret with name ${secretName}`); output = await fetchLatestGCPSecret(secretName); } @@ -74,8 +75,10 @@ function tryGCPSecretFromEnvVariable(gcpSecretName: string) { process.env.GCP_SECRET_OVERRIDES_ENABLED && process.env.GCP_SECRET_OVERRIDES_ENABLED.length > 0; if (!overridingEnabled) { + debugLog('GCP secret overrides disabled'); return undefined; } + debugLog('GCP secret overrides enabled'); const overrideEnvVarName = `GCP_SECRET_OVERRIDE_${gcpSecretName .replaceAll('-', '_') .toUpperCase()}`; diff --git a/typescript/infra/src/warp/helm.ts b/typescript/infra/src/warp/helm.ts index 779a53584..f1207f9a6 100644 --- a/typescript/infra/src/warp/helm.ts +++ b/typescript/infra/src/warp/helm.ts @@ -13,6 +13,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager { constructor( readonly configFilePath: string, readonly runEnv: DeployEnvironment, + readonly environmentChainNames: string[], ) { super(); } @@ -26,10 +27,14 @@ export class WarpRouteMonitorHelmManager extends HelmManager { return { image: { repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '38ff1c4-20240823-093934', + tag: 'fce6adf-20240905-094435', }, configFilePath: pathRelativeToMonorepoRoot, fullnameOverride: this.helmReleaseName, + environment: this.runEnv, + hyperlane: { + chains: this.environmentChainNames, + }, }; } From 52c041862ec410c70384e60e7b96fef1a28c3d1a Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 19 Sep 2024 16:21:53 +0100 Subject: [PATCH 050/224] fix: stop transferring metadata and metadata pointer authorities (#4527) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/sealevel/client/src/warp_route.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rust/sealevel/client/src/warp_route.rs b/rust/sealevel/client/src/warp_route.rs index 723b1b592..3cb3328c1 100644 --- a/rust/sealevel/client/src/warp_route.rs +++ b/rust/sealevel/client/src/warp_route.rs @@ -365,8 +365,9 @@ impl RouterDeployer for WarpRouteDeployer { .expect("Failed to run command"); println!("initialized metadata. Status: {status}"); - // Burn the metadata pointer, metadata, and mint authorities by moving them to the mint - let authorities_to_transfer = &["metadata-pointer", "metadata", "mint"]; + // Move the mint authority to the mint account. + // The deployer key will still hold the metadata pointer and metadata authorities. + let authorities_to_transfer = &["mint"]; for authority in authorities_to_transfer { println!("Transferring authority: {authority} to the mint account {mint_account}"); From eb5afcf3ebe947494aa949a43e3b8dfda46d0701 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 19 Sep 2024 12:43:06 -0400 Subject: [PATCH 051/224] fix: native value covers message value in HypNative (#4526) ### Description `HypNative.transferRemote` overload checks that the native `msg.value` deposited covers the warp message `amount` in addition to checking the mailbox post-dispatch fee is covered. ### Backward compatibility No, applies to net new `HypNative` and `HypNativeScaled` deployments ### Testing Unit Tests --- .changeset/curvy-elephants-breathe.md | 5 ++ solidity/contracts/token/HypNative.sol | 24 ++++++++++ .../token/extensions/HypNativeScaled.sol | 25 ++++++++++ solidity/test/token/HypERC20.t.sol | 46 ++++++++++++++++++- solidity/test/token/HypNativeScaled.t.sol | 41 ++++++++++++++++- 5 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 .changeset/curvy-elephants-breathe.md diff --git a/.changeset/curvy-elephants-breathe.md b/.changeset/curvy-elephants-breathe.md new file mode 100644 index 000000000..c56062714 --- /dev/null +++ b/.changeset/curvy-elephants-breathe.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': patch +--- + +Patch `HypNative` with hook overrides `transferRemote` behavior diff --git a/solidity/contracts/token/HypNative.sol b/solidity/contracts/token/HypNative.sol index 5b620d00a..cfb526fa4 100644 --- a/solidity/contracts/token/HypNative.sol +++ b/solidity/contracts/token/HypNative.sol @@ -48,6 +48,30 @@ contract HypNative is TokenRouter { return _transferRemote(_destination, _recipient, _amount, _hookPayment); } + /** + * @inheritdoc TokenRouter + * @dev uses (`msg.value` - `_amount`) as hook payment. + */ + function transferRemote( + uint32 _destination, + bytes32 _recipient, + uint256 _amount, + bytes calldata _hookMetadata, + address _hook + ) external payable virtual override returns (bytes32 messageId) { + require(msg.value >= _amount, "Native: amount exceeds msg.value"); + uint256 _hookPayment = msg.value - _amount; + return + _transferRemote( + _destination, + _recipient, + _amount, + _hookPayment, + _hookMetadata, + _hook + ); + } + function balanceOf( address _account ) external view override returns (uint256) { diff --git a/solidity/contracts/token/extensions/HypNativeScaled.sol b/solidity/contracts/token/extensions/HypNativeScaled.sol index 88ccaa468..ad129fce8 100644 --- a/solidity/contracts/token/extensions/HypNativeScaled.sol +++ b/solidity/contracts/token/extensions/HypNativeScaled.sol @@ -38,6 +38,31 @@ contract HypNativeScaled is HypNative { ); } + /** + * @inheritdoc TokenRouter + * @dev uses (`msg.value` - `_amount`) as hook payment. + */ + function transferRemote( + uint32 _destination, + bytes32 _recipient, + uint256 _amount, + bytes calldata _hookMetadata, + address _hook + ) external payable override returns (bytes32 messageId) { + require(msg.value >= _amount, "Native: amount exceeds msg.value"); + uint256 _hookPayment = msg.value - _amount; + uint256 _scaledAmount = _amount / scale; + return + _transferRemote( + _destination, + _recipient, + _scaledAmount, + _hookPayment, + _hookMetadata, + _hook + ); + } + /** * @dev Sends scaled `_amount` (multiplied by `scale`) to `_recipient`. * @inheritdoc TokenRouter diff --git a/solidity/test/token/HypERC20.t.sol b/solidity/test/token/HypERC20.t.sol index ce50c611e..9c068b239 100644 --- a/solidity/test/token/HypERC20.t.sol +++ b/solidity/test/token/HypERC20.t.sol @@ -49,7 +49,7 @@ abstract contract HypTokenTest is Test { uint256 internal constant TOTAL_SUPPLY = 1_000_000e18; uint256 internal REQUIRED_VALUE; // initialized in setUp uint256 internal constant GAS_LIMIT = 10_000; - uint256 internal constant TRANSFER_AMT = 100e18; + uint256 internal TRANSFER_AMT = 100e18; string internal constant NAME = "HyperlaneInu"; string internal constant SYMBOL = "HYP"; address internal constant ALICE = address(0x1); @@ -640,7 +640,25 @@ contract HypNativeTest is HypTokenTest { _enrollRemoteTokenRouter(); } - function testInitialize_revert_ifAlreadyInitialized() public {} + function testTransfer_withHookSpecified( + uint256 fee, + bytes calldata metadata + ) public override { + TestPostDispatchHook hook = new TestPostDispatchHook(); + hook.setFee(fee); + + uint256 value = REQUIRED_VALUE + TRANSFER_AMT; + + vm.prank(ALICE); + primaryToken.approve(address(localToken), TRANSFER_AMT); + bytes32 messageId = _performRemoteTransferWithHook( + value, + TRANSFER_AMT, + address(hook), + metadata + ); + assertTrue(hook.messageDispatched(messageId)); + } function testRemoteTransfer() public { _performRemoteTransferWithEmit( @@ -668,4 +686,28 @@ contract HypNativeTest is HypTokenTest { TRANSFER_AMT + GAS_LIMIT * igp.gasPrice() ); } + + function test_transferRemote_reverts_whenAmountExceedsValue( + uint256 nativeValue + ) public { + vm.assume(nativeValue < address(this).balance); + + address recipient = address(0xdeadbeef); + bytes32 bRecipient = TypeCasts.addressToBytes32(recipient); + vm.expectRevert("Native: amount exceeds msg.value"); + nativeToken.transferRemote{value: nativeValue}( + DESTINATION, + bRecipient, + nativeValue + 1 + ); + + vm.expectRevert("Native: amount exceeds msg.value"); + nativeToken.transferRemote{value: nativeValue}( + DESTINATION, + bRecipient, + nativeValue + 1, + bytes(""), + address(0) + ); + } } diff --git a/solidity/test/token/HypNativeScaled.t.sol b/solidity/test/token/HypNativeScaled.t.sol index a9af062ae..ffded6565 100644 --- a/solidity/test/token/HypNativeScaled.t.sol +++ b/solidity/test/token/HypNativeScaled.t.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0; import "forge-std/Test.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {TestPostDispatchHook} from "../../contracts/test/TestPostDispatchHook.sol"; import {HypNativeScaled} from "../../contracts/token/extensions/HypNativeScaled.sol"; import {HypERC20} from "../../contracts/token/HypERC20.sol"; import {HypNative} from "../../contracts/token/HypNative.sol"; @@ -14,6 +15,8 @@ contract HypNativeScaledTest is Test { uint32 nativeDomain = 1; uint32 synthDomain = 2; + address internal constant ALICE = address(0x1); + uint8 decimals = 9; uint256 mintAmount = 123456789; uint256 nativeDecimals = 18; @@ -149,7 +152,7 @@ contract HypNativeScaledTest is Test { address recipient = address(0xdeadbeef); bytes32 bRecipient = TypeCasts.addressToBytes32(recipient); - vm.assume(nativeValue < address(this).balance); + vm.deal(address(this), nativeValue); vm.expectEmit(true, true, true, true); emit SentTransferRemote(synthDomain, bRecipient, synthAmount); native.transferRemote{value: nativeValue}( @@ -161,6 +164,33 @@ contract HypNativeScaledTest is Test { assertEq(synth.balanceOf(recipient), synthAmount); } + function testTransfer_withHookSpecified( + uint256 amount, + bytes calldata metadata + ) public { + vm.assume(amount <= mintAmount); + + uint256 nativeValue = amount * (10 ** nativeDecimals); + uint256 synthAmount = amount * (10 ** decimals); + address recipient = address(0xdeadbeef); + bytes32 bRecipient = TypeCasts.addressToBytes32(recipient); + + TestPostDispatchHook hook = new TestPostDispatchHook(); + + vm.deal(address(this), nativeValue); + vm.expectEmit(true, true, true, true); + emit SentTransferRemote(synthDomain, bRecipient, synthAmount); + native.transferRemote{value: nativeValue}( + synthDomain, + bRecipient, + nativeValue, + metadata, + address(hook) + ); + environment.processNextPendingMessageFromDestination(); + assertEq(synth.balanceOf(recipient), synthAmount); + } + function test_transferRemote_reverts_whenAmountExceedsValue( uint256 nativeValue ) public { @@ -174,5 +204,14 @@ contract HypNativeScaledTest is Test { bRecipient, nativeValue + 1 ); + + vm.expectRevert("Native: amount exceeds msg.value"); + native.transferRemote{value: nativeValue}( + synthDomain, + bRecipient, + nativeValue + 1, + bytes(""), + address(0) + ); } } From 1e485bc801880910673c047b8d2c15a1131ffd9f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:14:59 -0400 Subject: [PATCH 052/224] Version Packages (#4530) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/core@5.2.1 ### Patch Changes - eb5afcf3e: Patch `HypNative` with hook overrides `transferRemote` behavior - @hyperlane-xyz/utils@5.2.1 ## @hyperlane-xyz/cli@5.2.1 ### Patch Changes - @hyperlane-xyz/sdk@5.2.1 - @hyperlane-xyz/utils@5.2.1 ## @hyperlane-xyz/helloworld@5.2.1 ### Patch Changes - Updated dependencies [eb5afcf3e] - @hyperlane-xyz/core@5.2.1 - @hyperlane-xyz/sdk@5.2.1 ## @hyperlane-xyz/sdk@5.2.1 ### Patch Changes - Updated dependencies [eb5afcf3e] - @hyperlane-xyz/core@5.2.1 - @hyperlane-xyz/utils@5.2.1 ## @hyperlane-xyz/widgets@5.2.1 ### Patch Changes - @hyperlane-xyz/sdk@5.2.1 ## @hyperlane-xyz/utils@5.2.1 ## @hyperlane-xyz/infra@5.2.1 ### Patch Changes - @hyperlane-xyz/helloworld@5.2.1 - @hyperlane-xyz/sdk@5.2.1 - @hyperlane-xyz/utils@5.2.1 ## @hyperlane-xyz/ccip-server@5.2.1 ## @hyperlane-xyz/github-proxy@5.2.1 Co-authored-by: github-actions[bot] --- .changeset/curvy-elephants-breathe.md | 5 ----- solidity/CHANGELOG.md | 7 +++++++ solidity/package.json | 4 ++-- typescript/ccip-server/CHANGELOG.md | 2 ++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 7 +++++++ typescript/cli/package.json | 6 +++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 2 ++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 8 +++++++ typescript/helloworld/package.json | 6 +++--- typescript/infra/CHANGELOG.md | 8 +++++++ typescript/infra/package.json | 8 +++---- typescript/sdk/CHANGELOG.md | 8 +++++++ typescript/sdk/package.json | 6 +++--- typescript/utils/CHANGELOG.md | 2 ++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 6 ++++++ typescript/widgets/package.json | 4 ++-- yarn.lock | 30 +++++++++++++-------------- 21 files changed, 86 insertions(+), 41 deletions(-) delete mode 100644 .changeset/curvy-elephants-breathe.md diff --git a/.changeset/curvy-elephants-breathe.md b/.changeset/curvy-elephants-breathe.md deleted file mode 100644 index c56062714..000000000 --- a/.changeset/curvy-elephants-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': patch ---- - -Patch `HypNative` with hook overrides `transferRemote` behavior diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index 72b14534c..0e695b0b7 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,12 @@ # @hyperlane-xyz/core +## 5.2.1 + +### Patch Changes + +- eb5afcf3e: Patch `HypNative` with hook overrides `transferRemote` behavior + - @hyperlane-xyz/utils@5.2.1 + ## 5.2.0 ### Minor Changes diff --git a/solidity/package.json b/solidity/package.json index e5a765129..843a4c856 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.2.0", + "version": "5.2.1", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.2.0", + "@hyperlane-xyz/utils": "5.2.1", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index 4d088d0f4..36e16dd74 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/ccip-server +## 5.2.1 + ## 5.2.0 ### Patch Changes diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index ff457a5d7..0714e7c2a 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.2.0", + "version": "5.2.1", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index eaa4970b2..5edb0c00d 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,12 @@ # @hyperlane-xyz/cli +## 5.2.1 + +### Patch Changes + +- @hyperlane-xyz/sdk@5.2.1 +- @hyperlane-xyz/utils@5.2.1 + ## 5.2.0 ### Minor Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index eca751c13..85b1de5df 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.2.0", + "version": "5.2.1", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.3.2", - "@hyperlane-xyz/sdk": "5.2.0", - "@hyperlane-xyz/utils": "5.2.0", + "@hyperlane-xyz/sdk": "5.2.1", + "@hyperlane-xyz/utils": "5.2.1", "@inquirer/prompts": "^3.0.0", "asn1.js": "^5.4.1", "bignumber.js": "^9.1.1", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index 52ba2c39c..e1aa0bd55 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.2.0'; +export const VERSION = '5.2.1'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md index ceff61e23..70e5c73ec 100644 --- a/typescript/github-proxy/CHANGELOG.md +++ b/typescript/github-proxy/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/github-proxy +## 5.2.1 + ## 5.2.0 ### Minor Changes diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index 55c61baea..9a203f2bb 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.2.0", + "version": "5.2.1", "private": true, "scripts": { "deploy": "wrangler deploy", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index 15f464849..ad5881287 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/helloworld +## 5.2.1 + +### Patch Changes + +- Updated dependencies [eb5afcf3e] + - @hyperlane-xyz/core@5.2.1 + - @hyperlane-xyz/sdk@5.2.1 + ## 5.2.0 ### Minor Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index b7de18159..941c8dcee 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.2.0", + "version": "5.2.1", "dependencies": { - "@hyperlane-xyz/core": "5.2.0", + "@hyperlane-xyz/core": "5.2.1", "@hyperlane-xyz/registry": "4.1.0", - "@hyperlane-xyz/sdk": "5.2.0", + "@hyperlane-xyz/sdk": "5.2.1", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index 21886a78f..6bd879f45 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/infra +## 5.2.1 + +### Patch Changes + +- @hyperlane-xyz/helloworld@5.2.1 +- @hyperlane-xyz/sdk@5.2.1 +- @hyperlane-xyz/utils@5.2.1 + ## 5.2.0 ### Minor Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 3ac5dfb8b..c0c235c37 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.2.0", + "version": "5.2.1", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.2.0", + "@hyperlane-xyz/helloworld": "5.2.1", "@hyperlane-xyz/registry": "4.3.2", - "@hyperlane-xyz/sdk": "5.2.0", - "@hyperlane-xyz/utils": "5.2.0", + "@hyperlane-xyz/sdk": "5.2.1", + "@hyperlane-xyz/utils": "5.2.1", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index 1bcdb4c7f..da934b9e9 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/sdk +## 5.2.1 + +### Patch Changes + +- Updated dependencies [eb5afcf3e] + - @hyperlane-xyz/core@5.2.1 + - @hyperlane-xyz/utils@5.2.1 + ## 5.2.0 ### Minor Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 65f69ed3e..7c9d63e33 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.2.0", + "version": "5.2.1", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.2.0", - "@hyperlane-xyz/utils": "5.2.0", + "@hyperlane-xyz/core": "5.2.1", + "@hyperlane-xyz/utils": "5.2.1", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index 6a19cc8b5..61af4f186 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/utils +## 5.2.1 + ## 5.2.0 ### Minor Changes diff --git a/typescript/utils/package.json b/typescript/utils/package.json index e87aef47d..70a61f73b 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.2.0", + "version": "5.2.1", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index a085fab2b..0d39df731 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,11 @@ # @hyperlane-xyz/widgets +## 5.2.1 + +### Patch Changes + +- @hyperlane-xyz/sdk@5.2.1 + ## 5.2.0 ### Patch Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 01e187ff9..95e5247c6 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.2.0", + "version": "5.2.1", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@hyperlane-xyz/registry": "4.3.2", - "@hyperlane-xyz/sdk": "5.2.0" + "@hyperlane-xyz/sdk": "5.2.1" }, "devDependencies": { "@storybook/addon-essentials": "^7.6.14", diff --git a/yarn.lock b/yarn.lock index b05360c35..33d36fafe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7591,8 +7591,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.3.2" - "@hyperlane-xyz/sdk": "npm:5.2.0" - "@hyperlane-xyz/utils": "npm:5.2.0" + "@hyperlane-xyz/sdk": "npm:5.2.1" + "@hyperlane-xyz/utils": "npm:5.2.1" "@inquirer/prompts": "npm:^3.0.0" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:^18.14.5" @@ -7622,13 +7622,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.2.0, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.2.1, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.2.0" + "@hyperlane-xyz/utils": "npm:5.2.1" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7678,13 +7678,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.2.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.2.1, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.2.0" + "@hyperlane-xyz/core": "npm:5.2.1" "@hyperlane-xyz/registry": "npm:4.1.0" - "@hyperlane-xyz/sdk": "npm:5.2.0" + "@hyperlane-xyz/sdk": "npm:5.2.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7731,10 +7731,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.2.0" + "@hyperlane-xyz/helloworld": "npm:5.2.1" "@hyperlane-xyz/registry": "npm:4.3.2" - "@hyperlane-xyz/sdk": "npm:5.2.0" - "@hyperlane-xyz/utils": "npm:5.2.0" + "@hyperlane-xyz/sdk": "npm:5.2.1" + "@hyperlane-xyz/utils": "npm:5.2.1" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -7810,7 +7810,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.2.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.2.1, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -7818,8 +7818,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.2.0" - "@hyperlane-xyz/utils": "npm:5.2.0" + "@hyperlane-xyz/core": "npm:5.2.1" + "@hyperlane-xyz/utils": "npm:5.2.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -7860,7 +7860,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.2.0, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.2.1, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -7885,7 +7885,7 @@ __metadata: resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: "@hyperlane-xyz/registry": "npm:4.3.2" - "@hyperlane-xyz/sdk": "npm:5.2.0" + "@hyperlane-xyz/sdk": "npm:5.2.1" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From 5ecc529e14fcd4d3b41f98a5ea491c639cb5a6f2 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 19 Sep 2024 18:31:10 +0100 Subject: [PATCH 053/224] chore: tidy up worfklow triggers (#4479) chore: tidy up worfklow triggers This will hopefully stop the double triggering we're seeing currently for the X/X-skipped workflows rust.yml: - run if there are changes to rust dir or to the workflow file - always run in merge queue rust-skipped.yml: - only run if there are no changes to rust dir or to workflow file test.yml: - don't run if the only changes are MD files - always run in merge queue test.yml: - run if the only changes are MD files We always run the full rust.yml/test.yml workflows in the merge queue, because the path matching/filtering for push/pull_request isn't supported by the `merge_queue` argument. There's options to add a step to manually do it but considering our CI is a bit faster now it should be fine in the general case --- .github/workflows/rust-skipped.yml | 18 ++++++++++-------- .github/workflows/rust.yml | 4 ++++ .github/workflows/test-skipped.yml | 21 +++++---------------- .github/workflows/test.yml | 14 +++++++++----- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/.github/workflows/rust-skipped.yml b/.github/workflows/rust-skipped.yml index 4c58de50b..d6900af9a 100644 --- a/.github/workflows/rust-skipped.yml +++ b/.github/workflows/rust-skipped.yml @@ -4,16 +4,18 @@ name: rust on: push: branches: [main] - paths-ignore: - - 'rust/main/**' - - 'rust/sealevel/**' - - .github/workflows/rust.yml + paths: + - '**/*' + - '!rust/main/**' + - '!rust/sealevel/**' + - '!.github/workflows/rust.yml' pull_request: branches: [main] - paths-ignore: - - 'rust/main/**' - - 'rust/sealevel/**' - - .github/workflows/rust.yml + paths: + - '**/*' + - '!rust/main/**' + - '!rust/sealevel/**' + - '!.github/workflows/rust.yml' env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b33ecbc92..18b856bc4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,12 +1,16 @@ name: rust on: + # Triggers the workflow on pushes to main branch + # only if rust/** or .github/workflows/rust.yml is changed push: branches: [main] paths: - 'rust/main/**' - 'rust/sealevel/**' - .github/workflows/rust.yml + # Triggers the workflow on pull requests + # only if rust/** or .github/workflows/rust.yml is changed pull_request: branches: [main] paths: diff --git a/.github/workflows/test-skipped.yml b/.github/workflows/test-skipped.yml index 6b3f3b081..c8dc05e69 100644 --- a/.github/workflows/test-skipped.yml +++ b/.github/workflows/test-skipped.yml @@ -1,18 +1,20 @@ +# This is here to satisfy the PR requirements when only markdown changes occur. name: test on: + # Auto-pass tests if only md files are changed push: branches: [main] paths: - - '*.md' - '!**/*' + - '**/*.md' + # Auto-pass tests if only md files are changed pull_request: branches: - '*' paths: - - '*.md' - '!**/*' - merge_group: + - '**/*.md' concurrency: group: e2e-${{ github.ref }} @@ -25,12 +27,6 @@ jobs: - name: Instant pass run: echo "yarn-install job passed" - yarn-build: - runs-on: ubuntu-latest - steps: - - name: Instant pass - run: echo "yarn-build job passed" - lint-prettier: runs-on: ubuntu-latest steps: @@ -63,13 +59,6 @@ jobs: - name: Instant pass run: echo "e2e-matrix job passed" - e2e: - runs-on: ubuntu-latest - if: always() - steps: - - name: Instant pass - run: echo "e2e job passed" - cli-advanced-e2e: runs-on: ubuntu-latest if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main') || github.event_name == 'merge_group' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ff0a6ddcc..2e3516326 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,16 +1,20 @@ name: test on: - # Triggers the workflow on pushes to main branch + # Triggers the workflow on pushes to main branch, ignoring md files push: branches: [main] - # Triggers on pull requests ignoring md files + paths: + - '**/*' + - '!**/*.md' + # Triggers on pull requests, ignoring md files pull_request: branches: - - '*' # run against all branches - # Support for merge queues + - '*' + paths: + - '**/*' + - '!**/*.md' merge_group: - # Allows you to run this workflow manually from the Actions tab workflow_dispatch: concurrency: From 4151317b000ae5934dad0b841b0182af4f924047 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Fri, 20 Sep 2024 10:26:23 +0100 Subject: [PATCH 054/224] feat: Fetch logs by transaction hash (#4510) ### Description Cosmos indexers now can fetch logs by transaction hash. It allows to reprocess transaction which may be missed by range based indexers. ### Drive-by changes Quite a bit of refactoring ### Related issues Contributes into issue #4300 ### Backward compatibility Yes ### Testing E2E Tests --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- rust/README.md | 2 +- .../hyperlane-cosmos/src/aggregation_ism.rs | 2 +- .../hyperlane-cosmos/src/interchain_gas.rs | 59 ++-- .../src/interchain_security_module.rs | 2 +- .../hyperlane-cosmos/src/mailbox/contract.rs | 2 +- .../src/mailbox/delivery_indexer.rs | 34 ++- .../src/mailbox/dispatch_indexer.rs | 35 ++- .../hyperlane-cosmos/src/merkle_tree_hook.rs | 63 ++-- .../hyperlane-cosmos/src/multisig_ism.rs | 2 +- .../chains/hyperlane-cosmos/src/providers.rs | 8 + .../hyperlane-cosmos/src/providers/cosmos.rs | 3 + .../providers/{mod.rs => cosmos/provider.rs} | 53 +--- .../hyperlane-cosmos/src/providers/grpc.rs | 33 +-- .../src/providers/grpc/tests.rs | 2 +- .../hyperlane-cosmos/src/providers/rpc.rs | 254 +--------------- .../src/providers/rpc/client.rs | 77 +++++ .../src/providers/rpc/provider.rs | 277 ++++++++++++++++++ .../hyperlane-cosmos/src/routing_ism.rs | 2 +- .../main/chains/hyperlane-cosmos/src/utils.rs | 28 +- .../src/validator_announce.rs | 2 +- .../hyperlane-base/src/settings/chains.rs | 2 +- 21 files changed, 552 insertions(+), 390 deletions(-) create mode 100644 rust/main/chains/hyperlane-cosmos/src/providers.rs create mode 100644 rust/main/chains/hyperlane-cosmos/src/providers/cosmos.rs rename rust/main/chains/hyperlane-cosmos/src/providers/{mod.rs => cosmos/provider.rs} (87%) create mode 100644 rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs create mode 100644 rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs diff --git a/rust/README.md b/rust/README.md index 22bf8b54e..289d1dc1d 100644 --- a/rust/README.md +++ b/rust/README.md @@ -90,7 +90,7 @@ env $(cat ./config/validator.fuji.env | grep -v "#" | xargs) ./target/debug/vali Clone `hyperlane-registry` repo next to `hyperlane-monorepo` repo. -To perform an automated e2e test of the agents locally, from within the `hyperlane-monorepo/rust` directory, run: +To perform an automated e2e test of the agents locally, from within the `hyperlane-monorepo/rust/main` directory, run: ```bash cargo run --release --bin run-locally diff --git a/rust/main/chains/hyperlane-cosmos/src/aggregation_ism.rs b/rust/main/chains/hyperlane-cosmos/src/aggregation_ism.rs index 835b2cf04..d9a1f5391 100644 --- a/rust/main/chains/hyperlane-cosmos/src/aggregation_ism.rs +++ b/rust/main/chains/hyperlane-cosmos/src/aggregation_ism.rs @@ -33,7 +33,7 @@ impl CosmosAggregationIsm { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; diff --git a/rust/main/chains/hyperlane-cosmos/src/interchain_gas.rs b/rust/main/chains/hyperlane-cosmos/src/interchain_gas.rs index 0ab0a707e..1e1cb2b32 100644 --- a/rust/main/chains/hyperlane-cosmos/src/interchain_gas.rs +++ b/rust/main/chains/hyperlane-cosmos/src/interchain_gas.rs @@ -1,25 +1,24 @@ +use std::ops::RangeInclusive; + use async_trait::async_trait; use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; +use once_cell::sync::Lazy; +use tendermint::abci::EventAttribute; +use tracing::instrument; + use hyperlane_core::{ ChainCommunicationError, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, InterchainGasPaymaster, - InterchainGasPayment, LogMeta, SequenceAwareIndexer, H256, U256, + InterchainGasPayment, LogMeta, SequenceAwareIndexer, H256, H512, U256, }; -use once_cell::sync::Lazy; -use std::ops::RangeInclusive; -use tendermint::abci::EventAttribute; -use tracing::instrument; -use crate::utils::parse_logs_in_range; -use crate::{ - rpc::{CosmosWasmIndexer, ParsedEvent, WasmIndexer}, - signers::Signer, - utils::{ - execute_and_parse_log_futures, CONTRACT_ADDRESS_ATTRIBUTE_KEY, - CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, - }, - ConnectionConf, CosmosProvider, HyperlaneCosmosError, +use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; +use crate::signers::Signer; +use crate::utils::{ + execute_and_parse_log_futures, parse_logs_in_range, parse_logs_in_tx, + CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, }; +use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError}; /// A reference to a InterchainGasPaymaster contract on some Cosmos chain #[derive(Debug)] @@ -57,7 +56,7 @@ impl CosmosInterchainGasPaymaster { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; @@ -90,7 +89,7 @@ static DESTINATION_ATTRIBUTE_KEY_BASE64: Lazy = /// A reference to a InterchainGasPaymasterIndexer contract on some Cosmos chain #[derive(Debug, Clone)] pub struct CosmosInterchainGasPaymasterIndexer { - indexer: Box, + provider: Box, } impl CosmosInterchainGasPaymasterIndexer { @@ -103,7 +102,7 @@ impl CosmosInterchainGasPaymasterIndexer { locator: ContractLocator, reorg_period: u32, ) -> ChainResult { - let indexer = CosmosWasmIndexer::new( + let provider = CosmosWasmRpcProvider::new( conf, locator, Self::INTERCHAIN_GAS_PAYMENT_EVENT_TYPE.into(), @@ -111,7 +110,7 @@ impl CosmosInterchainGasPaymasterIndexer { )?; Ok(Self { - indexer: Box::new(indexer), + provider: Box::new(provider), }) } @@ -211,7 +210,7 @@ impl Indexer for CosmosInterchainGasPaymasterIndexer { ) -> ChainResult, LogMeta)>> { let logs_futures = parse_logs_in_range( range, - self.indexer.clone(), + self.provider.clone(), Self::interchain_gas_payment_parser, "InterchainGasPaymentCursor", ); @@ -220,7 +219,21 @@ impl Indexer for CosmosInterchainGasPaymasterIndexer { } async fn get_finalized_block_number(&self) -> ChainResult { - self.indexer.get_finalized_block_number().await + self.provider.get_finalized_block_number().await + } + + async fn fetch_logs_by_tx_hash( + &self, + tx_hash: H512, + ) -> ChainResult, LogMeta)>> { + parse_logs_in_tx( + &tx_hash.into(), + self.provider.clone(), + Self::interchain_gas_payment_parser, + "InterchainGasPaymentReceiver", + ) + .await + .map(|v| v.into_iter().map(|(m, l)| (m.into(), l)).collect()) } } @@ -269,10 +282,12 @@ impl TryInto for IncompleteInterchainGasPayment { #[cfg(test)] mod tests { - use hyperlane_core::{InterchainGasPayment, H256, U256}; use std::str::FromStr; - use crate::{rpc::ParsedEvent, utils::event_attributes_from_str}; + use hyperlane_core::{InterchainGasPayment, H256, U256}; + + use crate::providers::rpc::ParsedEvent; + use crate::utils::event_attributes_from_str; use super::*; diff --git a/rust/main/chains/hyperlane-cosmos/src/interchain_security_module.rs b/rust/main/chains/hyperlane-cosmos/src/interchain_security_module.rs index dd495be89..e23807a58 100644 --- a/rust/main/chains/hyperlane-cosmos/src/interchain_security_module.rs +++ b/rust/main/chains/hyperlane-cosmos/src/interchain_security_module.rs @@ -38,7 +38,7 @@ impl CosmosInterchainSecurityModule { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; diff --git a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs index 754a84ce7..9d9f39c54 100644 --- a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs +++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs @@ -41,7 +41,7 @@ impl CosmosMailbox { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; diff --git a/rust/main/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs index 7279c67fe..ccc92df70 100644 --- a/rust/main/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs +++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/delivery_indexer.rs @@ -9,14 +9,14 @@ use tendermint::abci::EventAttribute; use tracing::instrument; use hyperlane_core::{ - ChainCommunicationError, ChainResult, ContractLocator, Delivery, Indexed, Indexer, LogMeta, - SequenceAwareIndexer, H256, + ChainCommunicationError, ChainResult, ContractLocator, Delivery, HyperlaneMessage, Indexed, + Indexer, LogMeta, SequenceAwareIndexer, H256, H512, }; -use crate::rpc::{CosmosWasmIndexer, ParsedEvent, WasmIndexer}; +use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; use crate::utils::{ - execute_and_parse_log_futures, parse_logs_in_range, CONTRACT_ADDRESS_ATTRIBUTE_KEY, - CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, + execute_and_parse_log_futures, parse_logs_in_range, parse_logs_in_tx, + CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, }; use crate::{ConnectionConf, HyperlaneCosmosError, Signer}; @@ -28,7 +28,7 @@ static MESSAGE_ID_ATTRIBUTE_KEY_BASE64: Lazy = /// Struct that retrieves delivery event data for a Cosmos Mailbox contract pub struct CosmosMailboxDeliveryIndexer { - indexer: Box, + provider: Box, } impl CosmosMailboxDeliveryIndexer { @@ -40,7 +40,7 @@ impl CosmosMailboxDeliveryIndexer { signer: Option, reorg_period: u32, ) -> ChainResult { - let indexer = CosmosWasmIndexer::new( + let provider = CosmosWasmRpcProvider::new( conf, locator, MESSAGE_DELIVERY_EVENT_TYPE.to_owned(), @@ -48,7 +48,7 @@ impl CosmosMailboxDeliveryIndexer { )?; Ok(Self { - indexer: Box::new(indexer), + provider: Box::new(provider), }) } @@ -114,7 +114,7 @@ impl Indexer for CosmosMailboxDeliveryIndexer { ) -> ChainResult, LogMeta)>> { let logs_futures = parse_logs_in_range( range, - self.indexer.clone(), + self.provider.clone(), Self::hyperlane_delivery_parser, "DeliveryCursor", ); @@ -123,7 +123,21 @@ impl Indexer for CosmosMailboxDeliveryIndexer { } async fn get_finalized_block_number(&self) -> ChainResult { - self.indexer.get_finalized_block_number().await + self.provider.get_finalized_block_number().await + } + + async fn fetch_logs_by_tx_hash( + &self, + tx_hash: H512, + ) -> ChainResult, LogMeta)>> { + parse_logs_in_tx( + &tx_hash.into(), + self.provider.clone(), + Self::hyperlane_delivery_parser, + "DeliveryReceiver", + ) + .await + .map(|v| v.into_iter().map(|(m, l)| (m.into(), l)).collect()) } } diff --git a/rust/main/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs index 77fc6579c..433ea661e 100644 --- a/rust/main/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs +++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/dispatch_indexer.rs @@ -9,13 +9,13 @@ use tracing::instrument; use hyperlane_core::{ ChainCommunicationError, ChainResult, ContractLocator, Decode, HyperlaneMessage, Indexed, - Indexer, LogMeta, SequenceAwareIndexer, + Indexer, LogMeta, SequenceAwareIndexer, H512, }; -use crate::rpc::{CosmosWasmIndexer, ParsedEvent, WasmIndexer}; +use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; use crate::utils::{ - execute_and_parse_log_futures, parse_logs_in_range, CONTRACT_ADDRESS_ATTRIBUTE_KEY, - CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, + execute_and_parse_log_futures, parse_logs_in_range, parse_logs_in_tx, + CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, }; use crate::{ConnectionConf, CosmosMailbox, HyperlaneCosmosError, Signer}; @@ -29,7 +29,7 @@ static MESSAGE_ATTRIBUTE_KEY_BASE64: Lazy = #[derive(Debug, Clone)] pub struct CosmosMailboxDispatchIndexer { mailbox: CosmosMailbox, - indexer: Box, + provider: Box, } impl CosmosMailboxDispatchIndexer { @@ -42,7 +42,7 @@ impl CosmosMailboxDispatchIndexer { reorg_period: u32, ) -> ChainResult { let mailbox = CosmosMailbox::new(conf.clone(), locator.clone(), signer.clone())?; - let indexer = CosmosWasmIndexer::new( + let provider = CosmosWasmRpcProvider::new( conf, locator, MESSAGE_DISPATCH_EVENT_TYPE.into(), @@ -51,7 +51,7 @@ impl CosmosMailboxDispatchIndexer { Ok(Self { mailbox, - indexer: Box::new(indexer), + provider: Box::new(provider), }) } @@ -116,7 +116,7 @@ impl Indexer for CosmosMailboxDispatchIndexer { ) -> ChainResult, LogMeta)>> { let logs_futures = parse_logs_in_range( range, - self.indexer.clone(), + self.provider.clone(), Self::hyperlane_message_parser, "HyperlaneMessageCursor", ); @@ -125,7 +125,21 @@ impl Indexer for CosmosMailboxDispatchIndexer { } async fn get_finalized_block_number(&self) -> ChainResult { - self.indexer.get_finalized_block_number().await + self.provider.get_finalized_block_number().await + } + + async fn fetch_logs_by_tx_hash( + &self, + tx_hash: H512, + ) -> ChainResult, LogMeta)>> { + parse_logs_in_tx( + &tx_hash.into(), + self.provider.clone(), + Self::hyperlane_message_parser, + "HyperlaneMessageReceiver", + ) + .await + .map(|v| v.into_iter().map(|(m, l)| (m.into(), l)).collect()) } } @@ -144,7 +158,8 @@ impl SequenceAwareIndexer for CosmosMailboxDispatchIndexer { mod tests { use hyperlane_core::HyperlaneMessage; - use crate::{rpc::ParsedEvent, utils::event_attributes_from_str}; + use crate::providers::rpc::ParsedEvent; + use crate::utils::event_attributes_from_str; use super::*; diff --git a/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs index ce9283fe2..c9e48c59f 100644 --- a/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs @@ -2,27 +2,26 @@ use std::{fmt::Debug, num::NonZeroU64, ops::RangeInclusive, str::FromStr}; use async_trait::async_trait; use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; -use hyperlane_core::{ - accumulator::incremental::IncrementalMerkle, ChainCommunicationError, ChainResult, Checkpoint, - ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneProvider, - Indexed, Indexer, LogMeta, MerkleTreeHook, MerkleTreeInsertion, SequenceAwareIndexer, H256, -}; use once_cell::sync::Lazy; use tendermint::abci::EventAttribute; use tracing::instrument; -use crate::utils::parse_logs_in_range; -use crate::{ - grpc::WasmProvider, - payloads::{general, merkle_tree_hook}, - rpc::{CosmosWasmIndexer, ParsedEvent, WasmIndexer}, - utils::{ - execute_and_parse_log_futures, get_block_height_for_lag, CONTRACT_ADDRESS_ATTRIBUTE_KEY, - CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, - }, - ConnectionConf, CosmosProvider, HyperlaneCosmosError, Signer, +use hyperlane_core::accumulator::incremental::IncrementalMerkle; +use hyperlane_core::{ + ChainCommunicationError, ChainResult, Checkpoint, ContractLocator, HyperlaneChain, + HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, LogMeta, + MerkleTreeHook, MerkleTreeInsertion, SequenceAwareIndexer, H256, H512, }; +use crate::grpc::WasmProvider; +use crate::payloads::{general, merkle_tree_hook}; +use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; +use crate::utils::{ + execute_and_parse_log_futures, get_block_height_for_lag, parse_logs_in_range, parse_logs_in_tx, + CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, +}; +use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError, Signer}; + #[derive(Debug, Clone)] /// A reference to a MerkleTreeHook contract on some Cosmos chain pub struct CosmosMerkleTreeHook { @@ -44,7 +43,7 @@ impl CosmosMerkleTreeHook { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; @@ -188,8 +187,8 @@ pub(crate) static MESSAGE_ID_ATTRIBUTE_KEY_BASE64: Lazy = pub struct CosmosMerkleTreeHookIndexer { /// The CosmosMerkleTreeHook merkle_tree_hook: CosmosMerkleTreeHook, - /// Cosmwasm indexer instance - indexer: Box, + /// Cosmwasm RPC provider instance + provider: Box, } impl CosmosMerkleTreeHookIndexer { @@ -203,7 +202,7 @@ impl CosmosMerkleTreeHookIndexer { signer: Option, reorg_period: u32, ) -> ChainResult { - let indexer = CosmosWasmIndexer::new( + let provider = CosmosWasmRpcProvider::new( conf.clone(), locator.clone(), Self::MERKLE_TREE_INSERTION_EVENT_TYPE.into(), @@ -212,7 +211,7 @@ impl CosmosMerkleTreeHookIndexer { Ok(Self { merkle_tree_hook: CosmosMerkleTreeHook::new(conf, locator, signer)?, - indexer: Box::new(indexer), + provider: Box::new(provider), }) } @@ -287,7 +286,7 @@ impl Indexer for CosmosMerkleTreeHookIndexer { ) -> ChainResult, LogMeta)>> { let logs_futures = parse_logs_in_range( range, - self.indexer.clone(), + self.provider.clone(), Self::merkle_tree_insertion_parser, "MerkleTreeInsertionCursor", ); @@ -297,7 +296,21 @@ impl Indexer for CosmosMerkleTreeHookIndexer { /// Get the chain's latest block number that has reached finality async fn get_finalized_block_number(&self) -> ChainResult { - self.indexer.get_finalized_block_number().await + self.provider.get_finalized_block_number().await + } + + async fn fetch_logs_by_tx_hash( + &self, + tx_hash: H512, + ) -> ChainResult, LogMeta)>> { + parse_logs_in_tx( + &tx_hash.into(), + self.provider.clone(), + Self::merkle_tree_insertion_parser, + "MerkleTreeInsertionReceiver", + ) + .await + .map(|v| v.into_iter().map(|(m, l)| (m.into(), l)).collect()) } } @@ -337,10 +350,12 @@ impl TryInto for IncompleteMerkleTreeInsertion { #[cfg(test)] mod tests { - use hyperlane_core::H256; use std::str::FromStr; - use crate::{rpc::ParsedEvent, utils::event_attributes_from_str}; + use hyperlane_core::H256; + + use crate::providers::rpc::ParsedEvent; + use crate::utils::event_attributes_from_str; use super::*; diff --git a/rust/main/chains/hyperlane-cosmos/src/multisig_ism.rs b/rust/main/chains/hyperlane-cosmos/src/multisig_ism.rs index d558acfa3..0b7f49234 100644 --- a/rust/main/chains/hyperlane-cosmos/src/multisig_ism.rs +++ b/rust/main/chains/hyperlane-cosmos/src/multisig_ism.rs @@ -30,7 +30,7 @@ impl CosmosMultisigIsm { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; diff --git a/rust/main/chains/hyperlane-cosmos/src/providers.rs b/rust/main/chains/hyperlane-cosmos/src/providers.rs new file mode 100644 index 000000000..3c3a79fd8 --- /dev/null +++ b/rust/main/chains/hyperlane-cosmos/src/providers.rs @@ -0,0 +1,8 @@ +pub use cosmos::CosmosProvider; + +/// cosmos provider +mod cosmos; +/// cosmos grpc provider +pub mod grpc; +/// cosmos rpc provider +pub mod rpc; diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos.rs new file mode 100644 index 000000000..9fea74725 --- /dev/null +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos.rs @@ -0,0 +1,3 @@ +pub use provider::CosmosProvider; + +mod provider; diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/mod.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs similarity index 87% rename from rust/main/chains/hyperlane-cosmos/src/providers/mod.rs rename to rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index 0d3d2a854..5f207cc8a 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/mod.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -15,24 +15,18 @@ use hyperlane_core::{ }; use crate::address::CosmosAddress; -use crate::grpc::WasmProvider; +use crate::grpc::{WasmGrpcProvider, WasmProvider}; use crate::libs::account::CosmosAccountId; +use crate::providers::rpc::CosmosRpcClient; use crate::{ConnectionConf, CosmosAmount, HyperlaneCosmosError, Signer}; -use self::grpc::WasmGrpcProvider; - -/// cosmos grpc provider -pub mod grpc; -/// cosmos rpc provider -pub mod rpc; - /// Abstraction over a connection to a Cosmos chain #[derive(Debug, Clone)] pub struct CosmosProvider { domain: HyperlaneDomain, connection_conf: ConnectionConf, - grpc_client: WasmGrpcProvider, - rpc_client: HttpClient, + grpc_provider: WasmGrpcProvider, + rpc_client: CosmosRpcClient, } impl CosmosProvider { @@ -40,43 +34,30 @@ impl CosmosProvider { pub fn new( domain: HyperlaneDomain, conf: ConnectionConf, - locator: Option, + locator: ContractLocator, signer: Option, ) -> ChainResult { let gas_price = CosmosAmount::try_from(conf.get_minimum_gas_price().clone())?; - let grpc_client = WasmGrpcProvider::new( + let grpc_provider = WasmGrpcProvider::new( domain.clone(), conf.clone(), gas_price.clone(), locator, signer, )?; - let rpc_client = HttpClient::builder( - conf.get_rpc_url() - .parse() - .map_err(Into::::into)?, - ) - // Consider supporting different compatibility modes. - .compat_mode(CompatMode::latest()) - .build() - .map_err(Into::::into)?; + let rpc_client = CosmosRpcClient::new(&conf)?; Ok(Self { domain, connection_conf: conf, + grpc_provider, rpc_client, - grpc_client, }) } /// Get a grpc client pub fn grpc(&self) -> &WasmGrpcProvider { - &self.grpc_client - } - - /// Get an rpc client - pub fn rpc(&self) -> &HttpClient { - &self.rpc_client + &self.grpc_provider } fn search_payer_in_signer_infos( @@ -182,11 +163,7 @@ impl HyperlaneProvider for CosmosProvider { let tendermint_hash = Hash::from_bytes(Algorithm::Sha256, hash.as_bytes()) .expect("block hash should be of correct size"); - let response = self - .rpc_client - .block_by_hash(tendermint_hash) - .await - .map_err(ChainCommunicationError::from_other)?; + let response = self.rpc_client.get_block_by_hash(tendermint_hash).await?; let received_hash = H256::from_slice(response.block_id.hash.as_bytes()); @@ -218,11 +195,7 @@ impl HyperlaneProvider for CosmosProvider { let tendermint_hash = Hash::from_bytes(Algorithm::Sha256, hash.as_bytes()) .expect("transaction hash should be of correct size"); - let response = self - .rpc_client - .tx(tendermint_hash, false) - .await - .map_err(Into::::into)?; + let response = self.rpc_client.get_tx_by_hash(tendermint_hash).await?; let received_hash = H256::from_slice(response.hash.as_bytes()); @@ -269,7 +242,7 @@ impl HyperlaneProvider for CosmosProvider { } async fn is_contract(&self, address: &H256) -> ChainResult { - match self.grpc_client.wasm_contract_info().await { + match self.grpc_provider.wasm_contract_info().await { Ok(c) => Ok(true), Err(e) => Ok(false), } @@ -277,7 +250,7 @@ impl HyperlaneProvider for CosmosProvider { async fn get_balance(&self, address: String) -> ChainResult { Ok(self - .grpc_client + .grpc_provider .get_balance(address, self.connection_conf.get_canonical_asset()) .await?) } diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs index e0a6388a4..4b521658a 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs @@ -123,7 +123,7 @@ pub struct WasmGrpcProvider { conf: ConnectionConf, /// A contract address that can be used as the default /// for queries / sends / estimates. - contract_address: Option, + contract_address: CosmosAddress, /// Signer for transactions. signer: Option, /// GRPC Channel that can be cheaply cloned. @@ -138,7 +138,7 @@ impl WasmGrpcProvider { domain: HyperlaneDomain, conf: ConnectionConf, gas_price: CosmosAmount, - locator: Option, + locator: ContractLocator, signer: Option, ) -> ChainResult { // get all the configured grpc urls and convert them to a Vec @@ -156,15 +156,11 @@ impl WasmGrpcProvider { let fallback_provider = builder.build(); let provider = CosmosFallbackProvider::new(fallback_provider); - let contract_address = locator - .map(|l| { - CosmosAddress::from_h256( - l.address, - &conf.get_bech32_prefix(), - conf.get_contract_address_bytes(), - ) - }) - .transpose()?; + let contract_address = CosmosAddress::from_h256( + locator.address, + &conf.get_bech32_prefix(), + conf.get_contract_address_bytes(), + )?; Ok(Self { domain, @@ -446,11 +442,8 @@ impl WasmGrpcProvider { }) } - fn get_contract_address(&self) -> Result<&CosmosAddress, ChainCommunicationError> { - let contract_address = self.contract_address.as_ref().ok_or_else(|| { - ChainCommunicationError::from_other_str("No contract address available") - })?; - Ok(contract_address) + fn get_contract_address(&self) -> &CosmosAddress { + &self.contract_address } } @@ -488,7 +481,7 @@ impl WasmProvider for WasmGrpcProvider { where T: Serialize + Send + Sync + Clone + Debug, { - let contract_address = self.get_contract_address()?; + let contract_address = self.get_contract_address(); let query_data = serde_json::to_string(&payload)?.as_bytes().to_vec(); let response = self .provider @@ -522,7 +515,7 @@ impl WasmProvider for WasmGrpcProvider { } async fn wasm_contract_info(&self) -> ChainResult { - let contract_address = self.get_contract_address()?; + let contract_address = self.get_contract_address(); let response = self .provider .call(move |provider| { @@ -557,7 +550,7 @@ impl WasmProvider for WasmGrpcProvider { T: Serialize + Send + Sync + Clone + Debug, { let signer = self.get_signer()?; - let contract_address = self.get_contract_address()?; + let contract_address = self.get_contract_address(); let msgs = vec![MsgExecuteContract { sender: signer.address.clone(), contract: contract_address.address(), @@ -625,7 +618,7 @@ impl WasmProvider for WasmGrpcProvider { // Estimating gas requires a signer, which we can reasonably expect to have // since we need one to send a tx with the estimated gas anyways. let signer = self.get_signer()?; - let contract_address = self.get_contract_address()?; + let contract_address = self.get_contract_address(); let msg = MsgExecuteContract { sender: signer.address.clone(), contract: contract_address.address(), diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs index 9a59b6007..451c67b22 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs @@ -49,7 +49,7 @@ async fn test_wasm_contract_info_no_contract() { fn provider(address: &str) -> WasmGrpcProvider { let domain = HyperlaneDomain::Known(KnownHyperlaneDomain::Neutron); let address = CosmosAddress::from_str(address).unwrap(); - let locator = Some(ContractLocator::new(&domain, address.digest())); + let locator = ContractLocator::new(&domain, address.digest()); WasmGrpcProvider::new( domain.clone(), diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/rpc.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc.rs index fac93e008..08864b26c 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/rpc.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc.rs @@ -1,251 +1,5 @@ -use async_trait::async_trait; -use cosmrs::rpc::client::Client; -use hyperlane_core::{ChainCommunicationError, ChainResult, ContractLocator, LogMeta, H256, U256}; -use sha256::digest; -use std::fmt::Debug; -use tendermint::abci::{Event, EventAttribute}; -use tendermint::hash::Algorithm; -use tendermint::Hash; -use tendermint_rpc::endpoint::block::Response as BlockResponse; -use tendermint_rpc::endpoint::block_results::Response as BlockResultsResponse; -use tendermint_rpc::HttpClient; -use tracing::{debug, instrument, trace}; +pub use client::CosmosRpcClient; +pub use provider::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; -use crate::address::CosmosAddress; -use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError}; - -#[async_trait] -/// Trait for wasm indexer. Use rpc provider -pub trait WasmIndexer: Send + Sync { - /// Get the finalized block height. - async fn get_finalized_block_number(&self) -> ChainResult; - - /// Get logs for the given block using the given parser. - async fn get_logs_in_block( - &self, - block_number: u32, - parser: for<'a> fn(&'a Vec) -> ChainResult>, - cursor_label: &'static str, - ) -> ChainResult> - where - T: Send + Sync + PartialEq + Debug + 'static; -} - -#[derive(Debug, Eq, PartialEq)] -/// An event parsed from the RPC response. -pub struct ParsedEvent { - contract_address: String, - event: T, -} - -impl ParsedEvent { - /// Create a new ParsedEvent. - pub fn new(contract_address: String, event: T) -> Self { - Self { - contract_address, - event, - } - } - - /// Get the inner event - pub fn inner(self) -> T { - self.event - } -} - -#[derive(Debug, Clone)] -/// Cosmwasm RPC Provider -pub struct CosmosWasmIndexer { - provider: CosmosProvider, - contract_address: CosmosAddress, - target_event_kind: String, - reorg_period: u32, -} - -impl CosmosWasmIndexer { - const WASM_TYPE: &'static str = "wasm"; - - /// create new Cosmwasm RPC Provider - pub fn new( - conf: ConnectionConf, - locator: ContractLocator, - event_type: String, - reorg_period: u32, - ) -> ChainResult { - let provider = CosmosProvider::new( - locator.domain.clone(), - conf.clone(), - Some(locator.clone()), - None, - )?; - Ok(Self { - provider, - contract_address: CosmosAddress::from_h256( - locator.address, - conf.get_bech32_prefix().as_str(), - conf.get_contract_address_bytes(), - )?, - target_event_kind: format!("{}-{}", Self::WASM_TYPE, event_type), - reorg_period, - }) - } - - async fn get_block(client: HttpClient, block_number: u32) -> ChainResult { - Ok(client - .block(block_number) - .await - .map_err(Into::::into)?) - } - - async fn get_block_results( - client: HttpClient, - block_number: u32, - ) -> ChainResult { - Ok(client - .block_results(block_number) - .await - .map_err(Into::::into)?) - } - - async fn get_latest_block(client: HttpClient) -> ChainResult { - Ok(client - .latest_block() - .await - .map_err(Into::::into)?) - } -} - -impl CosmosWasmIndexer { - // Iterate through all txs, filter out failed txs, find target events - // in successful txs, and parse them. - fn handle_txs( - &self, - block: BlockResponse, - block_results: BlockResultsResponse, - parser: for<'a> fn(&'a Vec) -> ChainResult>, - cursor_label: &'static str, - ) -> Vec<(T, LogMeta)> - where - T: PartialEq + Debug + 'static, - { - let Some(tx_results) = block_results.txs_results else { - return vec![]; - }; - - let tx_hashes: Vec = block - .clone() - .block - .data - .into_iter() - .filter_map(|tx| hex::decode(digest(tx.as_slice())).ok()) - .filter_map(|hash| { - Hash::from_bytes(Algorithm::Sha256, hash.as_slice()) - .ok() - .map(|hash| H256::from_slice(hash.as_bytes())) - }) - .collect(); - - tx_results - .into_iter() - .enumerate() - .filter_map(move |(idx, tx)| { - let Some(tx_hash) = tx_hashes.get(idx) else { - debug!(?tx, "No tx hash found for tx"); - return None; - }; - if tx.code.is_err() { - debug!(?tx_hash, "Not indexing failed transaction"); - return None; - } - Some(self.handle_tx(block.clone(), tx.events, *tx_hash, idx, parser)) - }) - .flatten() - .collect() - } - - // Iter through all events in the tx, looking for any target events - // made by the contract we are indexing. - fn handle_tx( - &self, - block: BlockResponse, - tx_events: Vec, - tx_hash: H256, - transaction_index: usize, - parser: for<'a> fn(&'a Vec) -> ChainResult>, - ) -> impl Iterator + '_ - where - T: PartialEq + 'static, - { - tx_events.into_iter().enumerate().filter_map(move |(log_idx, event)| { - if event.kind.as_str() != self.target_event_kind { - return None; - } - - parser(&event.attributes) - .map_err(|err| { - // This can happen if we attempt to parse an event that just happens - // to have the same name but a different structure. - tracing::trace!(?err, tx_hash=?tx_hash, log_idx, ?event, "Failed to parse event attributes"); - }) - .ok() - .and_then(|parsed_event| { - // This is crucial! We need to make sure that the contract address - // in the event matches the contract address we are indexing. - // Otherwise, we might index events from other contracts that happen - // to have the same target event name. - if parsed_event.contract_address != self.contract_address.address() { - trace!(tx_hash=?tx_hash, log_idx, ?event, "Event contract address does not match indexer contract address"); - return None; - } - - Some((parsed_event.event, LogMeta { - address: self.contract_address.digest(), - block_number: block.block.header.height.into(), - block_hash: H256::from_slice(block.block_id.hash.as_bytes()), - transaction_id: H256::from_slice(tx_hash.as_bytes()).into(), - transaction_index: transaction_index as u64, - log_index: U256::from(log_idx), - })) - }) - }) - } -} - -#[async_trait] -impl WasmIndexer for CosmosWasmIndexer { - #[instrument(err, skip(self))] - #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn get_finalized_block_number(&self) -> ChainResult { - let latest_block = Self::get_latest_block(self.provider.rpc().clone()).await?; - let latest_height: u32 = latest_block - .block - .header - .height - .value() - .try_into() - .map_err(ChainCommunicationError::from_other)?; - Ok(latest_height.saturating_sub(self.reorg_period)) - } - - #[instrument(err, skip(self, parser))] - #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn get_logs_in_block( - &self, - block_number: u32, - parser: for<'a> fn(&'a Vec) -> ChainResult>, - cursor_label: &'static str, - ) -> ChainResult> - where - T: Send + Sync + PartialEq + Debug + 'static, - { - let client = self.provider.rpc().clone(); - debug!(?block_number, cursor_label, domain=?self.provider.domain, "Getting logs in block"); - - // The two calls below could be made in parallel, but on cosmos rate limiting is a bigger problem - // than indexing latency, so we do them sequentially. - let block = Self::get_block(client.clone(), block_number).await?; - let block_results = Self::get_block_results(client.clone(), block_number).await?; - - Ok(self.handle_txs(block, block_results, parser, cursor_label)) - } -} +mod client; +mod provider; diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs new file mode 100644 index 000000000..f3c3930b1 --- /dev/null +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs @@ -0,0 +1,77 @@ +use cosmrs::proto::tendermint::blocksync::BlockResponse; +use tendermint::Hash; +use tendermint_rpc::client::CompatMode; +use tendermint_rpc::endpoint::{block, block_by_hash, block_results, tx}; +use tendermint_rpc::{Client, HttpClient}; + +use hyperlane_core::ChainResult; + +use crate::{ConnectionConf, HyperlaneCosmosError}; + +/// Thin wrapper around Cosmos RPC client with error mapping +#[derive(Clone, Debug)] +pub struct CosmosRpcClient { + client: HttpClient, +} + +impl CosmosRpcClient { + /// Create new `CosmosRpcClient` + pub fn new(conf: &ConnectionConf) -> ChainResult { + let client = HttpClient::builder( + conf.get_rpc_url() + .parse() + .map_err(Into::::into)?, + ) + // Consider supporting different compatibility modes. + .compat_mode(CompatMode::latest()) + .build() + .map_err(Into::::into)?; + + Ok(Self { client }) + } + + /// Request block by block height + pub async fn get_block(&self, height: u32) -> ChainResult { + Ok(self + .client + .block(height) + .await + .map_err(Into::::into)?) + } + + /// Request block results by block height + pub async fn get_block_results(&self, height: u32) -> ChainResult { + Ok(self + .client + .block_results(height) + .await + .map_err(Into::::into)?) + } + + /// Request block by block hash + pub async fn get_block_by_hash(&self, hash: Hash) -> ChainResult { + Ok(self + .client + .block_by_hash(hash) + .await + .map_err(Into::::into)?) + } + + /// Request the latest block + pub async fn get_latest_block(&self) -> ChainResult { + Ok(self + .client + .latest_block() + .await + .map_err(Into::::into)?) + } + + /// Request transaction by transaction hash + pub async fn get_tx_by_hash(&self, hash: Hash) -> ChainResult { + Ok(self + .client + .tx(hash, false) + .await + .map_err(Into::::into)?) + } +} diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs new file mode 100644 index 000000000..0184aff96 --- /dev/null +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs @@ -0,0 +1,277 @@ +use std::fmt::Debug; + +use async_trait::async_trait; +use cosmrs::cosmwasm::MsgExecuteContract; +use cosmrs::rpc::client::Client; +use futures::StreamExt; +use sha256::digest; +use tendermint::abci::{Event, EventAttribute}; +use tendermint::hash::Algorithm; +use tendermint::Hash; +use tendermint_rpc::client::CompatMode; +use tendermint_rpc::endpoint::block::Response as BlockResponse; +use tendermint_rpc::endpoint::block_results::Response as BlockResultsResponse; +use tendermint_rpc::endpoint::tx; +use tendermint_rpc::HttpClient; +use time::OffsetDateTime; +use tracing::{debug, instrument, trace}; + +use hyperlane_core::{ + ChainCommunicationError, ChainResult, ContractLocator, HyperlaneDomain, LogMeta, H256, U256, +}; + +use crate::address::CosmosAddress; +use crate::rpc::CosmosRpcClient; +use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError}; + +#[async_trait] +/// Trait for wasm indexer. Use rpc provider +pub trait WasmRpcProvider: Send + Sync { + /// Get the finalized block height. + async fn get_finalized_block_number(&self) -> ChainResult; + + /// Get logs for the given block using the given parser. + async fn get_logs_in_block( + &self, + block_number: u32, + parser: for<'a> fn(&'a Vec) -> ChainResult>, + cursor_label: &'static str, + ) -> ChainResult> + where + T: Send + Sync + PartialEq + Debug + 'static; + + /// Get logs for the given transaction using the given parser. + async fn get_logs_in_tx( + &self, + tx_hash: Hash, + parser: for<'a> fn(&'a Vec) -> ChainResult>, + cursor_label: &'static str, + ) -> ChainResult> + where + T: Send + Sync + PartialEq + Debug + 'static; +} + +#[derive(Debug, Eq, PartialEq)] +/// An event parsed from the RPC response. +pub struct ParsedEvent { + contract_address: String, + event: T, +} + +impl ParsedEvent { + /// Create a new ParsedEvent. + pub fn new(contract_address: String, event: T) -> Self { + Self { + contract_address, + event, + } + } + + /// Get the inner event + pub fn inner(self) -> T { + self.event + } +} + +#[derive(Debug, Clone)] +/// Cosmwasm RPC Provider +pub struct CosmosWasmRpcProvider { + domain: HyperlaneDomain, + contract_address: CosmosAddress, + target_event_kind: String, + reorg_period: u32, + rpc_client: CosmosRpcClient, +} + +impl CosmosWasmRpcProvider { + const WASM_TYPE: &'static str = "wasm"; + + /// create new Cosmwasm RPC Provider + pub fn new( + conf: ConnectionConf, + locator: ContractLocator, + event_type: String, + reorg_period: u32, + ) -> ChainResult { + let rpc_client = CosmosRpcClient::new(&conf)?; + + Ok(Self { + domain: locator.domain.clone(), + contract_address: CosmosAddress::from_h256( + locator.address, + conf.get_bech32_prefix().as_str(), + conf.get_contract_address_bytes(), + )?, + target_event_kind: format!("{}-{}", Self::WASM_TYPE, event_type), + reorg_period, + rpc_client, + }) + } +} + +impl CosmosWasmRpcProvider { + // Iterate through all txs, filter out failed txs, find target events + // in successful txs, and parse them. + fn handle_txs( + &self, + block: BlockResponse, + block_results: BlockResultsResponse, + parser: for<'a> fn(&'a Vec) -> ChainResult>, + cursor_label: &'static str, + ) -> Vec<(T, LogMeta)> + where + T: PartialEq + Debug + 'static, + { + let Some(tx_results) = block_results.txs_results else { + return vec![]; + }; + + let tx_hashes: Vec = block + .clone() + .block + .data + .into_iter() + .filter_map(|tx| hex::decode(digest(tx.as_slice())).ok()) + .filter_map(|hash| Hash::from_bytes(Algorithm::Sha256, hash.as_slice()).ok()) + .collect(); + + tx_results + .into_iter() + .enumerate() + .filter_map(move |(idx, tx)| { + let Some(tx_hash) = tx_hashes.get(idx) else { + debug!(?tx, "No tx hash found for tx"); + return None; + }; + if tx.code.is_err() { + debug!(?tx_hash, "Not indexing failed transaction"); + return None; + } + + // We construct a simplified structure `tx::Response` here so that we can + // reuse `handle_tx` method below. + let tx_response = tx::Response { + hash: *tx_hash, + height: block_results.height, + index: idx as u32, + tx_result: tx, + tx: vec![], + proof: None, + }; + + let block_hash = H256::from_slice(block.block_id.hash.as_bytes()); + + Some(self.handle_tx(tx_response, block_hash, parser)) + }) + .flatten() + .collect() + } + + // Iter through all events in the tx, looking for any target events + // made by the contract we are indexing. + fn handle_tx( + &self, + tx: tx::Response, + block_hash: H256, + parser: for<'a> fn(&'a Vec) -> ChainResult>, + ) -> impl Iterator + '_ + where + T: PartialEq + 'static, + { + let tx_events = tx.tx_result.events; + let tx_hash = tx.hash; + let tx_index = tx.index; + let block_height = tx.height; + + tx_events.into_iter().enumerate().filter_map(move |(log_idx, event)| { + if event.kind.as_str() != self.target_event_kind { + return None; + } + + parser(&event.attributes) + .map_err(|err| { + // This can happen if we attempt to parse an event that just happens + // to have the same name but a different structure. + trace!(?err, tx_hash=?tx_hash, log_idx, ?event, "Failed to parse event attributes"); + }) + .ok() + .and_then(|parsed_event| { + // This is crucial! We need to make sure that the contract address + // in the event matches the contract address we are indexing. + // Otherwise, we might index events from other contracts that happen + // to have the same target event name. + if parsed_event.contract_address != self.contract_address.address() { + trace!(tx_hash=?tx_hash, log_idx, ?event, "Event contract address does not match indexer contract address"); + return None; + } + + Some((parsed_event.event, LogMeta { + address: self.contract_address.digest(), + block_number: block_height.value(), + block_hash, + transaction_id: H256::from_slice(tx_hash.as_bytes()).into(), + transaction_index: tx_index as u64, + log_index: U256::from(log_idx), + })) + }) + }) + } +} + +#[async_trait] +impl WasmRpcProvider for CosmosWasmRpcProvider { + #[instrument(err, skip(self))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn get_finalized_block_number(&self) -> ChainResult { + let latest_block = self.rpc_client.get_latest_block().await?; + let latest_height: u32 = latest_block + .block + .header + .height + .value() + .try_into() + .map_err(ChainCommunicationError::from_other)?; + Ok(latest_height.saturating_sub(self.reorg_period)) + } + + #[instrument(err, skip(self, parser))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn get_logs_in_block( + &self, + block_number: u32, + parser: for<'a> fn(&'a Vec) -> ChainResult>, + cursor_label: &'static str, + ) -> ChainResult> + where + T: Send + Sync + PartialEq + Debug + 'static, + { + debug!(?block_number, cursor_label, domain=?self.domain, "Getting logs in block"); + + // The two calls below could be made in parallel, but on cosmos rate limiting is a bigger problem + // than indexing latency, so we do them sequentially. + let block = self.rpc_client.get_block(block_number).await?; + let block_results = self.rpc_client.get_block_results(block_number).await?; + + Ok(self.handle_txs(block, block_results, parser, cursor_label)) + } + + #[instrument(err, skip(self, parser))] + #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue + async fn get_logs_in_tx( + &self, + hash: Hash, + parser: for<'a> fn(&'a Vec) -> ChainResult>, + cursor_label: &'static str, + ) -> ChainResult> + where + T: Send + Sync + PartialEq + Debug + 'static, + { + debug!(?hash, cursor_label, domain=?self.domain, "Getting logs in transaction"); + + let tx = self.rpc_client.get_tx_by_hash(hash).await?; + let block = self.rpc_client.get_block(tx.height.value() as u32).await?; + let block_hash = H256::from_slice(block.block_id.hash.as_bytes()); + + Ok(self.handle_tx(tx, block_hash, parser).collect()) + } +} diff --git a/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs b/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs index 63b759f1b..f7d3620eb 100644 --- a/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs +++ b/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs @@ -35,7 +35,7 @@ impl CosmosRoutingIsm { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; diff --git a/rust/main/chains/hyperlane-cosmos/src/utils.rs b/rust/main/chains/hyperlane-cosmos/src/utils.rs index 032700785..74cb75a27 100644 --- a/rust/main/chains/hyperlane-cosmos/src/utils.rs +++ b/rust/main/chains/hyperlane-cosmos/src/utils.rs @@ -6,13 +6,15 @@ use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; use futures::future; use once_cell::sync::Lazy; use tendermint::abci::EventAttribute; +use tendermint::hash::Algorithm; +use tendermint::Hash; use tokio::task::JoinHandle; use tracing::warn; -use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta}; +use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta, H256}; use crate::grpc::{WasmGrpcProvider, WasmProvider}; -use crate::rpc::{CosmosWasmIndexer, ParsedEvent, WasmIndexer}; +use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; type FutureChainResults = Vec>, u32)>>; @@ -43,21 +45,37 @@ pub(crate) async fn get_block_height_for_lag( pub(crate) fn parse_logs_in_range( range: RangeInclusive, - indexer: Box, + provider: Box, parser: for<'a> fn(&'a Vec) -> ChainResult>, label: &'static str, ) -> FutureChainResults { range .map(|block_number| { - let indexer = indexer.clone(); + let provider = provider.clone(); tokio::spawn(async move { - let logs = indexer.get_logs_in_block(block_number, parser, label).await; + let logs = provider + .get_logs_in_block(block_number, parser, label) + .await; (logs, block_number) }) }) .collect() } +pub(crate) async fn parse_logs_in_tx( + hash: &H256, + provider: Box, + parser: for<'a> fn(&'a Vec) -> ChainResult>, + label: &'static str, +) -> ChainResult> { + let tendermint_hash = Hash::from_bytes(Algorithm::Sha256, hash.as_bytes()) + .expect("transaction hash should be of correct size"); + + provider + .get_logs_in_tx(tendermint_hash, parser, label) + .await +} + #[allow(clippy::type_complexity)] pub(crate) async fn execute_and_parse_log_futures>>( logs_futures: Vec, ChainCommunicationError>, u32)>>, diff --git a/rust/main/chains/hyperlane-cosmos/src/validator_announce.rs b/rust/main/chains/hyperlane-cosmos/src/validator_announce.rs index 9ead17f8f..d82b0e829 100644 --- a/rust/main/chains/hyperlane-cosmos/src/validator_announce.rs +++ b/rust/main/chains/hyperlane-cosmos/src/validator_announce.rs @@ -35,7 +35,7 @@ impl CosmosValidatorAnnounce { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), signer, )?; diff --git a/rust/main/hyperlane-base/src/settings/chains.rs b/rust/main/hyperlane-base/src/settings/chains.rs index 34de1192a..8dcb2b9c5 100644 --- a/rust/main/hyperlane-base/src/settings/chains.rs +++ b/rust/main/hyperlane-base/src/settings/chains.rs @@ -188,7 +188,7 @@ impl ChainConf { let provider = CosmosProvider::new( locator.domain.clone(), conf.clone(), - Some(locator.clone()), + locator.clone(), None, )?; Ok(Box::new(provider) as Box) From aef3dbf4d6f2f73475f37eaad1235a7a07521a5c Mon Sep 17 00:00:00 2001 From: xeno097 Date: Fri, 20 Sep 2024 07:08:28 -0400 Subject: [PATCH 055/224] feat: remove mailbox confirmation prompt for `warp init` command (#4485) ### Description This PR removes the mailbox address confirmation prompt from the `warp init` command. The command now uses the default mailbox value retrieved from the registry and asks for user input only if a mailbox address is not found in the registry for the selected chain. - Adds a `isAddressAndMatchesProtocol` function to validate that a provided string is a valid address and belongs to an expected protocol (Ethereum, Solana, ...) - Adds address validation for the user-provided mailbox address using the newly implemented `isAddressAndMatchesProtocol` function Before: image After: image image image ### Drive-by changes - No ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4463 ### Backward compatibility - Yes ### Testing - Manual testing Notes: - E2e test implementation was attempted but testing prompts have proven difficult and require further investigation/hacking to see if there is a way to test user prompts. --- .changeset/lazy-flies-sin.md | 5 +++++ typescript/cli/src/config/warp.ts | 29 ++++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 .changeset/lazy-flies-sin.md diff --git a/.changeset/lazy-flies-sin.md b/.changeset/lazy-flies-sin.md new file mode 100644 index 000000000..33b439809 --- /dev/null +++ b/.changeset/lazy-flies-sin.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +Remove mailbox choice prompt if it can be automatically detected from the registry diff --git a/typescript/cli/src/config/warp.ts b/typescript/cli/src/config/warp.ts index 240e0e39d..8e15ccc3c 100644 --- a/typescript/cli/src/config/warp.ts +++ b/typescript/cli/src/config/warp.ts @@ -12,7 +12,13 @@ import { WarpRouteDeployConfig, WarpRouteDeployConfigSchema, } from '@hyperlane-xyz/sdk'; -import { Address, assert, objMap, promiseObjAll } from '@hyperlane-xyz/utils'; +import { + Address, + assert, + isAddress, + objMap, + promiseObjAll, +} from '@hyperlane-xyz/utils'; import { CommandContext } from '../context/types.js'; import { errorRed, log, logBlue, logGreen } from '../logger.js'; @@ -125,6 +131,17 @@ export async function createWarpRouteDeployConfig({ const result: WarpRouteDeployConfig = {}; for (const chain of warpChains) { logBlue(`${chain}: Configuring warp route...`); + + // default to the mailbox from the registry and if not found ask to the user to submit one + const chainAddresses = await context.registry.getChainAddresses(chain); + + const mailbox = + chainAddresses?.mailbox ?? + (await input({ + validate: isAddress, + message: `Could not retrieve mailbox address from the registry for chain "${chain}". Please enter a valid mailbox address:`, + })); + const type = await select({ message: `Select ${chain}'s token type`, choices: TYPE_CHOICES, @@ -134,16 +151,6 @@ export async function createWarpRouteDeployConfig({ const isNft = type === TokenType.syntheticUri || type === TokenType.collateralUri; - const mailbox = await detectAndConfirmOrPrompt( - async () => { - const addresses = await context.registry.getChainAddresses(chain); - return addresses?.mailbox; - }, - `For ${chain}, enter the`, - 'mailbox address', - 'hyperlane-registry', - ); - const interchainSecurityModule = advanced ? await createAdvancedIsmConfig(context) : createDefaultWarpIsmConfig(owner); From b872d635e194e93b8813c207b557487ecd1a588a Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:59:02 +0100 Subject: [PATCH 056/224] =?UTF-8?q?chore:=20include=20txids=20in=20indexin?= =?UTF-8?q?g=20logs;=20add=20vscode=20config=20for=20rust-ana=E2=80=A6=20(?= =?UTF-8?q?#4537)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - adds support for rust-analyzer with the new workspace split - includes txids in agent indexing logs, to more easily link message_ids to their txid. @Mo-Hussain and I spent quite some time today trying to find the corresponding txid --- mono.code-workspace | 11 ++++++++++- rust/main/hyperlane-base/src/contract_sync/mod.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/mono.code-workspace b/mono.code-workspace index 447d67634..f23838cd6 100644 --- a/mono.code-workspace +++ b/mono.code-workspace @@ -20,6 +20,10 @@ "cSpell.words": [ "hyperlane" ], + "rust-analyzer.linkedProjects": [ + "./rust/main/Cargo.toml", + "./rust/sealevel/Cargo.toml", + ], }, "folders": [ { @@ -33,7 +37,10 @@ "path": "./solidity" }, { - "path": "./rust" + "path": "./rust/main" + }, + { + "path": "./rust/sealevel" } ], "extensions": { @@ -66,6 +73,8 @@ "yoavbls.pretty-ts-errors", // Yaml language support "redhat.vscode-yaml", + // Rust language support + "rust-lang.rust-analyzer" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] diff --git a/rust/main/hyperlane-base/src/contract_sync/mod.rs b/rust/main/hyperlane-base/src/contract_sync/mod.rs index 50d0eac0f..5105a1ade 100644 --- a/rust/main/hyperlane-base/src/contract_sync/mod.rs +++ b/rust/main/hyperlane-base/src/contract_sync/mod.rs @@ -31,6 +31,14 @@ use cursors::ForwardBackwardSequenceAwareSyncCursor; const SLEEP_DURATION: Duration = Duration::from_secs(5); +#[derive(Debug, derive_new::new)] +#[allow(dead_code)] +/// Utility struct for pretty-printing indexed items. +struct IndexedTxIdAndSequence { + tx_id: H512, + sequence: Option, +} + /// Entity that drives the syncing of an agent's db with on-chain data. /// Extracts chain-specific data (emitted checkpoints, messages, etc) from an /// `indexer` and fills the agent's db with this data. @@ -172,7 +180,7 @@ where ?range, num_logs = logs_found, estimated_time_to_sync = fmt_sync_time(eta), - sequences = ?logs.iter().map(|(log, _)| log.sequence).collect::>(), + sequences = ?logs.iter().map(|(log, meta)| IndexedTxIdAndSequence::new(meta.transaction_id, log.sequence)).collect::>(), cursor = ?cursor, "Found log(s) in index range" ); From 35d4503b94d107621aa9351308a13ccd6c681db8 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:49:57 +0100 Subject: [PATCH 057/224] chore: new svm warp route artifacts (#4531) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --------- Co-authored-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/hip-yaks-switch.md | 7 +++++ .gitignore | 2 -- .registryrc | 2 +- rust/main/config/mainnet_config.json | 10 +++---- .../warp-routes/eclipsesol/program-ids.json | 12 ++++----- .../warp-routes/eclipseteth/program-ids.json | 14 +++++----- .../warp-routes/eclipseteth/token-config.json | 4 +-- .../warp-routes/eclipseusdc/program-ids.json | 18 ++++++------- typescript/cli/package.json | 2 +- typescript/helloworld/package.json | 2 +- .../config/environments/mainnet3/agent.ts | 4 +-- typescript/infra/package.json | 2 +- typescript/widgets/package.json | 2 +- yarn.lock | 26 ++++++------------- 14 files changed, 51 insertions(+), 56 deletions(-) create mode 100644 .changeset/hip-yaks-switch.md diff --git a/.changeset/hip-yaks-switch.md b/.changeset/hip-yaks-switch.md new file mode 100644 index 000000000..b11ef8f10 --- /dev/null +++ b/.changeset/hip-yaks-switch.md @@ -0,0 +1,7 @@ +--- +'@hyperlane-xyz/helloworld': minor +'@hyperlane-xyz/widgets': minor +'@hyperlane-xyz/cli': minor +--- + +Update to registry v4.3.6 diff --git a/.gitignore b/.gitignore index 5acf861cd..82e68e79d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,5 @@ yarn-error.log .idea **/*.ignore -/.vscode -!/.vscode/* tsconfig.editor.json diff --git a/.registryrc b/.registryrc index b913b7c65..4a24b8cb7 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -v4.1.0 +v4.3.6 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index fa99ee61a..b3c01dccf 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -758,7 +758,7 @@ "eclipsemainnet": { "blockExplorers": [ { - "apiUrl": "https://mainnetbeta-rpc.eclipse.xyz", + "apiUrl": "https://explorer.eclipse.xyz/api", "family": "other", "name": "Eclipse Explorer", "url": "https://explorer.eclipse.xyz/" @@ -3934,10 +3934,10 @@ "everclear": { "blockExplorers": [ { - "apiUrl": "https://everclear.cloud.blockscout.com/api", + "apiUrl": "https://scan.everclear.org/api", "family": "blockscout", "name": "Everclear Explorer", - "url": "https://everclear.cloud.blockscout.com" + "url": "https://scan.everclear.org" } ], "blocks": { @@ -3976,7 +3976,7 @@ "interchainAccountIsm": "0xcd9D3744512F07AE844c40E27912092d7c503565", "interchainAccountRouter": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8", "interchainGasPaymaster": "0xb58257cc81E47EC72fD38aE16297048de23163b4", - "interchainSecurityModule": "0xD5a72d4EF4D7db52C12802d0e3fBEF47b268e0dB", + "interchainSecurityModule": "0xA16954f5040ba7fE2286569aD107a22a46FffDC6", "mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", "merkleTreeHook": "0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1", "pausableHook": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", @@ -4036,7 +4036,7 @@ "interchainAccountIsm": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319", "interchainAccountRouter": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE", "interchainGasPaymaster": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86", - "interchainSecurityModule": "0x9E59d69F8e23dc159761Ca713C61a081422d1d47", + "interchainSecurityModule": "0x128432015A0E08d490e0FD6b4dE4EAbe30f617a3", "mailbox": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", "merkleTreeHook": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", "pausableHook": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2", diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/program-ids.json index bfb247531..f123070fd 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/program-ids.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/program-ids.json @@ -1,10 +1,10 @@ { - "eclipsemainnet": { - "hex": "0xe3f33280ca1f35cb45cc637993b90ce5c7ee8959da401b1763a9de81a7a8eddf", - "base58": "GLpdg3jt6w4eVYiCMhokVZ4mX6hmRvPhcL5RoCjzGr5k" - }, "solanamainnet": { - "hex": "0x3394c8f8213bfcd718f284ddfb65b13777287416b80c9a355bbfb2b1278fc7bd", - "base58": "4UMNyNWW75zo69hxoJaRX5iXNUa5FdRPZZa9vDVCiESg" + "hex": "0x6b4e9fed101f020c0b989737843efb49ac1aa918aa992c4a3808d29bc12f7efd", + "base58": "8DtAGQpcMuD5sG3KdxDy49ydqXUggR1LQtebh2TECbAc" + }, + "eclipsemainnet": { + "hex": "0xd49959a478c4c4170ef86528b8e14646d0a94b4ecbc0582f28d7e4de2e4f5b44", + "base58": "FJu4E1BDYKVg7aTWdwATZRUvytJZ8ZZ2gQuvPfMWAz9y" } } \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json index 5b816e08e..7f4be7582 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/program-ids.json @@ -1,10 +1,10 @@ { - "ethereum": { - "hex": "0x0000000000000000000000003ac6a6cca0b49c3f3f06d12f46e8d88eefbb7415", - "base58": "111111111111pVc7hF6xGk4TFPJAr7cTknNSZit" - }, "eclipsemainnet": { - "hex": "0x99151bae88c2a4620b24ede803232e0cedb5f762dbc11b8c65761b93df22d791", - "base58": "BJa3fPvvjKx8gRCWunoSrWBbsmieub37gsGpjp4BfTfW" + "hex": "0x4e38e43e87ba8942a6c5cfa81445cde1a08400a8d6cb5850f40135aed1ba1c11", + "base58": "6GM7hy6M6LjhadG1xuKXPQ3jPC1eieEszR8DforoRzUp" + }, + "ethereum": { + "hex": "0x000000000000000000000000c2495f3183f043627caecd56daaa726e3b2d9c09", + "base58": "1111111111113hzUGDMkDVcewnZG9Zd1bY8j2op4" } -} +} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json index 921cad451..d6c4b02fd 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseteth/token-config.json @@ -5,13 +5,13 @@ "remoteDecimals": 18, "name": "Turbo ETH", "symbol": "tETH", - "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/77a04c0b7e214ae17853215467f8ddea5e0ac710/deployments/warp_routes/tETH/metadata.json", + "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/f5c3d59c5f0155618ae156c971ace5894a88cec6/deployments/warp_routes/tETH/metadata.json", "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" }, "ethereum": { "type": "collateral", "decimals": 18, "token": "0x19e099B7aEd41FA52718D780dDA74678113C0b32", - "foreignDeployment": "0x3Ac6A6Cca0b49C3f3f06D12F46e8d88EEfbB7415" + "foreignDeployment": "0xc2495f3183F043627CAECD56dAaa726e3B2D9c09" } } diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json index 9a5d4f868..453a2bc2b 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/program-ids.json @@ -1,14 +1,14 @@ { - "solanamainnet": { - "hex": "0xd9aa20b2eb8965db1c5ac0af8608dd1f1e223838b4c0324767728a4a250f95cb", - "base58": "Fefw54S6NDdwNbPngPePvW4tiFTFQDT7gBPvFoDFeGqg" + "eclipsemainnet": { + "hex": "0xcd8f7348bdee9233f64432ab826c3526692e6cb17d6a5a5ddacfe3cbd0d77a9e", + "base58": "EqRSt9aUDMKYKhzd1DGMderr3KNp29VZH3x5P7LFTC8m" }, "ethereum": { - "hex": "0x000000000000000000000000fc8f5272d690cf19732a7ed6f246adf5fb8708db", - "base58": "1111111111114X5Wp5Z6aWk6v7FMSteKXMS6myvi" + "hex": "0x000000000000000000000000e1de9910fe71cc216490ac7fcf019e13a34481d7", + "base58": "11111111111149We9K5tM8ijcyNy9zDMG9RyDBCJ" }, - "eclipsemainnet": { - "hex": "0xb3c4dfa7156aada50e24f6e5c5630a246265ad2fd9a5856233481e8ed52c9f84", - "base58": "D6k6T3G74ij6atCtBiWBs5TbFa1hFVcrFUSGZHuV7q3Z" + "solanamainnet": { + "hex": "0x21419dfbe06b0ab41171d012ac511e058f2d036333e003f0c2e6003ac8dea12c", + "base58": "3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm" } -} \ No newline at end of file +} diff --git a/typescript/cli/package.json b/typescript/cli/package.json index 85b1de5df..e28e89b7a 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -5,7 +5,7 @@ "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", - "@hyperlane-xyz/registry": "4.3.2", + "@hyperlane-xyz/registry": "4.3.6", "@hyperlane-xyz/sdk": "5.2.1", "@hyperlane-xyz/utils": "5.2.1", "@inquirer/prompts": "^3.0.0", diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index 941c8dcee..c53c002b9 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -4,7 +4,7 @@ "version": "5.2.1", "dependencies": { "@hyperlane-xyz/core": "5.2.1", - "@hyperlane-xyz/registry": "4.1.0", + "@hyperlane-xyz/registry": "4.3.6", "@hyperlane-xyz/sdk": "5.2.1", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index ca61148df..a00e6a3c4 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -378,7 +378,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '5a0d68b-20240916-144115', + tag: '946dec8-20240919-151233', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -412,7 +412,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '5a0d68b-20240916-144115', + tag: '946dec8-20240919-151233', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. diff --git a/typescript/infra/package.json b/typescript/infra/package.json index c0c235c37..849387d06 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -14,7 +14,7 @@ "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", "@hyperlane-xyz/helloworld": "5.2.1", - "@hyperlane-xyz/registry": "4.3.2", + "@hyperlane-xyz/registry": "4.3.6", "@hyperlane-xyz/sdk": "5.2.1", "@hyperlane-xyz/utils": "5.2.1", "@inquirer/prompts": "^5.3.8", diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 95e5247c6..604ebe3a1 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -7,7 +7,7 @@ "react-dom": "^18" }, "dependencies": { - "@hyperlane-xyz/registry": "4.3.2", + "@hyperlane-xyz/registry": "4.3.6", "@hyperlane-xyz/sdk": "5.2.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 33d36fafe..5255a6e82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7590,7 +7590,7 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.577.0" "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" - "@hyperlane-xyz/registry": "npm:4.3.2" + "@hyperlane-xyz/registry": "npm:4.3.6" "@hyperlane-xyz/sdk": "npm:5.2.1" "@hyperlane-xyz/utils": "npm:5.2.1" "@inquirer/prompts": "npm:^3.0.0" @@ -7683,7 +7683,7 @@ __metadata: resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: "@hyperlane-xyz/core": "npm:5.2.1" - "@hyperlane-xyz/registry": "npm:4.1.0" + "@hyperlane-xyz/registry": "npm:4.3.6" "@hyperlane-xyz/sdk": "npm:5.2.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" @@ -7732,7 +7732,7 @@ __metadata: "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" "@hyperlane-xyz/helloworld": "npm:5.2.1" - "@hyperlane-xyz/registry": "npm:4.3.2" + "@hyperlane-xyz/registry": "npm:4.3.6" "@hyperlane-xyz/sdk": "npm:5.2.1" "@hyperlane-xyz/utils": "npm:5.2.1" "@inquirer/prompts": "npm:^5.3.8" @@ -7790,23 +7790,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/registry@npm:4.1.0": - version: 4.1.0 - resolution: "@hyperlane-xyz/registry@npm:4.1.0" - dependencies: - yaml: "npm:2.4.5" - zod: "npm:^3.21.2" - checksum: 5de3ef5539abfaadbfefb82e6e69fdb2413f404d8321456c91810fb50a5a70e9f93b38789495efce6ab5963682536e95a2abe636c7d0ad91ee158cc0ce6b063a - languageName: node - linkType: hard - -"@hyperlane-xyz/registry@npm:4.3.2": - version: 4.3.2 - resolution: "@hyperlane-xyz/registry@npm:4.3.2" +"@hyperlane-xyz/registry@npm:4.3.6": + version: 4.3.6 + resolution: "@hyperlane-xyz/registry@npm:4.3.6" dependencies: yaml: "npm:2.4.5" zod: "npm:^3.21.2" - checksum: 7b1ff07074e4499f74a4c75dbbf0b7e641b3610bfc2a67785db724748d887d7b03c9dc9738b790cb56e008d6453789432c863f3b251498f77c931f196b9dab86 + checksum: 7cc42813f4f8b8ef09266be249f3dcec0584832166419df2f48eec3cc43ba766e58845ecc16673bf6465a711f08ff6c4fc5216da2f704bc31ef8ade52af4b6e5 languageName: node linkType: hard @@ -7884,7 +7874,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: - "@hyperlane-xyz/registry": "npm:4.3.2" + "@hyperlane-xyz/registry": "npm:4.3.6" "@hyperlane-xyz/sdk": "npm:5.2.1" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" From 0744137f38bf63ed5e7029bda227805a2a8790a5 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:07:46 +0100 Subject: [PATCH 058/224] feat: v3 Jito submission (#3429) (#4528) Ports this v2 fix to v3 https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/3434 originally authored by @tkporter --------- Co-authored-by: Trevor Porter Co-authored-by: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> --- rust/main/Cargo.lock | 4 + .../main/chains/hyperlane-sealevel/Cargo.toml | 4 + .../chains/hyperlane-sealevel/src/mailbox.rs | 171 +++++++++++++++++- 3 files changed, 169 insertions(+), 10 deletions(-) diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index 9364cf598..f58a90d40 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -4607,6 +4607,7 @@ dependencies = [ "anyhow", "async-trait", "base64 0.21.7", + "bincode", "borsh 0.9.3", "derive-new", "hyperlane-core", @@ -4619,13 +4620,16 @@ dependencies = [ "jsonrpc-core", "multisig-ism", "num-traits", + "reqwest", "serde", + "serde_json", "serializable-account-meta", "solana-account-decoder", "solana-client", "solana-sdk", "solana-transaction-status", "thiserror", + "tokio", "tracing", "tracing-futures", "url", diff --git a/rust/main/chains/hyperlane-sealevel/Cargo.toml b/rust/main/chains/hyperlane-sealevel/Cargo.toml index 8179ff94c..3a1bda12f 100644 --- a/rust/main/chains/hyperlane-sealevel/Cargo.toml +++ b/rust/main/chains/hyperlane-sealevel/Cargo.toml @@ -7,16 +7,20 @@ edition = "2021" anyhow.workspace = true async-trait.workspace = true base64.workspace = true +bincode.workspace = true borsh.workspace = true derive-new.workspace = true jsonrpc-core.workspace = true num-traits.workspace = true +reqwest.workspace = true serde.workspace = true +serde_json.workspace = true solana-account-decoder.workspace = true solana-client.workspace = true solana-sdk.workspace = true solana-transaction-status.workspace = true thiserror.workspace = true +tokio.workspace = true tracing-futures.workspace = true tracing.workspace = true url.workspace = true diff --git a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs index beb4e86c3..e919b2de7 100644 --- a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs @@ -11,8 +11,8 @@ use hyperlane_core::{ accumulator::incremental::IncrementalMerkle, BatchItem, ChainCommunicationError, ChainResult, Checkpoint, ContractLocator, Decode as _, Encode as _, FixedPointNumber, HyperlaneAbi, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, - Indexed, Indexer, LogMeta, Mailbox, MerkleTreeHook, SequenceAwareIndexer, TxCostEstimate, - TxOutcome, H256, H512, U256, + Indexed, Indexer, KnownHyperlaneDomain, LogMeta, Mailbox, MerkleTreeHook, SequenceAwareIndexer, + TxCostEstimate, TxOutcome, H256, H512, U256, }; use hyperlane_sealevel_interchain_security_module_interface::{ InterchainSecurityModuleInstruction, VerifyInstruction, @@ -30,16 +30,17 @@ use serializable_account_meta::SimulationReturnData; use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}; use solana_client::{ nonblocking::rpc_client::RpcClient, + rpc_client::SerializableTransaction, rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcSendTransactionConfig}, rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType}, }; use solana_sdk::{ account::Account, + bs58, commitment_config::CommitmentConfig, compute_budget::ComputeBudgetInstruction, hash::Hash, - instruction::AccountMeta, - instruction::Instruction, + instruction::{AccountMeta, Instruction}, message::Message, pubkey::Pubkey, signature::Signature, @@ -65,6 +66,24 @@ const SPL_NOOP: &str = "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV"; // TODO: consider a more sane value and/or use IGP gas payments instead. const PROCESS_COMPUTE_UNITS: u32 = 1_400_000; +/// 0.0005 SOL, in lamports. +/// A typical tx fee without a prioritization fee is 0.000005 SOL, or +/// 5000 lamports. (Example: https://explorer.solana.com/tx/fNd3xVeBzFHeuzr8dXQxLGiHMzTeYpykSV25xWzNRaHtzzjvY9A3MzXh1ZsK2JncRHkwtuWrGEwGXVhFaUCYhtx) +/// See average priority fees here https://solanacompass.com/statistics/fees +/// to inform what to spend here. +const PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX: u64 = 500000; + +/// In micro-lamports. Multiply this by the compute units to figure out +/// the additional cost of processing a message, in addition to the mandatory +/// "base" cost of signature verification. +const PROCESS_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS: u64 = + ( + // Convert to micro-lamports + (PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX * 1_000_000) + // Divide by the max compute units + / PROCESS_COMPUTE_UNITS as u64 + ); + /// A reference to a Mailbox contract on some Sealevel chain pub struct SealevelMailbox { pub(crate) program_id: Pubkey, @@ -253,6 +272,129 @@ impl SealevelMailbox { self.get_account_metas(instruction).await } + + fn use_jito(&self) -> bool { + matches!( + self.domain(), + HyperlaneDomain::Known(KnownHyperlaneDomain::SolanaMainnet) + ) + } + + async fn send_and_confirm_transaction( + &self, + transaction: &Transaction, + ) -> ChainResult { + if self.use_jito() { + self.send_and_confirm_transaction_with_jito(transaction) + .await + } else { + self.provider + .rpc() + .send_and_confirm_transaction(transaction) + .await + .map_err(ChainCommunicationError::from_other) + } + } + + // Stolen from Solana's non-blocking client, but with Jito! + pub async fn send_and_confirm_transaction_with_jito( + &self, + transaction: &impl SerializableTransaction, + ) -> ChainResult { + let signature = transaction.get_signature(); + + let base58_txn = bs58::encode( + bincode::serialize(&transaction).map_err(ChainCommunicationError::from_other)?, + ) + .into_string(); + + const SEND_RETRIES: usize = 1; + const GET_STATUS_RETRIES: usize = usize::MAX; + + 'sending: for _ in 0..SEND_RETRIES { + let jito_request_body = serde_json::json!({ + "jsonrpc": "2.0", + "id": 1, + "method": "sendBundle", + "params": [ + [base58_txn] + ], + }); + + tracing::info!( + ?jito_request_body, + ?signature, + "Sending sealevel transaction to Jito as bundle" + ); + + let jito_response = reqwest::Client::new() + .post("https://mainnet.block-engine.jito.wtf:443/api/v1/bundles") + .json(&jito_request_body) + .send() + .await + .map_err(ChainCommunicationError::from_other)?; + let jito_response_text = jito_response.text().await; + + tracing::info!( + ?signature, + ?jito_response_text, + "Got Jito response for sealevel transaction bundle" + ); + + let recent_blockhash = if transaction.uses_durable_nonce() { + let (recent_blockhash, ..) = self + .provider + .rpc() + .get_latest_blockhash_with_commitment(CommitmentConfig::processed()) + .await + .map_err(ChainCommunicationError::from_other)?; + recent_blockhash + } else { + *transaction.get_recent_blockhash() + }; + + for status_retry in 0..GET_STATUS_RETRIES { + match self + .provider + .rpc() + .get_signature_status(&signature) + .await + .map_err(ChainCommunicationError::from_other)? + { + Some(Ok(_)) => return Ok(*signature), + Some(Err(e)) => return Err(ChainCommunicationError::from_other(e)), + None => { + if !self + .provider + .rpc() + .is_blockhash_valid(&recent_blockhash, CommitmentConfig::processed()) + .await + .map_err(ChainCommunicationError::from_other)? + { + // Block hash is not found by some reason + break 'sending; + } else if cfg!(not(test)) + // Ignore sleep at last step. + && status_retry < GET_STATUS_RETRIES + { + // Retry twice a second + tokio::time::sleep(std::time::Duration::from_millis(500)).await; + continue; + } + } + } + } + } + + Err(ChainCommunicationError::from_other( + solana_client::rpc_request::RpcError::ForUser( + "unable to confirm transaction. \ + This can happen in situations such as transaction expiration \ + and insufficient fee-payer funds" + .to_string(), + ), + )) + } } impl HyperlaneContract for SealevelMailbox { @@ -353,12 +495,25 @@ impl Mailbox for SealevelMailbox { .as_ref() .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?; - let mut instructions = Vec::with_capacity(2); + let mut instructions = Vec::with_capacity(3); // Set the compute unit limit. instructions.push(ComputeBudgetInstruction::set_compute_unit_limit( PROCESS_COMPUTE_UNITS, )); + // If we're using Jito, we need to send a tip to the Jito fee account. + // Otherwise, we need to set the compute unit price. + if self.use_jito() { + // The tip is a standalone transfer to a Jito fee account. + // See https://github.com/jito-labs/mev-protos/blob/master/json_rpc/http.md#sendbundle. + instructions.push(solana_sdk::system_instruction::transfer( + &payer.pubkey(), + // A random Jito fee account, taken from the getFeeAccount RPC response: + // https://github.com/jito-labs/mev-protos/blob/master/json_rpc/http.md#gettipaccounts + &solana_sdk::pubkey!("DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh"), + PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX, + )); + } // "processed" level commitment does not guarantee finality. // roughly 5% of blocks end up on a dropped fork. // However we don't want this function to be a bottleneck and there already @@ -450,11 +605,7 @@ impl Mailbox for SealevelMailbox { tracing::info!(?txn, "Created sealevel transaction to process message"); - let signature = self - .rpc() - .send_and_confirm_transaction(&txn) - .await - .map_err(ChainCommunicationError::from_other)?; + let signature = self.send_and_confirm_transaction(&txn).await?; tracing::info!(?txn, ?signature, "Sealevel transaction sent"); From f36beb683109f620dfd36560e79b29f687fa4e5a Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Fri, 20 Sep 2024 17:52:55 +0100 Subject: [PATCH 059/224] feat: monitor sealevel ATA payer balances in the key funder (#4533) ### Description - Tested and set up alerts - We already have the relayer balances from the agents themselves, so just need the ATA payers (which are responsible for paying for the rent of token accounts that don't yet exist when bridging in) - Putting it here because it's easy and this is what we did in v2 (see #3432, which this is based off) ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --------- Co-authored-by: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> --- .../config/environments/mainnet3/funding.ts | 2 +- .../funding/fund-keys-from-deployer.ts | 95 +++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index 601f07b38..2376ebb9f 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '9c056c7-20240911-154400', + tag: '877656c-20240919-202332', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron diff --git a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts index 9a0cce0c0..081453c09 100644 --- a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts +++ b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts @@ -1,9 +1,11 @@ import { EthBridger, getL2Network } from '@arbitrum/sdk'; import { CrossChainMessenger } from '@eth-optimism/sdk'; +import { Connection, PublicKey } from '@solana/web3.js'; import { BigNumber, ethers } from 'ethers'; import { Gauge, Registry } from 'prom-client'; import { format } from 'util'; +import { eclipsemainnet } from '@hyperlane-xyz/registry'; import { ChainMap, ChainName, @@ -14,6 +16,7 @@ import { Address, objFilter, objMap, rootLogger } from '@hyperlane-xyz/utils'; import { Contexts } from '../../config/contexts.js'; import { getEnvAddresses } from '../../config/registry.js'; +import { getSecretRpcEndpoints } from '../../src/agents/index.js'; import { KeyAsAddress, fetchLocalKeyAddresses, @@ -96,6 +99,43 @@ const MIN_DELTA_DENOMINATOR = ethers.BigNumber.from(10); const RC_FUNDING_DISCOUNT_NUMERATOR = ethers.BigNumber.from(2); const RC_FUNDING_DISCOUNT_DENOMINATOR = ethers.BigNumber.from(10); +interface SealevelAccount { + pubkey: PublicKey; + walletName: string; +} + +const sealevelAccountsToTrack: ChainMap = { + solanamainnet: [ + { + // WIF warp route ATA payer + pubkey: new PublicKey('R5oMfxcbjx4ZYK1B2Aic1weqwt2tQsRzFEGe5WJfAxh'), + walletName: 'WIF/eclipsemainnet-solanamainnet/ata-payer', + }, + { + // USDC warp route ATA payer + pubkey: new PublicKey('A1XtL9mAzkNEpBPinrCpDRrPqVAFjgaxDk4ATFVoQVyc'), + walletName: 'USDC/eclipsemainnet-ethereum-solanamainnet/ata-payer', + }, + ], + eclipsemainnet: [ + { + // WIF warp route ATA payer + pubkey: new PublicKey('HCQAfDd5ytAEidzR9g7CipjEGv2ZrSSZq1UY34oDFv8h'), + walletName: 'WIF/eclipsemainnet-solanamainnet/ata-payer', + }, + { + // USDC warp route ATA payer + pubkey: new PublicKey('7arS1h8nwVVmmTVWSsu9rQ4WjLBN8iAi4DvHi8gWjBNC'), + walletName: 'USDC/eclipsemainnet-ethereum-solanamainnet/ata-payer', + }, + { + // tETH warp route ATA payer + pubkey: new PublicKey('Hyy4jryRxgZm5pvuSx29fXxJ9J55SuDtXiCo89kmNuz5'), + walletName: 'tETH/eclipsemainnet-ethereum/ata-payer', + }, + ], +}; + // Funds key addresses for multiple contexts from the deployer key of the context // specified via the `--context` flag. // The --contexts-and-roles flag is used to specify the contexts and the key roles @@ -466,6 +506,13 @@ class ContextFunder { false, ); + if ( + this.environment === 'mainnet3' && + this.context === Contexts.Hyperlane + ) { + await this.updateSolanaWalletBalanceGauge(); + } + return failureOccurred; } @@ -812,6 +859,54 @@ class ContextFunder { ), ); } + + private async updateSolanaWalletBalanceGauge() { + for (const chain of Object.keys(sealevelAccountsToTrack) as ChainName[]) { + await this.updateSealevelWalletBalanceAccounts( + chain, + sealevelAccountsToTrack[chain], + ); + } + } + + private async updateSealevelWalletBalanceAccounts( + chain: ChainName, + accounts: SealevelAccount[], + ) { + const rpcUrls = await getSecretRpcEndpoints(this.environment, chain); + const provider = new Connection(rpcUrls[0], 'confirmed'); + + for (const { pubkey, walletName } of accounts) { + logger.info( + { + chain, + pubkey: pubkey.toString(), + walletName, + }, + 'Fetching sealevel wallet balance', + ); + const balance = await provider.getBalance(pubkey); + logger.info( + { + balance, + chain, + pubkey: pubkey.toString(), + walletName, + }, + 'Retrieved sealevel chain wallet balance', + ); + walletBalanceGauge + .labels({ + chain, + wallet_address: pubkey.toString(), + wallet_name: walletName, + token_symbol: 'Native', + token_name: 'Native', + ...constMetricLabels, + }) + .set(balance / 1e9); + } + } } async function getAddressInfo( From c032b8ba2757657b272d6df3e8173e2fd7f4b596 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:40:46 +0530 Subject: [PATCH 060/224] chore: refactor MessagIdHook/ISM tests into a common `ExternalBridgeTest` contract (#4490) ### Description We currently have 6 different versions of ISMs derived from AbstractMessageIdAuthorizedIsm: - OPL2ToL1 - ArbL2ToL1 - OPStack (L1->L2) - ERC5164 - LayerZero - PolygonPOS But all of them have their own custom test suite right now, with widely overlapping testing areas. For standardizing the tests, I've created a base test contract `ExternalBridgeTest` that handles the common tests. This has a few benefits: - harder to miss tests for known pitfalls like msg.value or asynchronicity assumption for verifyMessageId - less code duplication with each additional Ism I have moved OPL2ToL1, ArbL2ToL1, OPStack, and ERC5164 to the new base test, and I'll forgo the rest for now because of the time sensitivity of audit remediations. I've created an issue tracking the remaining work here: https://github.com/hyperlane-xyz/issues/issues/1384 ### Drive-by changes None ### Related issues Related to https://github.com/chainlight-io/2024-08-hyperlane/issues/3 ### Backward compatibility Yes ### Testing Unit --- solidity/test/isms/ArbL2ToL1Ism.t.sol | 260 ++--------- solidity/test/isms/ERC5164ISM.t.sol | 152 ++----- solidity/test/isms/ExternalBridgeTest.sol | 268 +++++++++++ solidity/test/isms/OPL2ToL1Ism.t.sol | 238 ++-------- solidity/test/isms/OPStackIsm.t.sol | 529 ++++------------------ 5 files changed, 480 insertions(+), 967 deletions(-) create mode 100644 solidity/test/isms/ExternalBridgeTest.sol diff --git a/solidity/test/isms/ArbL2ToL1Ism.t.sol b/solidity/test/isms/ArbL2ToL1Ism.t.sol index f34c1a74e..a251cfda4 100644 --- a/solidity/test/isms/ArbL2ToL1Ism.t.sol +++ b/solidity/test/isms/ArbL2ToL1Ism.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT or Apache-2.0 pragma solidity ^0.8.13; -import {Test} from "forge-std/Test.sol"; - import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; import {MessageUtils} from "./IsmTestUtils.sol"; import {TestMailbox} from "../../contracts/test/TestMailbox.sol"; @@ -13,13 +11,9 @@ import {ArbL2ToL1Hook} from "../../contracts/hooks/ArbL2ToL1Hook.sol"; import {ArbL2ToL1Ism} from "../../contracts/isms/hook/ArbL2ToL1Ism.sol"; import {MockArbBridge, MockArbSys} from "../../contracts/mock/MockArbBridge.sol"; import {TestRecipient} from "../../contracts/test/TestRecipient.sol"; +import {ExternalBridgeTest} from "./ExternalBridgeTest.sol"; -contract ArbL2ToL1IsmTest is Test { - uint8 internal constant HYPERLANE_VERSION = 1; - uint32 internal constant MAINNET_DOMAIN = 1; - uint32 internal constant ARBITRUM_DOMAIN = 42161; - uint256 internal constant GAS_QUOTE = 120_000; - +contract ArbL2ToL1IsmTest is ExternalBridgeTest { uint256 internal constant MOCK_LEAF_INDEX = 40160; uint256 internal constant MOCK_L2_BLOCK = 54220000; uint256 internal constant MOCK_L1_BLOCK = 6098300; @@ -28,26 +22,14 @@ contract ArbL2ToL1IsmTest is Test { 0x0000000000000000000000000000000000000064; MockArbBridge internal arbBridge; - TestMailbox public l2Mailbox; - ArbL2ToL1Hook public hook; - ArbL2ToL1Ism public ism; - TestRecipient internal testRecipient; - bytes internal testMessage = - abi.encodePacked("Hello from the other chain!"); - bytes internal encodedMessage; - bytes internal testMetadata = - StandardHookMetadata.overrideRefundAddress(address(this)); - bytes32 internal messageId; - - function setUp() public { + function setUp() public override { // Arbitrum bridge mock setup + GAS_QUOTE = 120_000; vm.etch(L2_ARBSYS_ADDRESS, address(new MockArbSys()).code); - testRecipient = new TestRecipient(); - - encodedMessage = _encodeTestMessage(); - messageId = Message.id(encodedMessage); + deployAll(); + super.setUp(); } /////////////////////////////////////////////////////////////////// @@ -55,10 +37,10 @@ contract ArbL2ToL1IsmTest is Test { /////////////////////////////////////////////////////////////////// function deployHook() public { - l2Mailbox = new TestMailbox(ARBITRUM_DOMAIN); + originMailbox = new TestMailbox(ORIGIN_DOMAIN); hook = new ArbL2ToL1Hook( - address(l2Mailbox), - MAINNET_DOMAIN, + address(originMailbox), + DESTINATION_DOMAIN, TypeCasts.addressToBytes32(address(ism)), L2_ARBSYS_ADDRESS, GAS_QUOTE @@ -67,7 +49,6 @@ contract ArbL2ToL1IsmTest is Test { function deployIsm() public { arbBridge = new MockArbBridge(); - ism = new ArbL2ToL1Ism(address(arbBridge)); } @@ -75,196 +56,39 @@ contract ArbL2ToL1IsmTest is Test { deployIsm(); deployHook(); + arbBridge.setL2ToL1Sender(address(hook)); ism.setAuthorizedHook(TypeCasts.addressToBytes32(address(hook))); } - function test_postDispatch() public { - deployAll(); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); - - l2Mailbox.updateLatestDispatchedId(messageId); + /* ============ helper functions ============ */ + function _expectOriginExternalBridgeCall( + bytes memory _encodedHookData + ) internal override { vm.expectCall( L2_ARBSYS_ADDRESS, abi.encodeCall( MockArbSys.sendTxToL1, - (address(ism), encodedHookData) + (address(ism), _encodedHookData) ) ); - hook.postDispatch(testMetadata, encodedMessage); - } - - function testFork_postDispatch_revertWhen_chainIDNotSupported() public { - deployAll(); - - bytes memory message = MessageUtils.formatMessage( - 0, - uint32(0), - ARBITRUM_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - 2, // wrong domain - TypeCasts.addressToBytes32(address(testRecipient)), - testMessage - ); - - l2Mailbox.updateLatestDispatchedId(Message.id(message)); - vm.expectRevert( - "AbstractMessageIdAuthHook: invalid destination domain" - ); - hook.postDispatch(testMetadata, message); - } - - function test_postDispatch_revertWhen_notLastDispatchedMessage() public { - deployAll(); - - vm.expectRevert( - "AbstractMessageIdAuthHook: message not latest dispatched" - ); - hook.postDispatch(testMetadata, encodedMessage); - } - - function test_verify_outboxCall() public { - deployAll(); - - bytes memory encodedOutboxTxMetadata = _encodeOutboxTx( - address(hook), - address(ism), - messageId, - 1 ether - ); - - vm.deal(address(arbBridge), 1 ether); - arbBridge.setL2ToL1Sender(address(hook)); - assertTrue(ism.verify(encodedOutboxTxMetadata, encodedMessage)); - assertEq(address(testRecipient).balance, 1 ether); } - function test_verify_statefulVerify() public { - deployAll(); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); - - arbBridge.setL2ToL1Sender(address(hook)); - arbBridge.executeTransaction{value: 1 ether}( - new bytes32[](0), - MOCK_LEAF_INDEX, - address(hook), - address(ism), - MOCK_L2_BLOCK, - MOCK_L1_BLOCK, - block.timestamp, - 1 ether, - encodedHookData - ); - - vm.etch(address(arbBridge), new bytes(0)); // this is a way to test that the arbBridge isn't called again - assertTrue(ism.verify(new bytes(0), encodedMessage)); - assertEq(address(testRecipient).balance, 1 ether); + function _encodeExternalDestinationBridgeCall( + address _from, + address _to, + uint256 _msgValue, + bytes32 _messageId + ) internal override returns (bytes memory) { + vm.deal(address(arbBridge), _msgValue); + return _encodeOutboxTx(_from, _to, _messageId, _msgValue); } - function test_verify_statefulAndOutbox() public { - deployAll(); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); - - arbBridge.setL2ToL1Sender(address(hook)); - arbBridge.executeTransaction{value: 1 ether}( - new bytes32[](0), - MOCK_LEAF_INDEX, - address(hook), - address(ism), - MOCK_L2_BLOCK, - MOCK_L1_BLOCK, - block.timestamp, - 1 ether, - encodedHookData - ); - - bytes memory encodedOutboxTxMetadata = _encodeOutboxTx( - address(hook), - address(ism), - messageId, - 1 ether - ); - - vm.etch(address(arbBridge), new bytes(0)); // this is a way to test that the arbBridge isn't called again - assertTrue(ism.verify(encodedOutboxTxMetadata, encodedMessage)); - assertEq(address(testRecipient).balance, 1 ether); - } - - function test_verify_revertsWhen_noStatefulOrOutbox() public { - deployAll(); - - vm.expectRevert(); - ism.verify(new bytes(0), encodedMessage); - } - - function test_verify_revertsWhen_notAuthorizedHook() public { - deployAll(); - - bytes memory encodedOutboxTxMetadata = _encodeOutboxTx( - address(this), - address(ism), - messageId, - 0 - ); - - arbBridge.setL2ToL1Sender(address(this)); - - vm.expectRevert("ArbL2ToL1Ism: l2Sender != authorizedHook"); - ism.verify(encodedOutboxTxMetadata, encodedMessage); - } - - function test_verify_revertsWhen_invalidIsm() public { - deployAll(); - - bytes memory encodedOutboxTxMetadata = _encodeOutboxTx( - address(hook), - address(this), - messageId, - 0 - ); - - arbBridge.setL2ToL1Sender(address(hook)); - - vm.expectRevert(); // BridgeCallFailed() - ism.verify(encodedOutboxTxMetadata, encodedMessage); - } - - function test_verify_revertsWhen_incorrectMessageId() public { - deployAll(); - - bytes32 incorrectMessageId = keccak256("incorrect message id"); - - bytes memory encodedOutboxTxMetadata = _encodeOutboxTx( - address(hook), - address(ism), - incorrectMessageId, - 0 - ); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (incorrectMessageId) - ); - - arbBridge.setL2ToL1Sender(address(hook)); - - // through outbox call - vm.expectRevert("ArbL2ToL1Ism: invalid message id"); - ism.verify(encodedOutboxTxMetadata, encodedMessage); - - // through statefulVerify + function _externalBridgeDestinationCall( + bytes memory _encodedHookData, + uint256 _msgValue + ) internal override { + vm.deal(address(arbBridge), _msgValue); arbBridge.executeTransaction( new bytes32[](0), MOCK_LEAF_INDEX, @@ -273,16 +97,17 @@ contract ArbL2ToL1IsmTest is Test { MOCK_L2_BLOCK, MOCK_L1_BLOCK, block.timestamp, - 0, - encodedHookData + _msgValue, + _encodedHookData ); - - vm.etch(address(arbBridge), new bytes(0)); // to stop the outbox route - vm.expectRevert(); - assertFalse(ism.verify(new bytes(0), encodedMessage)); } - /* ============ helper functions ============ */ + function _setExternalOriginSender( + address _sender + ) internal override returns (bytes memory unauthorizedHookErrorMsg) { + arbBridge.setL2ToL1Sender(_sender); + return "ArbL2ToL1Ism: l2Sender != authorizedHook"; + } function _encodeOutboxTx( address _hook, @@ -309,17 +134,4 @@ contract ArbL2ToL1IsmTest is Test { encodedHookData ); } - - function _encodeTestMessage() internal view returns (bytes memory) { - return - MessageUtils.formatMessage( - HYPERLANE_VERSION, - uint32(0), - ARBITRUM_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - MAINNET_DOMAIN, - TypeCasts.addressToBytes32(address(testRecipient)), - testMessage - ); - } } diff --git a/solidity/test/isms/ERC5164ISM.t.sol b/solidity/test/isms/ERC5164ISM.t.sol index c94052e25..75c79fb82 100644 --- a/solidity/test/isms/ERC5164ISM.t.sol +++ b/solidity/test/isms/ERC5164ISM.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT or Apache-2.0 pragma solidity ^0.8.13; -import {Test} from "forge-std/Test.sol"; - import {LibBit} from "../../contracts/libs/LibBit.sol"; import {Message} from "../../contracts/libs/Message.sol"; import {MessageUtils} from "./IsmTestUtils.sol"; @@ -17,8 +15,9 @@ import {ERC5164Ism} from "../../contracts/isms/hook/ERC5164Ism.sol"; import {TestMailbox} from "../../contracts/test/TestMailbox.sol"; import {TestRecipient} from "../../contracts/test/TestRecipient.sol"; import {MockMessageDispatcher, MockMessageExecutor} from "../../contracts/mock/MockERC5164.sol"; +import {ExternalBridgeTest} from "./ExternalBridgeTest.sol"; -contract ERC5164IsmTest is Test { +contract ERC5164IsmTest is ExternalBridgeTest { using LibBit for uint256; using TypeCasts for address; using Message for bytes; @@ -27,23 +26,8 @@ contract ERC5164IsmTest is Test { IMessageDispatcher internal dispatcher; MockMessageExecutor internal executor; - ERC5164Hook internal hook; - ERC5164Ism internal ism; - TestMailbox internal originMailbox; - TestRecipient internal testRecipient; - - uint32 internal constant TEST1_DOMAIN = 1; - uint32 internal constant TEST2_DOMAIN = 2; - - uint8 internal constant VERSION = 0; - bytes internal testMessage = - abi.encodePacked("Hello from the other chain!"); address internal alice = address(0x1); - // req for most tests - bytes encodedMessage = _encodeTestMessage(0, address(testRecipient)); - bytes32 messageId = encodedMessage.id(); - event MessageDispatched( bytes32 indexed messageId, address indexed from, @@ -56,19 +40,19 @@ contract ERC5164IsmTest is Test { /// SETUP /// /////////////////////////////////////////////////////////////////// - function setUp() public { + function setUp() public override { dispatcher = new MockMessageDispatcher(); executor = new MockMessageExecutor(); - testRecipient = new TestRecipient(); - originMailbox = new TestMailbox(TEST1_DOMAIN); + originMailbox = new TestMailbox(ORIGIN_DOMAIN); ism = new ERC5164Ism(address(executor)); hook = new ERC5164Hook( address(originMailbox), - TEST2_DOMAIN, + DESTINATION_DOMAIN, address(ism).addressToBytes32(), address(dispatcher) ); ism.setAuthorizedHook(TypeCasts.addressToBytes32(address(hook))); + super.setUp(); } /////////////////////////////////////////////////////////////////// @@ -100,7 +84,7 @@ contract ERC5164IsmTest is Test { vm.expectRevert("AbstractMessageIdAuthHook: invalid ISM"); hook = new ERC5164Hook( address(originMailbox), - TEST2_DOMAIN, + DESTINATION_DOMAIN, address(0).addressToBytes32(), address(dispatcher) ); @@ -108,125 +92,83 @@ contract ERC5164IsmTest is Test { vm.expectRevert("ERC5164Hook: invalid dispatcher"); hook = new ERC5164Hook( address(originMailbox), - TEST2_DOMAIN, + DESTINATION_DOMAIN, address(ism).addressToBytes32(), address(0) ); } - function test_postDispatch() public { - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); - originMailbox.updateLatestDispatchedId(messageId); + function testTypes() public view { + assertEq(hook.hookType(), uint8(IPostDispatchHook.Types.ID_AUTH_ISM)); + assertEq(ism.moduleType(), uint8(IInterchainSecurityModule.Types.NULL)); + } - // note: not checking for messageId since this is implementation dependent on each vendor + function _expectOriginExternalBridgeCall( + bytes memory _encodedHookData + ) internal override { vm.expectEmit(false, true, true, true, address(dispatcher)); emit MessageDispatched( messageId, address(hook), - TEST2_DOMAIN, + DESTINATION_DOMAIN, address(ism), - encodedHookData + _encodedHookData ); - - hook.postDispatch(bytes(""), encodedMessage); - } - - function testTypes() public { - assertEq(hook.hookType(), uint8(IPostDispatchHook.Types.ID_AUTH_ISM)); - assertEq(ism.moduleType(), uint8(IInterchainSecurityModule.Types.NULL)); } - function test_postDispatch_RevertWhen_ChainIDNotSupported() public { - encodedMessage = MessageUtils.formatMessage( - VERSION, - 0, - TEST1_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - 3, // unsupported chain id - TypeCasts.addressToBytes32(address(testRecipient)), - testMessage - ); - originMailbox.updateLatestDispatchedId(Message.id(encodedMessage)); - - vm.expectRevert( - "AbstractMessageIdAuthHook: invalid destination domain" - ); - hook.postDispatch(bytes(""), encodedMessage); + function test_verify_revertWhen_invalidMetadata() public override { + assertFalse(ism.verify(new bytes(0), encodedMessage)); } - function test_postDispatch_RevertWhen_msgValueNotAllowed() public payable { + function test_postDispatch_revertWhen_msgValueNotAllowed() public payable { originMailbox.updateLatestDispatchedId(messageId); vm.expectRevert("ERC5164Hook: no value allowed"); hook.postDispatch{value: 1}(bytes(""), encodedMessage); } - /* ============ ISM.verifyMessageId ============ */ - - function test_verifyMessageId() public { - vm.startPrank(address(executor)); - - ism.verifyMessageId(messageId); - assertTrue(ism.verifiedMessages(messageId).isBitSet(255)); - - vm.stopPrank(); - } - - function test_verifyMessageId_RevertWhen_NotAuthorized() public { - vm.startPrank(alice); + // override to omit direct external bridge call + function test_verify_revertsWhen_notAuthorizedHook() public override { + vm.prank(alice); - // needs to be called by the authorized hook contract on Ethereum vm.expectRevert( "AbstractMessageIdAuthorizedIsm: sender is not the hook" ); ism.verifyMessageId(messageId); - - vm.stopPrank(); + assertFalse(ism.isVerified(encodedMessage)); } - /* ============ ISM.verify ============ */ + // SKIP - duplicate of test_verify_revertWhen_invalidMetadata + function test_verify_revertsWhen_incorrectMessageId() public override {} - function test_verify() public { - vm.startPrank(address(executor)); + function test_verify_revertsWhen_invalidIsm() public override {} - ism.verifyMessageId(messageId); + // SKIP - 5164 ism does not support msg.value + function test_verify_msgValue_asyncCall() public override {} - bool verified = ism.verify(new bytes(0), encodedMessage); - assertTrue(verified); + function test_verify_msgValue_externalBridgeCall() public override {} - vm.stopPrank(); - } + function test_verify_valueAlreadyClaimed(uint256) public override {} - function test_verify_RevertWhen_InvalidMessage() public { - vm.startPrank(address(executor)); + /* ============ helper functions ============ */ + function _externalBridgeDestinationCall( + bytes memory _encodedHookData, + uint256 _msgValue + ) internal override { + vm.prank(address(executor)); ism.verifyMessageId(messageId); - - bytes memory invalidMessage = _encodeTestMessage(0, address(this)); - bool verified = ism.verify(new bytes(0), invalidMessage); - assertFalse(verified); - - vm.stopPrank(); } - /* ============ helper functions ============ */ - - function _encodeTestMessage( - uint32 _msgCount, - address _receipient - ) internal view returns (bytes memory) { - return - MessageUtils.formatMessage( - VERSION, - _msgCount, - TEST1_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - TEST2_DOMAIN, - TypeCasts.addressToBytes32(_receipient), - testMessage - ); + function _encodeExternalDestinationBridgeCall( + address _from, + address _to, + uint256 _msgValue, + bytes32 _messageId + ) internal override returns (bytes memory) { + if (_from == address(hook)) { + vm.prank(address(executor)); + ism.verifyMessageId{value: _msgValue}(messageId); + } } } diff --git a/solidity/test/isms/ExternalBridgeTest.sol b/solidity/test/isms/ExternalBridgeTest.sol new file mode 100644 index 000000000..8db043fcf --- /dev/null +++ b/solidity/test/isms/ExternalBridgeTest.sol @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: MIT or Apache-2.0 +pragma solidity ^0.8.13; + +import {Test} from "forge-std/Test.sol"; +import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; +import {StandardHookMetadata} from "../../contracts/hooks/libs/StandardHookMetadata.sol"; +import {TestMailbox} from "../../contracts/test/TestMailbox.sol"; +import {Message} from "../../contracts/libs/Message.sol"; +import {MessageUtils} from "./IsmTestUtils.sol"; +import {TestRecipient} from "../../contracts/test/TestRecipient.sol"; +import {AbstractMessageIdAuthorizedIsm} from "../../contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol"; +import {AbstractMessageIdAuthHook} from "../../contracts/hooks/libs/AbstractMessageIdAuthHook.sol"; + +abstract contract ExternalBridgeTest is Test { + using TypeCasts for address; + using MessageUtils for bytes; + + uint8 internal constant HYPERLANE_VERSION = 1; + uint32 internal constant ORIGIN_DOMAIN = 1; + uint32 internal constant DESTINATION_DOMAIN = 2; + uint256 internal constant MAX_MSG_VALUE = 2 ** 255 - 1; + uint256 internal GAS_QUOTE; + + TestMailbox internal originMailbox; + TestRecipient internal testRecipient; + + AbstractMessageIdAuthHook internal hook; + AbstractMessageIdAuthorizedIsm internal ism; + + bytes internal testMessage = + abi.encodePacked("Hello from the other chain!"); + bytes internal testMetadata = + StandardHookMetadata.overrideRefundAddress(address(this)); + bytes internal encodedMessage; + bytes32 internal messageId; + + function setUp() public virtual { + testRecipient = new TestRecipient(); + encodedMessage = _encodeTestMessage(); + messageId = Message.id(encodedMessage); + } + + /* ============ hook.quoteDispatch ============ */ + + function test_quoteDispatch() public view { + assertEq(hook.quoteDispatch(testMetadata, encodedMessage), GAS_QUOTE); + } + + /* ============ Hook.postDispatch ============ */ + + function test_postDispatch() public { + bytes memory encodedHookData = _encodeHookData(messageId); + originMailbox.updateLatestDispatchedId(messageId); + _expectOriginExternalBridgeCall(encodedHookData); + + hook.postDispatch{value: GAS_QUOTE}(testMetadata, encodedMessage); + } + + function test_postDispatch_revertWhen_chainIDNotSupported() public { + bytes memory message = originMailbox.buildOutboundMessage( + 3, + TypeCasts.addressToBytes32(address(this)), + testMessage + ); + + originMailbox.updateLatestDispatchedId(Message.id(message)); + vm.expectRevert( + "AbstractMessageIdAuthHook: invalid destination domain" + ); + hook.postDispatch(testMetadata, message); + } + + function test_postDispatch_revertWhen_notLastDispatchedMessage() public { + vm.expectRevert( + "AbstractMessageIdAuthHook: message not latest dispatched" + ); + hook.postDispatch(testMetadata, encodedMessage); + } + + function test_postDispatch_revertWhen_tooMuchValue() public { + vm.deal(address(this), uint256(MAX_MSG_VALUE + 1)); + bytes memory excessValueMetadata = StandardHookMetadata + .overrideMsgValue(uint256(2 ** 255 + 1)); + + originMailbox.updateLatestDispatchedId(messageId); + vm.expectRevert( + "AbstractMessageIdAuthHook: msgValue must be less than 2 ** 255" + ); + hook.postDispatch(excessValueMetadata, encodedMessage); + } + + /* ============ ISM.verifyMessageId ============ */ + + function test_verifyMessageId_asyncCall() public { + bytes memory encodedHookData = abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + (messageId) + ); + _externalBridgeDestinationCall(encodedHookData, 0); + + assertTrue(ism.isVerified(encodedMessage)); + } + + function test_verifyMessageId_externalBridgeCall() public virtual { + bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( + address(hook), + address(ism), + 0, + messageId + ); + + assertTrue(ism.verify(externalCalldata, encodedMessage)); + assertTrue(ism.isVerified(encodedMessage)); + } + + /* ============ ISM.verify ============ */ + + function test_verify_revertWhen_invalidMetadata() public virtual { + vm.expectRevert(); + assertFalse(ism.verify(new bytes(0), encodedMessage)); + } + + function test_verify_msgValue_asyncCall() public virtual { + bytes memory encodedHookData = _encodeHookData(messageId); + _externalBridgeDestinationCall(encodedHookData, 1 ether); + + assertTrue(ism.verify(new bytes(0), encodedMessage)); + assertEq(address(testRecipient).balance, 1 ether); + } + + function test_verify_msgValue_externalBridgeCall() public virtual { + bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( + address(hook), + address(ism), + 1 ether, + messageId + ); + ism.verify(externalCalldata, encodedMessage); + assertEq(address(testRecipient).balance, 1 ether); + } + + function test_verify_revertsWhen_invalidIsm() public virtual { + bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( + address(hook), + address(this), + 0, + messageId + ); + + vm.expectRevert(); + assertFalse(ism.verify(externalCalldata, encodedMessage)); + } + + function test_verify_revertsWhen_notAuthorizedHook() public virtual { + bytes memory unauthorizedHookErrorMsg = _setExternalOriginSender( + address(this) + ); + + bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( + address(this), + address(ism), + 0, + messageId + ); + + // external call + vm.expectRevert(unauthorizedHookErrorMsg); + assertFalse(ism.verify(externalCalldata, encodedMessage)); + + // async call vm.expectRevert(NotCrossChainCall.selector); + vm.expectRevert(); + _externalBridgeDestinationCall(externalCalldata, 0); + assertFalse(ism.isVerified(encodedMessage)); + } + + function test_verify_revertsWhen_incorrectMessageId() public virtual { + bytes32 incorrectMessageId = keccak256("incorrect message id"); + bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( + address(hook), + address(ism), + 0, + incorrectMessageId + ); + + // external call + vm.expectRevert(); + assertFalse(ism.verify(externalCalldata, encodedMessage)); + + // async call - native bridges might have try catch block to prevent revert + try + this.externalBridgeDestinationCallWrapper( + _encodeHookData(incorrectMessageId), + 0 + ) + {} catch {} + assertFalse(ism.isVerified(testMessage)); + } + + /// forge-config: default.fuzz.runs = 10 + function test_verify_valueAlreadyClaimed(uint256 _msgValue) public virtual { + _msgValue = bound(_msgValue, 0, MAX_MSG_VALUE); + _externalBridgeDestinationCall(_encodeHookData(messageId), _msgValue); + + bool verified = ism.verify(new bytes(0), encodedMessage); + assertTrue(verified); + assertEq(address(ism).balance, 0); + assertEq(address(testRecipient).balance, _msgValue); + + // send more value to the ISM + vm.deal(address(ism), _msgValue); + + // verified still true + verified = ism.verify(new bytes(0), encodedMessage); + assertTrue(verified); + // value which was already sent + assertEq(address(ism).balance, _msgValue); + assertEq(address(testRecipient).balance, _msgValue); + } + + /* ============ helper functions ============ */ + + function _encodeTestMessage() internal view returns (bytes memory) { + return + originMailbox.buildOutboundMessage( + DESTINATION_DOMAIN, + TypeCasts.addressToBytes32(address(testRecipient)), + testMessage + ); + } + + function _encodeHookData( + bytes32 _messageId + ) internal pure returns (bytes memory) { + return + abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + (_messageId) + ); + } + + // wrapper function needed for _externalBridgeDestinationCall because try catch cannot call an internal function + function externalBridgeDestinationCallWrapper( + bytes memory _encodedHookData, + uint256 _msgValue + ) external { + _externalBridgeDestinationCall(_encodedHookData, _msgValue); + } + + function _expectOriginExternalBridgeCall( + bytes memory _encodedHookData + ) internal virtual; + + function _externalBridgeDestinationCall( + bytes memory _encodedHookData, + uint256 _msgValue + ) internal virtual; + + function _encodeExternalDestinationBridgeCall( + address _from, + address _to, + uint256 _msgValue, + bytes32 _messageId + ) internal virtual returns (bytes memory); + + function _setExternalOriginSender( + address _sender + ) internal virtual returns (bytes memory) {} +} diff --git a/solidity/test/isms/OPL2ToL1Ism.t.sol b/solidity/test/isms/OPL2ToL1Ism.t.sol index 9466a7c93..d829e0211 100644 --- a/solidity/test/isms/OPL2ToL1Ism.t.sol +++ b/solidity/test/isms/OPL2ToL1Ism.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT or Apache-2.0 pragma solidity ^0.8.13; -import {Test} from "forge-std/Test.sol"; - import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; import {Message} from "../../contracts/libs/Message.sol"; import {MessageUtils} from "./IsmTestUtils.sol"; @@ -15,57 +13,41 @@ import {TestRecipient} from "../../contracts/test/TestRecipient.sol"; import {MockOptimismMessenger, MockOptimismPortal} from "../../contracts/mock/MockOptimism.sol"; import {OPL2ToL1Hook} from "../../contracts/hooks/OPL2ToL1Hook.sol"; import {OPL2ToL1Ism} from "../../contracts/isms/hook/OPL2ToL1Ism.sol"; +import {ExternalBridgeTest} from "./ExternalBridgeTest.sol"; -contract OPL2ToL1IsmTest is Test { - uint8 internal constant HYPERLANE_VERSION = 1; - uint32 internal constant MAINNET_DOMAIN = 1; - uint32 internal constant OPTIMISM_DOMAIN = 10; - uint32 internal constant GAS_QUOTE = 120_000; - +contract OPL2ToL1IsmTest is ExternalBridgeTest { address internal constant L2_MESSENGER_ADDRESS = 0x4200000000000000000000000000000000000007; uint256 internal constant MOCK_NONCE = 0; - TestMailbox public l2Mailbox; - TestRecipient internal testRecipient; - bytes internal testMessage = - abi.encodePacked("Hello from the other chain!"); - bytes internal encodedMessage; - bytes internal testMetadata = - StandardHookMetadata.overrideRefundAddress(address(this)); - bytes32 internal messageId; - MockOptimismPortal internal portal; MockOptimismMessenger internal l1Messenger; - OPL2ToL1Hook public hook; - OPL2ToL1Ism public ism; /////////////////////////////////////////////////////////////////// /// SETUP /// /////////////////////////////////////////////////////////////////// - function setUp() public { + function setUp() public override { // Optimism messenger mock setup + GAS_QUOTE = 120_000; vm.etch( L2_MESSENGER_ADDRESS, address(new MockOptimismMessenger()).code ); - testRecipient = new TestRecipient(); - - encodedMessage = _encodeTestMessage(); - messageId = Message.id(encodedMessage); + deployAll(); + super.setUp(); } function deployHook() public { - l2Mailbox = new TestMailbox(OPTIMISM_DOMAIN); + originMailbox = new TestMailbox(ORIGIN_DOMAIN); hook = new OPL2ToL1Hook( - address(l2Mailbox), - MAINNET_DOMAIN, + address(originMailbox), + DESTINATION_DOMAIN, TypeCasts.addressToBytes32(address(ism)), L2_MESSENGER_ADDRESS, - GAS_QUOTE + uint32(GAS_QUOTE) ); } @@ -85,197 +67,58 @@ contract OPL2ToL1IsmTest is Test { ism.setAuthorizedHook(TypeCasts.addressToBytes32(address(hook))); } - function test_postDispatch() public { - deployAll(); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); - - l2Mailbox.updateLatestDispatchedId(messageId); + /* ============ helper functions ============ */ + function _expectOriginExternalBridgeCall( + bytes memory _encodedHookData + ) internal override { vm.expectCall( L2_MESSENGER_ADDRESS, abi.encodeCall( ICrossDomainMessenger.sendMessage, - (address(ism), encodedHookData, GAS_QUOTE) + (address(ism), _encodedHookData, uint32(GAS_QUOTE)) ) ); - - hook.postDispatch{value: GAS_QUOTE}(testMetadata, encodedMessage); - } - - function testFork_postDispatch_revertWhen_chainIDNotSupported() public { - deployAll(); - - bytes memory message = MessageUtils.formatMessage( - 0, - uint32(0), - OPTIMISM_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - 2, // wrong domain - TypeCasts.addressToBytes32(address(testRecipient)), - testMessage - ); - - l2Mailbox.updateLatestDispatchedId(Message.id(message)); - vm.expectRevert( - "AbstractMessageIdAuthHook: invalid destination domain" - ); - hook.postDispatch(testMetadata, message); - } - - function test_postDispatch_revertWhen_notLastDispatchedMessage() public { - deployAll(); - - vm.expectRevert( - "AbstractMessageIdAuthHook: message not latest dispatched" - ); - hook.postDispatch(testMetadata, encodedMessage); - } - - function test_verify_directWithdrawalCall() public { - deployAll(); - - bytes memory encodedWithdrawalTx = _encodeFinalizeWithdrawalTx( - address(ism), - 0, - messageId - ); - - assertTrue(ism.verify(encodedWithdrawalTx, encodedMessage)); - } - - function test_verify_directWithdrawalCall_revertsWhen_invalidSender() - public - { - deployAll(); - l1Messenger.setXDomainMessageSender(address(this)); - - bytes memory encodedWithdrawalTx = _encodeFinalizeWithdrawalTx( - address(ism), - 0, - messageId - ); - - vm.expectRevert(); // evmRevert in MockOptimismPortal - ism.verify(encodedWithdrawalTx, encodedMessage); - } - - function test_verify_statefulVerify() public { - deployAll(); - - vm.deal(address(portal), 1 ether); - IOptimismPortal.WithdrawalTransaction - memory withdrawal = IOptimismPortal.WithdrawalTransaction({ - nonce: MOCK_NONCE, - sender: L2_MESSENGER_ADDRESS, - target: address(l1Messenger), - value: 1 ether, - gasLimit: uint256(GAS_QUOTE), - data: _encodeMessengerCalldata(address(ism), 1 ether, messageId) - }); - portal.finalizeWithdrawalTransaction(withdrawal); - - vm.etch(address(portal), new bytes(0)); // this is a way to test that the portal isn't called again - assertTrue(ism.verify(new bytes(0), encodedMessage)); - assertEq(address(testRecipient).balance, 1 ether); // testing msg.value - } - - function test_verify_statefulAndDirectWithdrawal() public { - deployAll(); - - IOptimismPortal.WithdrawalTransaction - memory withdrawal = IOptimismPortal.WithdrawalTransaction({ - nonce: MOCK_NONCE, - sender: L2_MESSENGER_ADDRESS, - target: address(l1Messenger), - value: 0, - gasLimit: uint256(GAS_QUOTE), - data: _encodeMessengerCalldata(address(ism), 0, messageId) - }); - portal.finalizeWithdrawalTransaction(withdrawal); - - bytes memory encodedWithdrawalTx = _encodeFinalizeWithdrawalTx( - address(ism), - 0, - messageId - ); - - vm.etch(address(portal), new bytes(0)); // this is a way to test that the portal isn't called again - assertTrue(ism.verify(encodedWithdrawalTx, encodedMessage)); } - function test_verify_revertsWhen_noStatefulAndDirectWithdrawal() public { - deployAll(); - - vm.expectRevert(); - ism.verify(new bytes(0), encodedMessage); + function _encodeExternalDestinationBridgeCall( + address, + /*_from*/ + address _to, + uint256 _msgValue, + bytes32 _messageId + ) internal override returns (bytes memory) { + vm.deal(address(portal), _msgValue); + return _encodeFinalizeWithdrawalTx(_to, _msgValue, _messageId); } - function test_verify_revertsWhen_invalidIsm() public { - deployAll(); - - bytes memory encodedWithdrawalTx = _encodeFinalizeWithdrawalTx( - address(this), - 0, - messageId - ); - - vm.expectRevert(); // evmRevert in MockOptimismPortal - ism.verify(encodedWithdrawalTx, encodedMessage); + function _setExternalOriginSender( + address _sender + ) internal override returns (bytes memory) { + l1Messenger.setXDomainMessageSender(_sender); + return "AbstractMessageIdAuthorizedIsm: sender is not the hook"; } - function test_verify_revertsWhen_incorrectMessageId() public { - deployAll(); - - bytes32 incorrectMessageId = keccak256("incorrect message id"); - - bytes memory encodedWithdrawalTx = _encodeFinalizeWithdrawalTx( - address(this), - 0, - incorrectMessageId - ); - - // through portal call - vm.expectRevert("OPL2ToL1Ism: invalid message id"); - ism.verify(encodedWithdrawalTx, encodedMessage); - - // through statefulVerify + function _externalBridgeDestinationCall( + bytes memory, + /*_encodedHookData*/ + uint256 _msgValue + ) internal override { + vm.deal(address(portal), _msgValue); IOptimismPortal.WithdrawalTransaction memory withdrawal = IOptimismPortal.WithdrawalTransaction({ nonce: MOCK_NONCE, sender: L2_MESSENGER_ADDRESS, target: address(l1Messenger), - value: 0, + value: _msgValue, gasLimit: uint256(GAS_QUOTE), data: _encodeMessengerCalldata( address(ism), - 0, - incorrectMessageId + _msgValue, + messageId ) }); portal.finalizeWithdrawalTransaction(withdrawal); - - vm.etch(address(portal), new bytes(0)); // to stop the portal route - vm.expectRevert(); // evmRevert() - assertFalse(ism.verify(new bytes(0), encodedMessage)); - } - - /* ============ helper functions ============ */ - - function _encodeTestMessage() internal view returns (bytes memory) { - return - MessageUtils.formatMessage( - HYPERLANE_VERSION, - uint32(0), - OPTIMISM_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - MAINNET_DOMAIN, - TypeCasts.addressToBytes32(address(testRecipient)), - testMessage - ); } function _encodeMessengerCalldata( @@ -283,10 +126,7 @@ contract OPL2ToL1IsmTest is Test { uint256 _value, bytes32 _messageId ) internal view returns (bytes memory) { - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (_messageId) - ); + bytes memory encodedHookData = _encodeHookData(_messageId); return abi.encodeCall( diff --git a/solidity/test/isms/OPStackIsm.t.sol b/solidity/test/isms/OPStackIsm.t.sol index 9862717ad..45c818ec3 100644 --- a/solidity/test/isms/OPStackIsm.t.sol +++ b/solidity/test/isms/OPStackIsm.t.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: MIT or Apache-2.0 pragma solidity ^0.8.13; -import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; import {LibBit} from "../../contracts/libs/LibBit.sol"; import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; import {StandardHookMetadata} from "../../contracts/hooks/libs/StandardHookMetadata.sol"; import {StandardHookMetadata} from "../../contracts/hooks/libs/StandardHookMetadata.sol"; import {AbstractMessageIdAuthorizedIsm} from "../../contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol"; +import {MockOptimismMessenger} from "../../contracts/mock/MockOptimism.sol"; import {TestMailbox} from "../../contracts/test/TestMailbox.sol"; import {Message} from "../../contracts/libs/Message.sol"; import {MessageUtils} from "./IsmTestUtils.sol"; @@ -18,16 +19,14 @@ import {TestRecipient} from "../../contracts/test/TestRecipient.sol"; import {NotCrossChainCall} from "@openzeppelin/contracts/crosschain/errors.sol"; import {AddressAliasHelper} from "@eth-optimism/contracts/standards/AddressAliasHelper.sol"; -import {ICrossDomainMessenger, IL2CrossDomainMessenger} from "../../contracts/interfaces/optimism/ICrossDomainMessenger.sol"; +import {ICrossDomainMessenger} from "../../contracts/interfaces/optimism/ICrossDomainMessenger.sol"; +import {ExternalBridgeTest} from "./ExternalBridgeTest.sol"; -contract OPStackIsmTest is Test { +contract OPStackIsmTest is ExternalBridgeTest { using LibBit for uint256; using TypeCasts for address; using MessageUtils for bytes; - uint256 internal mainnetFork; - uint256 internal optimismFork; - address internal constant L1_MESSENGER_ADDRESS = 0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1; address internal constant L1_CANNONICAL_CHAIN = @@ -36,36 +35,12 @@ contract OPStackIsmTest is Test { 0x4200000000000000000000000000000000000007; uint8 internal constant OPTIMISM_VERSION = 0; - uint8 internal constant HYPERLANE_VERSION = 1; uint256 internal constant DEFAULT_GAS_LIMIT = 1_920_000; address internal alice = address(0x1); - ICrossDomainMessenger internal l1Messenger; - IL2CrossDomainMessenger internal l2Messenger; - TestMailbox internal l1Mailbox; - OPStackIsm internal opISM; - OPStackHook internal opHook; - - TestRecipient internal testRecipient; - bytes internal testMessage = - abi.encodePacked("Hello from the other chain!"); - bytes internal testMetadata = - StandardHookMetadata.overrideRefundAddress(address(this)); - - bytes internal encodedMessage; - bytes32 internal messageId; - - uint32 internal constant MAINNET_DOMAIN = 1; - uint32 internal constant OPTIMISM_DOMAIN = 10; - - event SentMessage( - address indexed target, - address sender, - bytes message, - uint256 messageNonce, - uint256 gasLimit - ); + MockOptimismMessenger internal l1Messenger; + MockOptimismMessenger internal l2Messenger; event RelayedMessage(bytes32 indexed msgHash); @@ -73,469 +48,145 @@ contract OPStackIsmTest is Test { event ReceivedMessage(bytes32 indexed messageId); - function setUp() public { - // block numbers to fork from, chain data is cached to ../../forge-cache/ - mainnetFork = vm.createFork(vm.rpcUrl("mainnet"), 18_992_500); - optimismFork = vm.createFork(vm.rpcUrl("optimism"), 114_696_811); + function setUp() public override { + GAS_QUOTE = 0; - testRecipient = new TestRecipient(); + vm.etch( + L1_MESSENGER_ADDRESS, + address(new MockOptimismMessenger()).code + ); + vm.etch( + L2_MESSENGER_ADDRESS, + address(new MockOptimismMessenger()).code + ); + l1Messenger = MockOptimismMessenger(L1_MESSENGER_ADDRESS); + l2Messenger = MockOptimismMessenger(L2_MESSENGER_ADDRESS); - encodedMessage = _encodeTestMessage(); - messageId = Message.id(encodedMessage); + deployAll(); + super.setUp(); } /////////////////////////////////////////////////////////////////// /// SETUP /// /////////////////////////////////////////////////////////////////// - function deployOptimismHook() public { - vm.selectFork(mainnetFork); - - l1Messenger = ICrossDomainMessenger(L1_MESSENGER_ADDRESS); - l1Mailbox = new TestMailbox(MAINNET_DOMAIN); - - opHook = new OPStackHook( - address(l1Mailbox), - OPTIMISM_DOMAIN, - TypeCasts.addressToBytes32(address(opISM)), + function deployHook() public { + originMailbox = new TestMailbox(ORIGIN_DOMAIN); + hook = new OPStackHook( + address(originMailbox), + DESTINATION_DOMAIN, + TypeCasts.addressToBytes32(address(ism)), L1_MESSENGER_ADDRESS ); - - vm.makePersistent(address(opHook)); } - function deployOPStackIsm() public { - vm.selectFork(optimismFork); - - l2Messenger = IL2CrossDomainMessenger(L2_MESSENGER_ADDRESS); - opISM = new OPStackIsm(L2_MESSENGER_ADDRESS); - - vm.makePersistent(address(opISM)); + function deployIsm() public { + ism = new OPStackIsm(L2_MESSENGER_ADDRESS); } function deployAll() public { - deployOPStackIsm(); - deployOptimismHook(); + deployIsm(); + deployHook(); - vm.selectFork(optimismFork); - - opISM.setAuthorizedHook(TypeCasts.addressToBytes32(address(opHook))); - // for sending value - vm.deal( - AddressAliasHelper.applyL1ToL2Alias(L1_MESSENGER_ADDRESS), - 2 ** 255 - ); + ism.setAuthorizedHook(TypeCasts.addressToBytes32(address(hook))); + l2Messenger.setXDomainMessageSender(address(hook)); } - /////////////////////////////////////////////////////////////////// - /// FORK TESTS /// - /////////////////////////////////////////////////////////////////// - - /* ============ hook.quoteDispatch ============ */ - - function testFork_quoteDispatch() public { - deployAll(); - - vm.selectFork(mainnetFork); - - assertEq(opHook.quoteDispatch(testMetadata, encodedMessage), 0); + function test_verify_revertWhen_invalidMetadata() public override { + assertFalse(ism.verify(new bytes(0), encodedMessage)); } - /* ============ hook.postDispatch ============ */ + function test_verify_revertsWhen_incorrectMessageId() public override { + bytes32 incorrectMessageId = keccak256("incorrect message id"); - function testFork_postDispatch() public { - deployAll(); - - vm.selectFork(mainnetFork); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); - - uint40 testNonce = 123; - l1Mailbox.updateLatestDispatchedId(messageId); - - vm.expectEmit(true, true, true, false, L1_MESSENGER_ADDRESS); - emit SentMessage( - address(opISM), - address(opHook), - encodedHookData, - testNonce, - DEFAULT_GAS_LIMIT - ); - opHook.postDispatch(testMetadata, encodedMessage); + _externalBridgeDestinationCall(_encodeHookData(incorrectMessageId), 0); + assertFalse(ism.isVerified(testMessage)); } - function testFork_postDispatch_RevertWhen_ChainIDNotSupported() public { - deployAll(); - - vm.selectFork(mainnetFork); - - bytes memory message = MessageUtils.formatMessage( - OPTIMISM_VERSION, - uint32(0), - MAINNET_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - 11, // wrong domain - TypeCasts.addressToBytes32(address(testRecipient)), - testMessage - ); + /* ============ helper functions ============ */ - l1Mailbox.updateLatestDispatchedId(Message.id(message)); - vm.expectRevert( - "AbstractMessageIdAuthHook: invalid destination domain" + function _expectOriginExternalBridgeCall( + bytes memory _encodedHookData + ) internal override { + vm.expectCall( + L1_MESSENGER_ADDRESS, + abi.encodeCall( + ICrossDomainMessenger.sendMessage, + (address(ism), _encodedHookData, uint32(DEFAULT_GAS_LIMIT)) + ) ); - opHook.postDispatch(testMetadata, message); } - function testFork_postDispatch_RevertWhen_TooMuchValue() public { - deployAll(); - - vm.selectFork(mainnetFork); - - vm.deal(address(this), uint256(2 ** 255 + 1)); - bytes memory excessValueMetadata = StandardHookMetadata - .overrideMsgValue(uint256(2 ** 255 + 1)); - - l1Mailbox.updateLatestDispatchedId(messageId); - vm.expectRevert( - "AbstractMessageIdAuthHook: msgValue must be less than 2 ** 255" + function _externalBridgeDestinationCall( + bytes memory _encodedHookData, + uint256 _msgValue + ) internal override { + vm.deal(L2_MESSENGER_ADDRESS, _msgValue); + l2Messenger.relayMessage( + 0, + address(hook), + address(ism), + _msgValue, + uint32(GAS_QUOTE), + _encodedHookData ); - opHook.postDispatch(excessValueMetadata, encodedMessage); } - function testFork_postDispatch_RevertWhen_NotLastDispatchedMessage() - public - { - deployAll(); - - vm.selectFork(mainnetFork); - - vm.expectRevert( - "AbstractMessageIdAuthHook: message not latest dispatched" - ); - opHook.postDispatch(testMetadata, encodedMessage); + function _encodeExternalDestinationBridgeCall( + address _from, + address _to, + uint256 _msgValue, + bytes32 _messageId + ) internal pure override returns (bytes memory) { + return new bytes(0); } - /* ============ ISM.verifyMessageId ============ */ - - function testFork_verifyMessageId() public { - deployAll(); - - vm.selectFork(optimismFork); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); - - (uint240 nonce, uint16 version) = decodeVersionedNonce( - l2Messenger.messageNonce() - ); - uint256 versionedNonce = encodeVersionedNonce(nonce + 1, version); + // SKIP - no external bridge call + function test_verifyMessageId_externalBridgeCall() public override {} - bytes32 versionedHash = hashCrossDomainMessageV1( - versionedNonce, - address(opHook), - address(opISM), - 0, - DEFAULT_GAS_LIMIT, - encodedHookData - ); - - vm.startPrank( - AddressAliasHelper.applyL1ToL2Alias(L1_MESSENGER_ADDRESS) - ); + function test_verify_msgValue_externalBridgeCall() public override {} - vm.expectEmit(true, false, false, false, address(opISM)); - emit ReceivedMessage(messageId); + function test_verify_revertsWhen_invalidIsm() public override {} - vm.expectEmit(true, false, false, false, L2_MESSENGER_ADDRESS); - emit RelayedMessage(versionedHash); - - l2Messenger.relayMessage( - versionedNonce, - address(opHook), - address(opISM), - 0, - DEFAULT_GAS_LIMIT, - encodedHookData - ); - - assertTrue(opISM.verifiedMessages(messageId).isBitSet(255)); - vm.stopPrank(); - } - - function testFork_verifyMessageId_RevertWhen_NotAuthorized() public { - deployAll(); - - vm.selectFork(optimismFork); + /* ============ ISM.verifyMessageId ============ */ + function test_verify_revertsWhen_notAuthorizedHook() public override { // needs to be called by the canonical messenger on Optimism vm.expectRevert(NotCrossChainCall.selector); - opISM.verifyMessageId(messageId); - - // set the xDomainMessageSender storage slot as alice - bytes32 key = bytes32(uint256(204)); - bytes32 value = TypeCasts.addressToBytes32(alice); - vm.store(address(l2Messenger), key, value); + ism.verifyMessageId(messageId); vm.startPrank(L2_MESSENGER_ADDRESS); + _setExternalOriginSender(address(this)); // needs to be called by the authorized hook contract on Ethereum vm.expectRevert( "AbstractMessageIdAuthorizedIsm: sender is not the hook" ); - opISM.verifyMessageId(messageId); + ism.verifyMessageId(messageId); } - /* ============ ISM.verify ============ */ - - function testFork_verify() public { - deployAll(); - - vm.selectFork(optimismFork); - - orchestrateRelayMessage(0, messageId); - - bool verified = opISM.verify(new bytes(0), encodedMessage); - assertTrue(verified); + function _setExternalOriginSender( + address _sender + ) internal override returns (bytes memory) { + l2Messenger.setXDomainMessageSender(_sender); + return ""; } - /// forge-config: default.fuzz.runs = 10 - function testFork_verify_WithValue(uint256 _msgValue) public { - _msgValue = bound(_msgValue, 0, 2 ** 254); - deployAll(); - - orchestrateRelayMessage(_msgValue, messageId); - - bool verified = opISM.verify(new bytes(0), encodedMessage); - assertTrue(verified); - - assertEq(address(opISM).balance, 0); - assertEq(address(testRecipient).balance, _msgValue); - } - - /// forge-config: default.fuzz.runs = 10 - function testFork_verify_valueAlreadyClaimed(uint256 _msgValue) public { - _msgValue = bound(_msgValue, 0, 2 ** 254); - deployAll(); - - orchestrateRelayMessage(_msgValue, messageId); - - bool verified = opISM.verify(new bytes(0), encodedMessage); - assertTrue(verified); - - assertEq(address(opISM).balance, 0); - assertEq(address(testRecipient).balance, _msgValue); - - // send more value to the ISM - vm.deal(address(opISM), _msgValue); - - verified = opISM.verify(new bytes(0), encodedMessage); - // verified still true - assertTrue(verified); - - assertEq(address(opISM).balance, _msgValue); - // value which was already sent - assertEq(address(testRecipient).balance, _msgValue); - } - - function testFork_verify_tooMuchValue() public { - deployAll(); + /* ============ ISM.verify ============ */ + function test_verify_tooMuchValue() public { uint256 _msgValue = 2 ** 255 + 1; - vm.expectEmit(false, false, false, false, address(l2Messenger)); - emit FailedRelayedMessage(messageId); - orchestrateRelayMessage(_msgValue, messageId); - - bool verified = opISM.verify(new bytes(0), encodedMessage); - assertFalse(verified); - - assertEq(address(opISM).balance, 0); - assertEq(address(testRecipient).balance, 0); - } - - // sending over invalid message - function testFork_verify_RevertWhen_HyperlaneInvalidMessage() public { - deployAll(); - - orchestrateRelayMessage(0, messageId); - - bytes memory invalidMessage = MessageUtils.formatMessage( - HYPERLANE_VERSION, - uint8(0), - MAINNET_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - OPTIMISM_DOMAIN, - TypeCasts.addressToBytes32(address(this)), // wrong recipient - testMessage + vm.expectRevert( + "AbstractMessageIdAuthorizedIsm: msg.value must be less than 2^255" ); - bool verified = opISM.verify(new bytes(0), invalidMessage); - assertFalse(verified); - } + _externalBridgeDestinationCall(_encodeHookData(messageId), _msgValue); - // invalid messageID in postDispatch - function testFork_verify_RevertWhen_InvalidOptimismMessageID() public { - deployAll(); - vm.selectFork(optimismFork); - - bytes memory invalidMessage = MessageUtils.formatMessage( - HYPERLANE_VERSION, - uint8(0), - MAINNET_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - OPTIMISM_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - testMessage - ); - bytes32 _messageId = Message.id(invalidMessage); - orchestrateRelayMessage(0, _messageId); + assertFalse(ism.isVerified(encodedMessage)); - bool verified = opISM.verify(new bytes(0), encodedMessage); - assertFalse(verified); + assertEq(address(ism).balance, 0); + assertEq(address(testRecipient).balance, 0); } /* ============ helper functions ============ */ - - function _encodeTestMessage() internal view returns (bytes memory) { - return - MessageUtils.formatMessage( - HYPERLANE_VERSION, - uint32(0), - MAINNET_DOMAIN, - TypeCasts.addressToBytes32(address(this)), - OPTIMISM_DOMAIN, - TypeCasts.addressToBytes32(address(testRecipient)), - testMessage - ); - } - - /// @dev from eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol - /// @notice Hashes a cross domain message based on the V1 (current) encoding. - /// @param _nonce Message nonce. - /// @param _sender Address of the sender of the message. - /// @param _target Address of the target of the message. - /// @param _value ETH value to send to the target. - /// @param _gasLimit Gas limit to use for the message. - /// @param _data Data to send with the message. - /// @return Hashed cross domain message. - function hashCrossDomainMessageV1( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes memory _data - ) internal pure returns (bytes32) { - return - keccak256( - encodeCrossDomainMessageV1( - _nonce, - _sender, - _target, - _value, - _gasLimit, - _data - ) - ); - } - - /// @dev from eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol - /// @notice Encodes a cross domain message based on the V1 (current) encoding. - /// @param _nonce Message nonce. - /// @param _sender Address of the sender of the message. - /// @param _target Address of the target of the message. - /// @param _value ETH value to send to the target. - /// @param _gasLimit Gas limit to use for the message. - /// @param _data Data to send with the message. - /// @return Encoded cross domain message. - function encodeCrossDomainMessageV1( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes memory _data - ) internal pure returns (bytes memory) { - return - abi.encodeWithSignature( - "relayMessage(uint256,address,address,uint256,uint256,bytes)", - _nonce, - _sender, - _target, - _value, - _gasLimit, - _data - ); - } - - /// @dev from eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol - /// @notice Adds a version number into the first two bytes of a message nonce. - /// @param _nonce Message nonce to encode into. - /// @param _version Version number to encode into the message nonce. - /// @return Message nonce with version encoded into the first two bytes. - function encodeVersionedNonce( - uint240 _nonce, - uint16 _version - ) internal pure returns (uint256) { - uint256 nonce; - assembly { - nonce := or(shl(240, _version), _nonce) - } - return nonce; - } - - /// @dev from eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol - /// @notice Pulls the version out of a version-encoded nonce. - /// @param _nonce Message nonce with version encoded into the first two bytes. - /// @return Nonce without encoded version. - /// @return Version of the message. - function decodeVersionedNonce( - uint256 _nonce - ) internal pure returns (uint240, uint16) { - uint240 nonce; - uint16 version; - assembly { - nonce := and( - _nonce, - 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - ) - version := shr(240, _nonce) - } - return (nonce, version); - } - - function orchestrateRelayMessage( - uint256 _msgValue, - bytes32 _messageId - ) internal { - vm.selectFork(optimismFork); - - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (_messageId) - ); - - (uint240 nonce, uint16 version) = decodeVersionedNonce( - l2Messenger.messageNonce() - ); - uint256 versionedNonce = encodeVersionedNonce(nonce + 1, version); - - vm.deal( - AddressAliasHelper.applyL1ToL2Alias(L1_MESSENGER_ADDRESS), - 2 ** 256 - 1 - ); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(L1_MESSENGER_ADDRESS)); - l2Messenger.relayMessage{value: _msgValue}( - versionedNonce, - address(opHook), - address(opISM), - _msgValue, - DEFAULT_GAS_LIMIT, - encodedHookData - ); - } } From a78c95cad8e8341f7d1a54e99b9b2305c63e2277 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Sat, 21 Sep 2024 19:38:57 +0100 Subject: [PATCH 061/224] chore: add SOL ATA payer on eclipsemainnet to funding monitoring (#4543) ### Description - Accidentally missed this in #4533 ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/infra/config/environments/mainnet3/funding.ts | 2 +- typescript/infra/scripts/funding/fund-keys-from-deployer.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index 2376ebb9f..19b385e96 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '877656c-20240919-202332', + tag: '11fbb13-20240921-100452', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron diff --git a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts index 081453c09..d262e52c8 100644 --- a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts +++ b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts @@ -133,6 +133,11 @@ const sealevelAccountsToTrack: ChainMap = { pubkey: new PublicKey('Hyy4jryRxgZm5pvuSx29fXxJ9J55SuDtXiCo89kmNuz5'), walletName: 'tETH/eclipsemainnet-ethereum/ata-payer', }, + { + // SOL warp route ATA payer + pubkey: new PublicKey('CijxTbPs9JZxTUfo8Hmz2imxzHtKnDFD3kZP3RPy34uJ'), + walletName: 'SOL/eclipsemainnet-solanamainnet/ata-payer', + }, ], }; From b9b3aaec10bf985873818f0d122407cecbbcd375 Mon Sep 17 00:00:00 2001 From: Nam Chu Hoai Date: Mon, 23 Sep 2024 21:12:02 +0800 Subject: [PATCH 062/224] chore: print validator when listing checkpoint indices (#4550) ### Description Minor addition to make it easy to figure out which validator is behind (from the multisig consts mapping) --- typescript/infra/scripts/list-validator-checkpoint-indices.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/typescript/infra/scripts/list-validator-checkpoint-indices.ts b/typescript/infra/scripts/list-validator-checkpoint-indices.ts index f3cfc6c1c..957719725 100644 --- a/typescript/infra/scripts/list-validator-checkpoint-indices.ts +++ b/typescript/infra/scripts/list-validator-checkpoint-indices.ts @@ -39,11 +39,12 @@ async function main() { chain, identifier, index, + validator, }; }, ); - console.table(indices, ['chain', 'index', 'identifier']); + console.table(indices, ['chain', 'index', 'identifier', 'validator']); } main().catch(console.error); From 25e5d1af81d182c645005bbad95daf217223db7c Mon Sep 17 00:00:00 2001 From: beckbecker <140314072+Oemerbeck@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:29:06 +0200 Subject: [PATCH 063/224] docs: fix broken links (#4546) ### Description While studying the documents, I found that some links are pointing to invalid addresses. They are updated now with the correct links. ### Testing No test is needed as only doc is modified --- solidity/contracts/token/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solidity/contracts/token/README.md b/solidity/contracts/token/README.md index 99edbd11d..1fbc80cf7 100644 --- a/solidity/contracts/token/README.md +++ b/solidity/contracts/token/README.md @@ -45,9 +45,9 @@ graph LR The Token Router contract comes in several flavors and a warp route can be composed of a combination of these flavors. -- [`Native`](./contracts/HypNative.sol) - for warping native assets (e.g. ETH) from the canonical chain -- [`Collateral`](./contracts/HypERC20Collateral.sol) - for warping tokens, ERC20 or ERC721, from the canonical chain -- [`Synthetic`](./contracts/HypERC20.sol) - for representing tokens, Native/ERC20 or ERC721, on a non-canonical chain +- [`Native`](./HypNative.sol) - for warping native assets (e.g. ETH) from the canonical chain +- [`Collateral`](./HypERC20Collateral.sol) - for warping tokens, ERC20 or ERC721, from the canonical chain +- [`Synthetic`](./HypERC20.sol) - for representing tokens, Native/ERC20 or ERC721, on a non-canonical chain ## Interchain Security Models From 82a90c120c413cc8108ce7aa6e8015cd30158780 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Mon, 23 Sep 2024 15:33:55 +0100 Subject: [PATCH 064/224] chore: update USDC Ethereum router address in token-config (#4542) ### Description - Updates the foreignDeployment to be the new one. Just the program-ids.json was updated - A drive-by with some logging that helps me plug a tx into a script to submit ledger txs (this should eventually be built directly into the sealevel client, at which point we can remove this though) ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/sealevel/client/src/context.rs | 17 +++++++++++++++-- .../warp-routes/eclipseusdc/token-config.json | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/rust/sealevel/client/src/context.rs b/rust/sealevel/client/src/context.rs index e704510a7..c3912ee4b 100644 --- a/rust/sealevel/client/src/context.rs +++ b/rust/sealevel/client/src/context.rs @@ -155,8 +155,21 @@ impl<'ctx, 'rpc> TxnBuilder<'ctx, 'rpc> { ); } - let message = Message::new(&self.instructions(), None); - let txn = Transaction::new_unsigned(message); + let message = Message::new(&self.instructions(), Some(&self.ctx.payer_pubkey)); + // Useful for plugging into ledger-friendly tools + if std::env::var("TX_BINARY").is_ok() { + println!( + "\t==== Message as binary: ====\n\t{:?}", + bincode::serialize(&message) + .unwrap() + .iter() + .map(|n| n.to_string()) + .collect::>() + .join(" ") + ); + } + + let txn = Transaction::new_unsigned(message.clone()); println!( "\t==== Transaction in base58: ====\n\t{}", bs58::encode(bincode::serialize(&txn).unwrap()).into_string() diff --git a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json index d5eb85403..8c31fbd0a 100644 --- a/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json +++ b/rust/sealevel/environments/mainnet3/warp-routes/eclipseusdc/token-config.json @@ -18,6 +18,6 @@ "type": "collateral", "decimals": 6, "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - "foreignDeployment": "0xFc8F5272d690cf19732a7eD6f246aDF5fB8708dB" + "foreignDeployment": "0xe1de9910fe71cc216490ac7fcf019e13a34481d7" } } From 7835c2abaf00f0a40c247b59021b1b5b6c0ae28a Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:52:59 +0100 Subject: [PATCH 065/224] chore: root repo vscode settings for `rust-analyzer` (#4556) ### Description `rust-analyzer` only detects workspaces that are 1 directory deep in the source tree, otherwise it has to be configured with the path to workspaces. This PR checks in `.vscode` settings with paths to the rust workspaces. This also fixes the issue where someone checks out the monorepo to make TS changes but can't commit because our husky precommit setups assumes that rust workspaces have already been built (which `rust-analyzer` does implicitly). Noting that the problem is only there if the repo isn't opened using the `mono.code-workspace` setting, which people I talked to don't use (other than @paulbalaji) --- .vscode/settings.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..6cb83cc9f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "rust-analyzer.linkedProjects": [ + "./rust/main/Cargo.toml", + "./rust/sealevel/Cargo.toml", + ], +} \ No newline at end of file From eb47aaee8627deab2e200bb48ee7df47d2fd33f4 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 23 Sep 2024 14:33:55 -0400 Subject: [PATCH 066/224] fix: warp core sealevel native (#4522) ### Description - **Modify native adapter collateral balance check** ### Drive-by changes - None ### Related issues - Opens https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4558 ### Backward compatibility Yes ### Testing Manual in warp UI, released as a beta build 5.2.1-beta0 --- .changeset/curvy-baboons-deliver.md | 5 +++++ typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100644 .changeset/curvy-baboons-deliver.md diff --git a/.changeset/curvy-baboons-deliver.md b/.changeset/curvy-baboons-deliver.md new file mode 100644 index 000000000..931472bac --- /dev/null +++ b/.changeset/curvy-baboons-deliver.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Use collateral account for sealevel native warp route balance diff --git a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts index 9529eb4bc..29ea30b24 100644 --- a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts @@ -516,6 +516,12 @@ export class SealevelHypNativeAdapter extends SealevelHypTokenAdapter { } override async getBalance(owner: Address): Promise { + if (eqAddress(owner, this.addresses.warpRouter)) { + const collateralAccount = this.deriveNativeTokenCollateralAccount(); + const balance = await this.getProvider().getBalance(collateralAccount); + // TODO: account for rent in https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4558 + return BigInt(balance.toString()); + } return this.wrappedNative.getBalance(owner); } From 05211a2e61537a1b4c048c8a08d42978413307fb Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 23 Sep 2024 14:51:32 -0400 Subject: [PATCH 067/224] chore: update CODEOWNERS (#4555) ### Description Update CODEOWNERS --- .github/CODEOWNERS | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ab8ed10d1..314d1e01d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,29 +1,22 @@ # File extension owners -*.sol @yorhodes @tkporter @aroralanuk @nbayindirli -*.ts @yorhodes @jmrossy @nbayindirli -*.rs @tkporter @daniel-savu -*.md @Skunkchain @avious00 +*.sol @yorhodes @aroralanuk @ltyu +*.ts @yorhodes @jmrossy +*.rs @tkporter @daniel-savu @ameten # Package owners ## Contracts -solidity/ @yorhodes @tkporter @aroralanuk @nbayindirli +solidity/ @yorhodes @tkporter @aroralanuk @ltyu ## Agents rust/ @tkporter @daniel-savu ## SDK -typescript/sdk @yorhodes @jmrossy - -## Token -typescript/token @yorhodes @jmrossy @tkporter @aroralanuk @nbayindirli - -## Hello World -typescript/helloworld @yorhodes +typescript/sdk @yorhodes @jmrossy @ltyu @paulbalaji ## CLI -typescript/cli @jmrossy @yorhodes @aroralanuk @nbayindirli +typescript/cli @jmrossy @yorhodes @ltyu ## Infra -typescript/infra @tkporter +typescript/infra @tkporter @paulbalaji @Mo-Hussain From 4508b4fed189023cb84cf9e78476d80bec525bd4 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Mon, 23 Sep 2024 20:40:34 +0100 Subject: [PATCH 068/224] fix: don't reuse prefix key in relayer (#4560) ### Description This PR fixes a bug @tkporter flagged, which would cause agents to reindex every igp payment on restart (but luckily with no impact on message processing). Unfortunately the same DB prefix key was used to store different items: `gas_payment_by_sequence` and `gas_payment_block_by_sequence`, with the latter overwriting the former. Sequence indexing relies on `gas_payment_by_sequence` to know whether a certain payment was already indexed - if not, it queries an RPC for it and stores it in the db. But because `gas_payment_by_sequence` would get overwritten and thus corrupted, checking whether a certain `gas_payment_by_sequence` is already in the db would fail with a decoding error, and because errors are treated as if the payment just wasn't indexed yet, the RPC call would be made again. Fortunately no migration is required, since just re-running the relayer will cause it to overwrite the old corrupted entries with correct ones, and would also create new prefix entries for the igp blocks. --- rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs b/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs index 109f833b9..689878ca3 100644 --- a/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs +++ b/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs @@ -23,6 +23,7 @@ const MESSAGE_DISPATCHED_BLOCK_NUMBER: &str = "message_dispatched_block_number_" const MESSAGE: &str = "message_"; const NONCE_PROCESSED: &str = "nonce_processed_"; const GAS_PAYMENT_BY_SEQUENCE: &str = "gas_payment_by_sequence_"; +const GAS_PAYMENT_BLOCK_BY_SEQUENCE: &str = "gas_payment_block_by_sequence_"; const HIGHEST_SEEN_MESSAGE_NONCE: &str = "highest_seen_message_nonce_"; const GAS_PAYMENT_FOR_MESSAGE_ID: &str = "gas_payment_sequence_for_message_id_v2_"; const GAS_PAYMENT_META_PROCESSED: &str = "gas_payment_meta_processed_v3_"; @@ -516,7 +517,7 @@ make_store_and_retrieve!( ); make_store_and_retrieve!(pub(self), interchain_gas_payment_data_by_gas_payment_key, GAS_PAYMENT_FOR_MESSAGE_ID, GasPaymentKey, InterchainGasPaymentData); make_store_and_retrieve!(pub(self), gas_payment_by_sequence, GAS_PAYMENT_BY_SEQUENCE, u32, InterchainGasPayment); -make_store_and_retrieve!(pub(self), gas_payment_block_by_sequence, GAS_PAYMENT_BY_SEQUENCE, u32, u64); +make_store_and_retrieve!(pub(self), gas_payment_block_by_sequence, GAS_PAYMENT_BLOCK_BY_SEQUENCE, u32, u64); make_store_and_retrieve!( pub, pending_message_retry_count_by_message_id, From 11a6a1cf2d682aada07a320c05659840257874c5 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 23 Sep 2024 15:46:55 -0400 Subject: [PATCH 069/224] test: add olympix github action (#4354) ### Description Run olympix static analyzer --------- Co-authored-by: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> --- .github/workflows/static-analysis.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 788324d6e..4fde41968 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -56,3 +56,18 @@ jobs: uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ steps.slither.outputs.sarif }} + category: "slither" + + - name: Olympix Integrated Security + uses: olympix/integrated-security@main + env: + OLYMPIX_API_TOKEN: ${{ secrets.OLYMPIX_API_TOKEN }} + OLYMPIX_CLI_LOG_LEVEL: 0 + with: + args: -p ./solidity/contracts --output-format sarif --output-path ./ + + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: olympix.sarif + category: "olympix" From 746eeb9d9d6df0f7005287f0863564a7d6829924 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 23 Sep 2024 16:01:30 -0400 Subject: [PATCH 070/224] feat: util for parsing warp route messages (#3784) ### Description Adds token message parser ### Backward compatibility Yes ### Testing Manual warp route send --- .changeset/shiny-dots-vanish.md | 5 +++++ typescript/cli/src/send/transfer.ts | 5 ++++- typescript/cli/src/status/message.ts | 9 ++++++-- typescript/utils/src/index.ts | 7 +++++- typescript/utils/src/messages.ts | 33 ++++++++++++++++++++++++---- typescript/utils/src/types.ts | 5 +++++ 6 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 .changeset/shiny-dots-vanish.md diff --git a/.changeset/shiny-dots-vanish.md b/.changeset/shiny-dots-vanish.md new file mode 100644 index 000000000..7b96ce512 --- /dev/null +++ b/.changeset/shiny-dots-vanish.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/utils': minor +--- + +Add parseTokenMessage util for decoding warp route transfers diff --git a/typescript/cli/src/send/transfer.ts b/typescript/cli/src/send/transfer.ts index 05d582f0a..0bfb4aa55 100644 --- a/typescript/cli/src/send/transfer.ts +++ b/typescript/cli/src/send/transfer.ts @@ -12,7 +12,7 @@ import { WarpCore, WarpCoreConfig, } from '@hyperlane-xyz/sdk'; -import { timeout } from '@hyperlane-xyz/utils'; +import { parseWarpRouteMessage, timeout } from '@hyperlane-xyz/utils'; import { MINIMUM_TEST_SEND_GAS } from '../consts.js'; import { WriteCommandContext } from '../context/types.js'; @@ -164,11 +164,14 @@ async function executeDelivery({ const message: DispatchedMessage = HyperlaneCore.getDispatchedMessages(transferTxReceipt)[messageIndex]; + const parsed = parseWarpRouteMessage(message.parsed.body); + logBlue( `Sent transfer from sender (${senderAddress}) on ${origin} to recipient (${recipient}) on ${destination}.`, ); logBlue(`Message ID: ${message.id}`); log(`Message:\n${indentYamlOrJson(yamlStringify(message, null, 2), 4)}`); + log(`Body:\n${indentYamlOrJson(yamlStringify(parsed, null, 2), 4)}`); if (selfRelay) { const relayer = new HyperlaneRelayer({ core }); diff --git a/typescript/cli/src/status/message.ts b/typescript/cli/src/status/message.ts index 63012499a..2c1e9af96 100644 --- a/typescript/cli/src/status/message.ts +++ b/typescript/cli/src/status/message.ts @@ -2,10 +2,10 @@ import type { TransactionReceipt } from '@ethersproject/providers'; import { input } from '@inquirer/prompts'; import { ChainName, HyperlaneCore, HyperlaneRelayer } from '@hyperlane-xyz/sdk'; -import { assert } from '@hyperlane-xyz/utils'; +import { assert, parseWarpRouteMessage } from '@hyperlane-xyz/utils'; import { WriteCommandContext } from '../context/types.js'; -import { log, logBlue, logGreen, logRed } from '../logger.js'; +import { log, logBlue, logGray, logGreen, logRed } from '../logger.js'; import { runSingleChainSelectionStep } from '../utils/chains.js'; import { stubMerkleTreeConfig } from '../utils/relay.js'; @@ -68,6 +68,11 @@ export async function checkMessageStatus({ const match = messages.find((m) => m.id === messageId); assert(match, `Message ${messageId} not found in dispatch tx ${dispatchTx}`); const message = match; + try { + const { amount, recipient } = parseWarpRouteMessage(message.parsed.body); + logGray(`Warping ${amount} to ${recipient}`); + // eslint-disable-next-line no-empty + } catch {} let deliveredTx: TransactionReceipt; diff --git a/typescript/utils/src/index.ts b/typescript/utils/src/index.ts index 527c6af98..7f4c15841 100644 --- a/typescript/utils/src/index.ts +++ b/typescript/utils/src/index.ts @@ -90,7 +90,12 @@ export { setRootLogger, } from './logging.js'; export { mean, median, randomInt, stdDev, sum } from './math.js'; -export { formatMessage, messageId, parseMessage } from './messages.js'; +export { + formatMessage, + messageId, + parseMessage, + parseWarpRouteMessage, +} from './messages.js'; export { formatLegacyMultisigIsmMetadata, parseLegacyMultisigIsmMetadata, diff --git a/typescript/utils/src/messages.ts b/typescript/utils/src/messages.ts index 2873edcdd..581391af0 100644 --- a/typescript/utils/src/messages.ts +++ b/typescript/utils/src/messages.ts @@ -1,7 +1,14 @@ import { BigNumber, ethers, utils } from 'ethers'; import { addressToBytes32 } from './addresses.js'; -import { Address, Domain, HexString, ParsedMessage } from './types.js'; +import { fromHexString, toHexString } from './strings.js'; +import { + Address, + Domain, + HexString, + ParsedMessage, + ParsedWarpRouteMessage, +} from './types.js'; /** * JS Implementation of solidity/contracts/libs/Message.sol#formatMessage @@ -61,9 +68,27 @@ export function parseMessage(message: string): ParsedMessage { const version = buf.readUint8(VERSION_OFFSET); const nonce = buf.readUInt32BE(NONCE_OFFSET); const origin = buf.readUInt32BE(ORIGIN_OFFSET); - const sender = utils.hexlify(buf.slice(SENDER_OFFSET, DESTINATION_OFFSET)); + const sender = utils.hexlify(buf.subarray(SENDER_OFFSET, DESTINATION_OFFSET)); const destination = buf.readUInt32BE(DESTINATION_OFFSET); - const recipient = utils.hexlify(buf.slice(RECIPIENT_OFFSET, BODY_OFFSET)); - const body = utils.hexlify(buf.slice(BODY_OFFSET)); + const recipient = utils.hexlify(buf.subarray(RECIPIENT_OFFSET, BODY_OFFSET)); + const body = utils.hexlify(buf.subarray(BODY_OFFSET)); return { version, nonce, origin, sender, destination, recipient, body }; } + +export function parseWarpRouteMessage( + messageBody: string, +): ParsedWarpRouteMessage { + const RECIPIENT_OFFSET = 0; + const AMOUNT_OFFSET = 32; + const buf = fromHexString(messageBody); + const recipient = toHexString( + buf.subarray(RECIPIENT_OFFSET, RECIPIENT_OFFSET + 32), + ); + const amount = BigInt( + toHexString(buf.subarray(AMOUNT_OFFSET, AMOUNT_OFFSET + 32)), + ); + return { + recipient, + amount, + }; +} diff --git a/typescript/utils/src/types.ts b/typescript/utils/src/types.ts index 122a4f82a..3d79f0058 100644 --- a/typescript/utils/src/types.ts +++ b/typescript/utils/src/types.ts @@ -98,6 +98,11 @@ export type ParsedMessage = { body: string; }; +export type ParsedWarpRouteMessage = { + recipient: string; + amount: bigint; +}; + export type ParsedLegacyMultisigIsmMetadata = { checkpointRoot: string; checkpointIndex: number; From f2bede3f5f1d6144f6a40f1b92afe82258e78cd7 Mon Sep 17 00:00:00 2001 From: Michael <22820692+joaolago1113@users.noreply.github.com> Date: Mon, 23 Sep 2024 22:05:33 +0100 Subject: [PATCH 071/224] docs: broken links (#4557) ### Description Some of the links in [solidity/contracts/middleware/README.md](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/middleware/README.md) were linked to invalid URLs. I updated those links to the correct addresses and replaced them. --- solidity/contracts/middleware/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solidity/contracts/middleware/README.md b/solidity/contracts/middleware/README.md index 150b240cc..2a95ece96 100644 --- a/solidity/contracts/middleware/README.md +++ b/solidity/contracts/middleware/README.md @@ -3,13 +3,13 @@ ## Interchain Accounts An interchain account is a smart contract that is deployed on a remote chain controlled exclusively by the origin chain's deployer account. -Interchain accounts provide developers with a [transparent multicall API](../OwnableMulticall.sol) to remote smart contracts. +Interchain accounts provide developers with a [transparent multicall API](libs/OwnableMulticall.sol) to remote smart contracts. This avoids the need to deploy application specific smart contracts on remote chains while simultaneously enabling cross-chain composability. See [IBC Interchain Accounts](https://github.com/cosmos/ibc/blob/main/spec/app/ics-027-interchain-accounts/README.md) for the Cosmos ecosystem equivalent. ## Interchain Query System -The interchain query system generalizes view calls to contracts on remote chains. It is a [transparent multicall API](../OwnableMulticall.sol) that can be used to query remote smart contracts. This avoids the need to deploy application specific smart contracts on remote chains while simultaneously enabling cross-chain composability. +The interchain query system generalizes view calls to contracts on remote chains. It is a [transparent multicall API](libs/OwnableMulticall.sol) that can be used to query remote smart contracts. This avoids the need to deploy application specific smart contracts on remote chains while simultaneously enabling cross-chain composability. See [IBC Interchain Query System](https://github.com/cosmos/ibc/tree/main/spec/app/ics-031-crosschain-queries) for the Cosmos ecosystem equivalent. From 8de531fa431d27167af316fde5e8da648ee6b282 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Tue, 24 Sep 2024 09:47:41 -0400 Subject: [PATCH 072/224] fix: warn on submodule metadata builder failures (#4561) ### Description Adds useful logs to aggregation ISM metadata builder. ### Drive-by changes None ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4520 ### Backward compatibility Yes ### Testing Manual --- .changeset/popular-cars-burn.md | 5 +++++ .../sdk/src/ism/metadata/aggregation.ts | 20 ++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 .changeset/popular-cars-burn.md diff --git a/.changeset/popular-cars-burn.md b/.changeset/popular-cars-burn.md new file mode 100644 index 000000000..e0faa46da --- /dev/null +++ b/.changeset/popular-cars-burn.md @@ -0,0 +1,5 @@ +--- +"@hyperlane-xyz/sdk": patch +--- + +fix: warn on submodule metadata builder failures diff --git a/typescript/sdk/src/ism/metadata/aggregation.ts b/typescript/sdk/src/ism/metadata/aggregation.ts index cdf20cd71..baa4d91ea 100644 --- a/typescript/sdk/src/ism/metadata/aggregation.ts +++ b/typescript/sdk/src/ism/metadata/aggregation.ts @@ -44,7 +44,7 @@ export class AggregationMetadataBuilder implements MetadataBuilder { 'Building aggregation metadata', ); assert(maxDepth > 0, 'Max depth reached'); - const promises = await Promise.allSettled( + const results = await Promise.allSettled( context.ism.modules.map((module) => timeout( this.base.build( @@ -58,10 +58,20 @@ export class AggregationMetadataBuilder implements MetadataBuilder { ), ), ); - const metadatas = promises.map((r) => - r.status === 'fulfilled' ? r.value ?? null : null, - ); - const included = metadatas.filter((m) => m !== null).length; + + const metadatas = results.map((result, index) => { + if (result.status === 'rejected') { + this.logger.warn( + `Failed to build for submodule ${index}: ${result.reason}`, + ); + return null; + } else { + this.logger.debug(`Built metadata for submodule ${index}`); + return result.value; + } + }); + + const included = metadatas.filter((meta) => meta !== null).length; assert( included >= context.ism.threshold, `Only built ${included} of ${context.ism.threshold} required modules`, From 74234d6745b9ad465d6d9914af49322fd68b2619 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Tue, 24 Sep 2024 15:26:03 +0100 Subject: [PATCH 073/224] chore: add eclipse warp routes to known app contexts (#4540) ### Description - adds a bunch of new app contexts related to the new warp routes - rearranged some things to avoid circular deps - deployed from a new image off main (following #4528 being merged too) - I did an RC deploy, which updated the rc validators for the first time in a while ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../config/environments/mainnet3/agent.ts | 29 +++++++++--- .../mainnet3/aw-validators/rc.json | 46 +++++++++++++++---- .../environments/mainnet3/warp/warpIds.ts | 17 +++++++ typescript/infra/config/registry.ts | 14 ++++++ typescript/infra/config/warp.ts | 17 +------ typescript/infra/scripts/agent-utils.ts | 13 ------ typescript/infra/scripts/check/check-utils.ts | 2 +- .../infra/scripts/check/check-warp-deploy.ts | 2 +- 8 files changed, 94 insertions(+), 46 deletions(-) create mode 100644 typescript/infra/config/environments/mainnet3/warp/warpIds.ts diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index a00e6a3c4..6c9f18630 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -15,7 +15,7 @@ import { } from '../../../src/config/agent/relayer.js'; import { ALL_KEY_ROLES, Role } from '../../../src/roles.js'; import { Contexts } from '../../contexts.js'; -import { getDomainId } from '../../registry.js'; +import { getDomainId, getWarpAddresses } from '../../registry.js'; import { environment } from './chains.js'; import { helloWorld } from './helloworld.js'; @@ -32,11 +32,11 @@ import inevmEthereumUsdtAddresses from './warp/inevm-USDT-addresses.json'; import injectiveInevmInjAddresses from './warp/injective-inevm-addresses.json'; import mantaTIAAddresses from './warp/manta-TIA-addresses.json'; import merklyEthAddresses from './warp/merkly-eth-addresses.json'; -import renzoEzEthAddressesV1 from './warp/renzo-ezETH-addresses-v1.json'; import renzoEzEthAddressesV3 from './warp/renzo-ezETH-addresses-v3.json'; import victionEthereumEthAddresses from './warp/viction-ETH-addresses.json'; import victionEthereumUsdcAddresses from './warp/viction-USDC-addresses.json'; import victionEthereumUsdtAddresses from './warp/viction-USDT-addresses.json'; +import { WarpRouteIds } from './warp/warpIds.js'; // const releaseCandidateHelloworldMatchingList = routerMatchingList( // helloWorld[Contexts.ReleaseCandidate].addresses, @@ -328,9 +328,24 @@ const metricAppContexts = [ matchingList: matchingList(renzoEzEthAddressesV3), }, { - // preserving old addresses in case any transactions are still in flight and need to be processed - name: 'renzo_ezeth_old', - matchingList: matchingList(renzoEzEthAddressesV1), + name: 'eclipse_usdc', + matchingList: matchingList( + getWarpAddresses(WarpRouteIds.EthereumEclipseUSDC), + ), + }, + { + name: 'eclipse_teth', + matchingList: matchingList( + getWarpAddresses(WarpRouteIds.EthereumEclipseTETH), + ), + }, + { + name: 'eclipse_wif', + matchingList: matchingList(getWarpAddresses(WarpRouteIds.EclipseSolanaWIF)), + }, + { + name: 'eclipse_sol', + matchingList: matchingList(getWarpAddresses(WarpRouteIds.EclipseSolanaSOL)), }, // Hitting max env var size limits, see https://stackoverflow.com/questions/28865473/setting-environment-variable-to-a-large-value-argument-list-too-long#answer-28865503 // { @@ -378,7 +393,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '946dec8-20240919-151233', + tag: 'f36beb6-20240920-170532', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -412,7 +427,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '946dec8-20240919-151233', + tag: 'f36beb6-20240920-170532', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. diff --git a/typescript/infra/config/environments/mainnet3/aw-validators/rc.json b/typescript/infra/config/environments/mainnet3/aw-validators/rc.json index e351098ac..55638fa67 100644 --- a/typescript/infra/config/environments/mainnet3/aw-validators/rc.json +++ b/typescript/infra/config/environments/mainnet3/aw-validators/rc.json @@ -9,6 +9,12 @@ "0x229d4dc6a740212da746b0e35314419a24bc2a5b" ] }, + "astar": { + "validators": ["0x50792eee9574f1bcd002e2c6dddf2aa73b04e254"] + }, + "astarzkevm": { + "validators": ["0x71e0a93f84548765cafc64d787eede19eea1ab06"] + }, "avalanche": { "validators": [ "0x2c7cf6d1796e37676ba95f056ff21bf536c6c2d3", @@ -23,6 +29,9 @@ "0xed7703e06572768bb09e03d88e6b788d8800b9fb" ] }, + "bitlayer": { + "validators": ["0xec567167f07479bcd02a66c2ea66fd329cb9e22f"] + }, "blast": { "validators": ["0x5b32f226e472da6ca19abfe1a29d5d28102a2d1a"] }, @@ -43,14 +52,20 @@ "cheesechain": { "validators": ["0xa481835355309ed46540c742a1c04b58380aa7b4"] }, + "coredao": { + "validators": ["0x9767df5bcebce5ca89fdca5efbfb3b891cf30c5b"] + }, "cyber": { "validators": ["0x84976d5012da6b180462742f2edfae2f9d740c82"] }, "degenchain": { "validators": ["0xac3734bb61e7ddda947b718b930c4067f0ccde7e"] }, + "dogechain": { + "validators": ["0x1e74735379a96586ec31f0a31aa4ee86016404a9"] + }, "eclipsemainnet": { - "validators": ["0xd188fbe099e2db077f4ebc1bf39bb22798500bfb"] + "validators": ["0x283065cb17f98386c2b3656650d8b85e05862c8e"] }, "ethereum": { "validators": [ @@ -59,6 +74,12 @@ "0x87cf8a85465118aff9ec728ca157798201b1e368" ] }, + "everclear": { + "validators": ["0x1b4455316aa859c9b3d2b13868490b7c97a9da3e"] + }, + "flare": { + "validators": ["0x35c3ce34f27def61c2d878ff7c3e35fbab08e92a"] + }, "fraxtal": { "validators": ["0x8c772b730c8deb333dded14cb462e577a06283da"] }, @@ -107,6 +128,9 @@ "mode": { "validators": ["0x2f04ed30b1c27ef8e9e6acd360728d9bd5c3a9e2"] }, + "molten": { + "validators": ["0x2e433ffc514a874537ca2473af51ebba4c863409"] + }, "moonbeam": { "validators": [ "0x75e3cd4e909089ae6c9f3a42b1468b33eec84161", @@ -114,12 +138,8 @@ "0xcaa9c6e6efa35e4a8b47565f3ce98845fa638bf3" ] }, - "neutron": { - "validators": [ - "0x307a8fe091b8273c7ce3d277b161b4a2167279b1", - "0xb825c1bd020cb068f477b320f591b32e26814b5b", - "0x0a5b31090d4c3c207b9ea6708f938e328f895fce" - ] + "oortmainnet": { + "validators": ["0x83f406ff315e90ae9589fa7786bf700e7c7a06f1"] }, "optimism": { "validators": [ @@ -164,8 +184,11 @@ "sei": { "validators": ["0x846e48a7e85e5403cc690a347e1ad3c3dca11b6e"] }, + "shibarium": { + "validators": ["0x7f52b98a0a3e1ced83cf4eced8c0fa61886e7268"] + }, "solanamainnet": { - "validators": ["0xca84b665ab3fed784baf120909c54497c14c93c8"] + "validators": ["0x7bd1536cb7505cf2ea1dc6744127d91fbe87a2ad"] }, "tangle": { "validators": ["0xd778d113975b2fe45eda424bf93c28f32a90b076"] @@ -188,5 +211,12 @@ }, "zetachain": { "validators": ["0xa13d146b47242671466e4041f5fe68d22a2ffe09"] + }, + "neutron": { + "validators": [ + "0x307a8fe091b8273c7ce3d277b161b4a2167279b1", + "0xb825c1bd020cb068f477b320f591b32e26814b5b", + "0x0a5b31090d4c3c207b9ea6708f938e328f895fce" + ] } } diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts new file mode 100644 index 000000000..5e8052d42 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -0,0 +1,17 @@ +export enum WarpRouteIds { + Ancient8EthereumUSDC = 'USDC/ancient8-ethereum', + ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-zircuit', + ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron', + ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', + EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet', + EclipseSolanaWIF = 'WIF/eclipsemainnet-solanamainnet', + EthereumInevmUSDC = 'USDC/ethereum-inevm', + EthereumInevmUSDT = 'USDT/ethereum-inevm', + EthereumEclipseTETH = 'tETH/eclipsemainnet-ethereum', + EthereumEclipseUSDC = 'USDC/eclipsemainnet-ethereum-solanamainnet', + EthereumVictionETH = 'ETH/ethereum-viction', + EthereumVictionUSDC = 'USDC/ethereum-viction', + EthereumVictionUSDT = 'USDT/ethereum-viction', + InevmInjectiveINJ = 'INJ/inevm-injective', + MantapacificNeutronTIA = 'TIA/mantapacific-neutron', +} diff --git a/typescript/infra/config/registry.ts b/typescript/infra/config/registry.ts index 50d6dec3d..51ac87729 100644 --- a/typescript/infra/config/registry.ts +++ b/typescript/infra/config/registry.ts @@ -5,6 +5,7 @@ import { ChainAddresses, MergedRegistry, PartialRegistry, + warpConfigToWarpAddresses, } from '@hyperlane-xyz/registry'; import { FileSystemRegistry } from '@hyperlane-xyz/registry/fs'; import { @@ -90,6 +91,19 @@ export function getChainAddresses(): ChainMap { return getRegistry().getAddresses(); } +export function getWarpAddresses(warpRouteId: string) { + const registry = getRegistry(); + const warpRouteConfig = registry.getWarpRoute(warpRouteId); + + if (!warpRouteConfig) { + throw new Error( + `Warp route config for ${warpRouteId} not found in registry`, + ); + } + + return warpConfigToWarpAddresses(warpRouteConfig); +} + export function getEnvChains(env: DeployEnvironment): ChainName[] { if (env === 'mainnet3') return mainnet3Chains; if (env === 'testnet4') return testnet4Chains; diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 9f1e00879..b96c74c4f 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -21,22 +21,7 @@ import { getEthereumVictionUSDTWarpConfig } from './environments/mainnet3/warp/c import { getInevmInjectiveINJWarpConfig } from './environments/mainnet3/warp/configGetters/getInevmInjectiveINJWarpConfig.js'; import { getMantapacificNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getMantapacificNeutronTiaWarpConfig.js'; import { getRenzoEZETHWarpConfig } from './environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.js'; - -export enum WarpRouteIds { - Ancient8EthereumUSDC = 'USDC/ancient8-ethereum', - ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-zircuit', - ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron', - ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', - EthereumInevmUSDC = 'USDC/ethereum-inevm', - EthereumInevmUSDT = 'USDT/ethereum-inevm', - EthereumEclipseTETH = 'tETH/eclipsemainnet-ethereum', - EthereumEclipseUSDC = 'USDC/eclipsemainnet-ethereum-solanamainnet', - EthereumVictionETH = 'ETH/ethereum-viction', - EthereumVictionUSDC = 'USDC/ethereum-viction', - EthereumVictionUSDT = 'USDT/ethereum-viction', - InevmInjectiveINJ = 'INJ/inevm-injective', - MantapacificNeutronTIA = 'TIA/mantapacific-neutron', -} +import { WarpRouteIds } from './environments/mainnet3/warp/warpIds.js'; type WarpConfigGetterWithConfig = ( routerConfig: ChainMap, diff --git a/typescript/infra/scripts/agent-utils.ts b/typescript/infra/scripts/agent-utils.ts index 74d37d457..2d657b6f3 100644 --- a/typescript/infra/scripts/agent-utils.ts +++ b/typescript/infra/scripts/agent-utils.ts @@ -497,19 +497,6 @@ export function getAddresses(environment: DeployEnvironment, module: Modules) { } } -export function getWarpAddresses(warpRouteId: string) { - const registry = getRegistry(); - const warpRouteConfig = registry.getWarpRoute(warpRouteId); - - if (!warpRouteConfig) { - throw new Error( - `Warp route config for ${warpRouteId} not found in registry`, - ); - } - - return warpConfigToWarpAddresses(warpRouteConfig); -} - export function writeAddresses( environment: DeployEnvironment, module: Modules, diff --git a/typescript/infra/scripts/check/check-utils.ts b/typescript/infra/scripts/check/check-utils.ts index 096745134..5b6537588 100644 --- a/typescript/infra/scripts/check/check-utils.ts +++ b/typescript/infra/scripts/check/check-utils.ts @@ -22,6 +22,7 @@ import { eqAddress, objFilter } from '@hyperlane-xyz/utils'; import { Contexts } from '../../config/contexts.js'; import { DEPLOYER } from '../../config/environments/mainnet3/owners.js'; +import { getWarpAddresses } from '../../config/registry.js'; import { getWarpConfig } from '../../config/warp.js'; import { DeployEnvironment } from '../../src/config/environment.js'; import { HyperlaneAppGovernor } from '../../src/govern/HyperlaneAppGovernor.js'; @@ -35,7 +36,6 @@ import { logViolationDetails } from '../../src/utils/violation.js'; import { Modules, getArgs as getRootArgs, - getWarpAddresses, withAsDeployer, withChains, withContext, diff --git a/typescript/infra/scripts/check/check-warp-deploy.ts b/typescript/infra/scripts/check/check-warp-deploy.ts index 1a582aa8c..66334b8cf 100644 --- a/typescript/infra/scripts/check/check-warp-deploy.ts +++ b/typescript/infra/scripts/check/check-warp-deploy.ts @@ -1,7 +1,7 @@ import chalk from 'chalk'; import { Gauge, Registry } from 'prom-client'; -import { WarpRouteIds } from '../../config/warp.js'; +import { WarpRouteIds } from '../../config/environments/mainnet3/warp/warpIds.js'; import { submitMetrics } from '../../src/utils/metrics.js'; import { Modules } from '../agent-utils.js'; From 5cb178704479f431a7740b07b354c1e13209db47 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Tue, 24 Sep 2024 20:16:47 +0100 Subject: [PATCH 074/224] feat: E2E Test Cosmos Scraper Invariant (#4536) ### Description - Add metrics based Scraper invariant into E2E Test for Cosmos - Report error if transaction contains multiple contract execution messages - Report error if fee are expressed in unsupported denomination ### Related issues - Successfully scrape Cosmos chains in e2e test #3355 ### Backward compatibility Yes ### Testing E2E Testing --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../src/providers/cosmos/provider.rs | 95 +++++++++++++++++-- .../src/providers/grpc/tests.rs | 6 +- .../hyperlane-cosmos/src/trait_builder.rs | 21 +++- .../src/settings/parser/connection_parser.rs | 24 ++++- .../hyperlane-base/src/settings/parser/mod.rs | 15 +-- rust/main/utils/run-locally/src/cosmos/mod.rs | 64 +++++++++++-- .../utils/run-locally/src/cosmos/types.rs | 7 +- .../src/invariants/termination_invariants.rs | 32 ++++--- rust/main/utils/run-locally/src/main.rs | 7 +- 9 files changed, 231 insertions(+), 40 deletions(-) diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index 5f207cc8a..62931e69e 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -2,12 +2,14 @@ use async_trait::async_trait; use cosmrs::cosmwasm::MsgExecuteContract; use cosmrs::crypto::PublicKey; use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo}; -use cosmrs::{AccountId, Tx}; +use cosmrs::{AccountId, Any, Coin, Tx}; use itertools::Itertools; +use once_cell::sync::Lazy; use tendermint::hash::Algorithm; use tendermint::Hash; use tendermint_rpc::{client::CompatMode, Client, HttpClient}; use time::OffsetDateTime; +use tracing::{error, warn}; use hyperlane_core::{ BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, ContractLocator, HyperlaneChain, @@ -20,6 +22,9 @@ use crate::libs::account::CosmosAccountId; use crate::providers::rpc::CosmosRpcClient; use crate::{ConnectionConf, CosmosAmount, HyperlaneCosmosError, Signer}; +/// Exponent value for atto units (10^-18). +const ATTO_EXPONENT: u32 = 18; + /// Abstraction over a connection to a Cosmos chain #[derive(Debug, Clone)] pub struct CosmosProvider { @@ -128,23 +133,84 @@ impl CosmosProvider { /// Extract contract address from transaction. /// Assumes that there is only one `MsgExecuteContract` message in the transaction - fn contract(tx: &Tx) -> ChainResult { + fn contract(tx: &Tx, tx_hash: &H256) -> ChainResult { use cosmrs::proto::cosmwasm::wasm::v1::MsgExecuteContract as ProtoMsgExecuteContract; - let any = tx + let contract_execution_messages = tx .body .messages .iter() - .find(|a| a.type_url == "/cosmwasm.wasm.v1.MsgExecuteContract") - .ok_or_else(|| { - ChainCommunicationError::from_other_str("could not find contract execution message") - })?; + .filter(|a| a.type_url == "/cosmwasm.wasm.v1.MsgExecuteContract") + .cloned() + .collect::>(); + + let contract_execution_messages_len = contract_execution_messages.len(); + if contract_execution_messages_len > 1 { + error!( + ?tx_hash, + ?contract_execution_messages, + "transaction contains multiple contract execution messages, we are indexing the first entry only"); + } + + let any = contract_execution_messages.first().ok_or_else(|| { + ChainCommunicationError::from_other_str("could not find contract execution message") + })?; let proto = ProtoMsgExecuteContract::from_any(any).map_err(Into::::into)?; let msg = MsgExecuteContract::try_from(proto)?; let contract = H256::try_from(CosmosAccountId::new(&msg.contract))?; Ok(contract) } + + /// Reports if transaction contains fees expressed in unsupported denominations + /// The only denomination we support at the moment is the one we express gas minimum price + /// in the configuration of a chain. If fees contain an entry in a different denomination, + /// we report it in the logs. + fn report_unsupported_denominations(&self, tx: &Tx, tx_hash: &H256) { + let supported_denomination = self.connection_conf.get_minimum_gas_price().denom; + let unsupported_denominations = tx + .auth_info + .fee + .amount + .iter() + .filter(|c| c.denom.as_ref() != supported_denomination) + .map(|c| c.denom.as_ref()) + .fold("".to_string(), |acc, denom| acc + ", " + denom); + + if !unsupported_denominations.is_empty() { + error!( + ?tx_hash, + ?supported_denomination, + ?unsupported_denominations, + "transaction contains fees in unsupported denominations, manual intervention is required"); + } + } + + /// Converts fees to a common denomination if necessary. + /// + /// Currently, we support Injective, Neutron and Osmosis. Fees in Injective are usually + /// expressed in `inj` which is 10^-18 of `INJ`, while fees in Neutron and Osmosis are + /// usually expressed in `untrn` and `uosmo`, respectively, which are 10^-6 of corresponding + /// `NTRN` and `OSMO`. + /// + /// This function will convert fees expressed in `untrn` and `uosmo` to 10^-18 of `NTRN` and + /// `OSMO` and it will keep fees expressed in `inj` as is. + /// + /// If fees are expressed in an unsupported denomination, they will be ignored. + fn convert_fee(&self, coin: &Coin) -> U256 { + let native_token = self.connection_conf.get_native_token(); + + if coin.denom.as_ref() != native_token.denom { + return U256::zero(); + } + + let exponent = ATTO_EXPONENT - native_token.decimals; + let coefficient = U256::from(10u128.pow(exponent)); + + let amount_in_native_denom = U256::from(coin.amount); + + amount_in_native_denom * coefficient + } } impl HyperlaneChain for CosmosProvider { @@ -208,19 +274,28 @@ impl HyperlaneProvider for CosmosProvider { let tx = Tx::from_bytes(&response.tx)?; - let contract = Self::contract(&tx)?; + let contract = Self::contract(&tx, hash)?; let (sender, nonce) = self.sender_and_nonce(&tx)?; - // TODO support multiple denomination for amount + // TODO support multiple denominations for amount + self.report_unsupported_denominations(&tx, hash); + let gas_limit = U256::from(tx.auth_info.fee.gas_limit); let fee = tx .auth_info .fee .amount .iter() - .fold(U256::zero(), |acc, a| acc + a.amount); + .map(|c| self.convert_fee(c)) + .fold(U256::zero(), |acc, v| acc + v); let gas_price = fee / gas_limit; + let gas_price = if gas_price == U256::zero() { + warn!(?fee, ?gas_limit, "calculated zero gas price"); + U256::one() + } else { + gas_price + }; let tx_info = TxnInfo { hash: hash.to_owned(), diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs index 451c67b22..05570f9ce 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs @@ -7,7 +7,7 @@ use hyperlane_core::{ContractLocator, HyperlaneDomain, KnownHyperlaneDomain}; use crate::address::CosmosAddress; use crate::grpc::{WasmGrpcProvider, WasmProvider}; -use crate::{ConnectionConf, CosmosAmount, RawCosmosAmount}; +use crate::{ConnectionConf, CosmosAmount, NativeToken, RawCosmosAmount}; #[ignore] #[tokio::test] @@ -65,6 +65,10 @@ fn provider(address: &str) -> WasmGrpcProvider { batch_contract_address: None, max_batch_size: 1, }, + NativeToken { + decimals: 6, + denom: "untrn".to_owned(), + }, ), CosmosAmount { denom: "untrn".to_owned(), diff --git a/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs b/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs index a6463654f..c48c3611d 100644 --- a/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs +++ b/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs @@ -1,9 +1,10 @@ use std::str::FromStr; use derive_new::new; -use hyperlane_core::{config::OperationBatchConfig, ChainCommunicationError, FixedPointNumber}; use url::Url; +use hyperlane_core::{config::OperationBatchConfig, ChainCommunicationError, FixedPointNumber}; + /// Cosmos connection configuration #[derive(Debug, Clone)] pub struct ConnectionConf { @@ -27,6 +28,8 @@ pub struct ConnectionConf { contract_address_bytes: usize, /// Operation batching configuration pub operation_batch: OperationBatchConfig, + /// Native Token + native_token: NativeToken, } /// Untyped cosmos amount @@ -57,6 +60,15 @@ impl TryFrom for CosmosAmount { } } +/// Chain native token denomination and number of decimal places +#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] +pub struct NativeToken { + /// The number of decimal places in token which can be expressed by denomination + pub decimals: u32, + /// Denomination of the token + pub denom: String, +} + /// An error type when parsing a connection configuration. #[derive(thiserror::Error, Debug)] pub enum ConnectionConfError { @@ -108,6 +120,11 @@ impl ConnectionConf { self.gas_price.clone() } + /// Get the native token + pub fn get_native_token(&self) -> &NativeToken { + &self.native_token + } + /// Get the number of bytes used to represent a contract address pub fn get_contract_address_bytes(&self) -> usize { self.contract_address_bytes @@ -124,6 +141,7 @@ impl ConnectionConf { minimum_gas_price: RawCosmosAmount, contract_address_bytes: usize, operation_batch: OperationBatchConfig, + native_token: NativeToken, ) -> Self { Self { grpc_urls, @@ -134,6 +152,7 @@ impl ConnectionConf { gas_price: minimum_gas_price, contract_address_bytes, operation_batch, + native_token, } } } diff --git a/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs b/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs index 4bc6a01b7..4a435444d 100644 --- a/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs +++ b/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs @@ -1,8 +1,10 @@ use eyre::eyre; +use url::Url; + use h_eth::TransactionOverrides; use hyperlane_core::config::{ConfigErrResultExt, OperationBatchConfig}; use hyperlane_core::{config::ConfigParsingError, HyperlaneDomainProtocol}; -use url::Url; +use hyperlane_cosmos::NativeToken; use crate::settings::envs::*; use crate::settings::ChainConnectionConf; @@ -135,6 +137,25 @@ pub fn build_cosmos_connection_conf( .parse_u64() .end(); + let native_token_decimals = chain + .chain(err) + .get_key("nativeToken") + .get_key("decimals") + .parse_u32() + .unwrap_or(18); + + let native_token_denom = chain + .chain(err) + .get_key("nativeToken") + .get_key("denom") + .parse_string() + .unwrap_or(""); + + let native_token = NativeToken { + decimals: native_token_decimals, + denom: native_token_denom.to_owned(), + }; + if !local_err.is_ok() { err.merge(local_err); None @@ -148,6 +169,7 @@ pub fn build_cosmos_connection_conf( gas_price.unwrap(), contract_address_bytes.unwrap().try_into().unwrap(), operation_batch, + native_token, ))) } } diff --git a/rust/main/hyperlane-base/src/settings/parser/mod.rs b/rust/main/hyperlane-base/src/settings/parser/mod.rs index 3c3a3aa65..f5c1451a0 100644 --- a/rust/main/hyperlane-base/src/settings/parser/mod.rs +++ b/rust/main/hyperlane-base/src/settings/parser/mod.rs @@ -11,23 +11,26 @@ use std::{ use convert_case::{Case, Casing}; use eyre::{eyre, Context}; +use itertools::Itertools; +use serde::Deserialize; +use serde_json::Value; +use url::Url; + use h_cosmos::RawCosmosAmount; use hyperlane_core::{ cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol, HyperlaneDomainTechnicalStack, IndexMode, }; -use itertools::Itertools; -use serde::Deserialize; -use serde_json::Value; -use url::Url; -pub use self::json_value_parser::ValueParser; -pub use super::envs::*; use crate::settings::{ chains::IndexSettings, parser::connection_parser::build_connection_conf, trace::TracingConfig, ChainConf, CoreContractAddresses, Settings, SignerConf, }; +pub use super::envs::*; + +pub use self::json_value_parser::ValueParser; + mod connection_parser; mod json_value_parser; diff --git a/rust/main/utils/run-locally/src/cosmos/mod.rs b/rust/main/utils/run-locally/src/cosmos/mod.rs index 83a56786b..2b0ab06b7 100644 --- a/rust/main/utils/run-locally/src/cosmos/mod.rs +++ b/rust/main/utils/run-locally/src/cosmos/mod.rs @@ -589,6 +589,7 @@ fn run_locally() { // look for the end condition. if termination_invariants_met( hpl_rly_metrics_port, + hpl_scr_metrics_port, dispatched_messages, starting_relayer_balance, ) @@ -615,37 +616,38 @@ fn run_locally() { fn termination_invariants_met( relayer_metrics_port: u32, + scraper_metrics_port: u32, messages_expected: u32, starting_relayer_balance: f64, ) -> eyre::Result { - let gas_payments_scraped = fetch_metric( + let expected_gas_payments = messages_expected; + let gas_payments_event_count = fetch_metric( &relayer_metrics_port.to_string(), "hyperlane_contract_sync_stored_events", &hashmap! {"data_type" => "gas_payment"}, )? .iter() .sum::(); - let expected_gas_payments = messages_expected; - if gas_payments_scraped != expected_gas_payments { + if gas_payments_event_count != expected_gas_payments { log!( "Relayer has indexed {} gas payments, expected {}", - gas_payments_scraped, + gas_payments_event_count, expected_gas_payments ); return Ok(false); } - let delivered_messages_scraped = fetch_metric( + let msg_processed_count = fetch_metric( &relayer_metrics_port.to_string(), "hyperlane_operations_processed_count", &hashmap! {"phase" => "confirmed"}, )? .iter() .sum::(); - if delivered_messages_scraped != messages_expected { + if msg_processed_count != messages_expected { log!( "Relayer confirmed {} submitted messages, expected {}", - delivered_messages_scraped, + msg_processed_count, messages_expected ); return Ok(false); @@ -667,6 +669,54 @@ fn termination_invariants_met( return Ok(false); } + let dispatched_messages_scraped = fetch_metric( + &scraper_metrics_port.to_string(), + "hyperlane_contract_sync_stored_events", + &hashmap! {"data_type" => "message_dispatch"}, + )? + .iter() + .sum::(); + if dispatched_messages_scraped != messages_expected { + log!( + "Scraper has scraped {} dispatched messages, expected {}", + dispatched_messages_scraped, + messages_expected + ); + return Ok(false); + } + + let gas_payments_scraped = fetch_metric( + &scraper_metrics_port.to_string(), + "hyperlane_contract_sync_stored_events", + &hashmap! {"data_type" => "gas_payment"}, + )? + .iter() + .sum::(); + if gas_payments_scraped != expected_gas_payments { + log!( + "Scraper has scraped {} gas payments, expected {}", + gas_payments_scraped, + expected_gas_payments + ); + return Ok(false); + } + + let delivered_messages_scraped = fetch_metric( + &scraper_metrics_port.to_string(), + "hyperlane_contract_sync_stored_events", + &hashmap! {"data_type" => "message_delivery"}, + )? + .iter() + .sum::(); + if delivered_messages_scraped != messages_expected { + log!( + "Scraper has scraped {} delivered messages, expected {}", + delivered_messages_scraped, + messages_expected + ); + return Ok(false); + } + log!("Termination invariants have been meet"); Ok(true) } diff --git a/rust/main/utils/run-locally/src/cosmos/types.rs b/rust/main/utils/run-locally/src/cosmos/types.rs index 78a45e6c2..4ce8f42a5 100644 --- a/rust/main/utils/run-locally/src/cosmos/types.rs +++ b/rust/main/utils/run-locally/src/cosmos/types.rs @@ -1,6 +1,6 @@ use std::{collections::BTreeMap, path::PathBuf}; -use hyperlane_cosmos::RawCosmosAmount; +use hyperlane_cosmos::{NativeToken, RawCosmosAmount}; use hyperlane_cosmwasm_interface::types::bech32_decode; use super::{cli::OsmosisCLI, CosmosNetwork}; @@ -125,6 +125,7 @@ pub struct AgentConfig { pub index: AgentConfigIndex, pub gas_price: RawCosmosAmount, pub contract_address_bytes: usize, + pub native_token: NativeToken, } #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] @@ -178,6 +179,10 @@ impl AgentConfig { }, contract_address_bytes: 32, index: AgentConfigIndex { from: 1, chunk: 5 }, + native_token: NativeToken { + decimals: 6, + denom: "uosmo".to_string(), + }, } } } diff --git a/rust/main/utils/run-locally/src/invariants/termination_invariants.rs b/rust/main/utils/run-locally/src/invariants/termination_invariants.rs index db3dae380..248daec84 100644 --- a/rust/main/utils/run-locally/src/invariants/termination_invariants.rs +++ b/rust/main/utils/run-locally/src/invariants/termination_invariants.rs @@ -10,7 +10,10 @@ use relayer::GAS_EXPENDITURE_LOG_MESSAGE; use crate::invariants::SOL_MESSAGES_EXPECTED; use crate::logging::log; use crate::solana::solana_termination_invariants_met; -use crate::{fetch_metric, AGENT_LOGGING_DIR, ZERO_MERKLE_INSERTION_KATHY_MESSAGES}; +use crate::{ + fetch_metric, AGENT_LOGGING_DIR, RELAYER_METRICS_PORT, SCRAPER_METRICS_PORT, + ZERO_MERKLE_INSERTION_KATHY_MESSAGES, +}; /// Use the metrics to check if the relayer queues are empty and the expected /// number of messages have been sent. @@ -29,7 +32,11 @@ pub fn termination_invariants_met( }; let total_messages_expected = eth_messages_expected + sol_messages_expected; - let lengths = fetch_metric("9092", "hyperlane_submitter_queue_length", &hashmap! {})?; + let lengths = fetch_metric( + RELAYER_METRICS_PORT, + "hyperlane_submitter_queue_length", + &hashmap! {}, + )?; assert!(!lengths.is_empty(), "Could not find queue length metric"); if lengths.iter().sum::() != ZERO_MERKLE_INSERTION_KATHY_MESSAGES { log!("Relayer queues not empty. Lengths: {:?}", lengths); @@ -38,10 +45,13 @@ pub fn termination_invariants_met( // Also ensure the counter is as expected (total number of messages), summed // across all mailboxes. - let msg_processed_count = - fetch_metric("9092", "hyperlane_messages_processed_count", &hashmap! {})? - .iter() - .sum::(); + let msg_processed_count = fetch_metric( + RELAYER_METRICS_PORT, + "hyperlane_messages_processed_count", + &hashmap! {}, + )? + .iter() + .sum::(); if msg_processed_count != total_messages_expected { log!( "Relayer has {} processed messages, expected {}", @@ -52,7 +62,7 @@ pub fn termination_invariants_met( } let gas_payment_events_count = fetch_metric( - "9092", + RELAYER_METRICS_PORT, "hyperlane_contract_sync_stored_events", &hashmap! {"data_type" => "gas_payments"}, )? @@ -114,7 +124,7 @@ pub fn termination_invariants_met( ); let gas_payment_sealevel_events_count = fetch_metric( - "9092", + RELAYER_METRICS_PORT, "hyperlane_contract_sync_stored_events", &hashmap! { "data_type" => "gas_payments", @@ -144,7 +154,7 @@ pub fn termination_invariants_met( } let dispatched_messages_scraped = fetch_metric( - "9093", + SCRAPER_METRICS_PORT, "hyperlane_contract_sync_stored_events", &hashmap! {"data_type" => "message_dispatch"}, )? @@ -160,7 +170,7 @@ pub fn termination_invariants_met( } let gas_payments_scraped = fetch_metric( - "9093", + SCRAPER_METRICS_PORT, "hyperlane_contract_sync_stored_events", &hashmap! {"data_type" => "gas_payment"}, )? @@ -180,7 +190,7 @@ pub fn termination_invariants_met( } let delivered_messages_scraped = fetch_metric( - "9093", + SCRAPER_METRICS_PORT, "hyperlane_contract_sync_stored_events", &hashmap! {"data_type" => "message_delivery"}, )? diff --git a/rust/main/utils/run-locally/src/main.rs b/rust/main/utils/run-locally/src/main.rs index 13c8e4ab1..65ff63199 100644 --- a/rust/main/utils/run-locally/src/main.rs +++ b/rust/main/utils/run-locally/src/main.rs @@ -94,6 +94,9 @@ const MONOREPO_ROOT_PATH: &str = "../../"; const ZERO_MERKLE_INSERTION_KATHY_MESSAGES: u32 = 10; +const RELAYER_METRICS_PORT: &str = "9092"; +const SCRAPER_METRICS_PORT: &str = "9093"; + type DynPath = Box>; static RUN_LOG_WATCHERS: AtomicBool = AtomicBool::new(true); @@ -210,7 +213,7 @@ fn main() -> ExitCode { multicall_address_string, ) .hyp_env("CHAINS_TEST3_MAXBATCHSIZE", "5") - .hyp_env("METRICSPORT", "9092") + .hyp_env("METRICSPORT", RELAYER_METRICS_PORT) .hyp_env("DB", relayer_db.to_str().unwrap()) .hyp_env("CHAINS_TEST1_SIGNER_KEY", RELAYER_KEYS[0]) .hyp_env("CHAINS_TEST2_SIGNER_KEY", RELAYER_KEYS[1]) @@ -284,7 +287,7 @@ fn main() -> ExitCode { .hyp_env("CHAINS_TEST3_RPCCONSENSUSTYPE", "quorum") .hyp_env("CHAINS_TEST3_CUSTOMRPCURLS", "http://127.0.0.1:8545") .hyp_env("CHAINSTOSCRAPE", "test1,test2,test3") - .hyp_env("METRICSPORT", "9093") + .hyp_env("METRICSPORT", SCRAPER_METRICS_PORT) .hyp_env( "DB", "postgresql://postgres:47221c18c610@localhost:5432/postgres", From c54cd21f5ea8fa21669fee7b51ace972ab51be91 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Tue, 24 Sep 2024 21:26:18 +0100 Subject: [PATCH 075/224] fix: update moonbeam IGP overhead (#4564) ### Description Following a recent runtime upgrade, they dramatically increased gas costs. It seems like the impact is that some txs may use as much as 4x the normal gas price. But confusingly this is only for some types of txs that affect the "proof of validity". Some context in the linked discord thread in the comment and in the tg chat with them ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/infra/config/environments/mainnet3/agent.ts | 4 ++-- typescript/infra/config/environments/mainnet3/igp.ts | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 6c9f18630..5565c0962 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -393,7 +393,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'f36beb6-20240920-170532', + tag: '5cb1787-20240924-192934', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -427,7 +427,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'f36beb6-20240920-170532', + tag: '5cb1787-20240924-192934', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. diff --git a/typescript/infra/config/environments/mainnet3/igp.ts b/typescript/infra/config/environments/mainnet3/igp.ts index 39e09e07d..ca167f356 100644 --- a/typescript/infra/config/environments/mainnet3/igp.ts +++ b/typescript/infra/config/environments/mainnet3/igp.ts @@ -27,13 +27,19 @@ const tokenPrices: ChainMap = rawTokenPrices; const FOREIGN_DEFAULT_OVERHEAD = 600_000; // cosmwasm warp route somewhat arbitrarily chosen -const remoteOverhead = (remote: ChainName) => - ethereumChainNames.includes(remote as any) +function remoteOverhead(remote: ChainName) { + let overhead = ethereumChainNames.includes(remote as any) ? multisigIsmVerificationCost( defaultMultisigConfigs[remote].threshold, defaultMultisigConfigs[remote].validators.length, ) : FOREIGN_DEFAULT_OVERHEAD; // non-ethereum overhead + if (remote === 'moonbeam') { + // Moonbeam has (roughly) 4x'd their gas costs, some context in https://discord.com/channels/935678348330434570/1287816893553705041 + overhead *= 4; + } + return overhead; +} // Gets the exchange rate of the remote quoted in local tokens function getTokenExchangeRate(local: ChainName, remote: ChainName): BigNumber { From 50319d8bad77fb485173c2ad1041d777329dd494 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:55:28 -0400 Subject: [PATCH 076/224] feat: improve infra deploy.ts logging (#4515) feat: improve infra deploy.ts logging - `ism`, `core` and `testrecipient` use the abstract HyperlaneDeployer's `deploy()` method, which then iterates through chains - this PR clones this method into infra and then makes the subsequent call per-chain, whilst tracking status of each chain's deploy - as part of the post-deploy step, print a table of deploy statuses for all requested chains - an alternative idea was to implement the map of chain status in the deployer, but I would rather minimise adding logic to the old deployers drive-by: update HyperlaneDeployer.deploy for better error handling/logging - i'm also happy to also revert this commit and keep the update to infra only drive-by: update column headings in print-mailbox-owner script example of success: ![image](https://github.com/user-attachments/assets/b02197fc-af43-46af-9cd5-1bdb5b1031ba) example of failure: ![image](https://github.com/user-attachments/assets/f8e75890-b609-4080-b16d-060374efb591) example of error during deployment: ![image](https://github.com/user-attachments/assets/1ef70e8e-d851-4e53-b589-4008c8ca10e6) --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/giant-houses-cough.md | 7 + .changeset/twenty-rats-buy.md | 5 + typescript/infra/scripts/deploy.ts | 7 +- .../infra/scripts/print-mailbox-owner.ts | 6 +- typescript/infra/src/deployment/deploy.ts | 227 +++++++++++++++--- .../sdk/src/deploy/HyperlaneDeployer.ts | 48 ++-- typescript/utils/src/async.ts | 29 ++- 7 files changed, 250 insertions(+), 79 deletions(-) create mode 100644 .changeset/giant-houses-cough.md create mode 100644 .changeset/twenty-rats-buy.md diff --git a/.changeset/giant-houses-cough.md b/.changeset/giant-houses-cough.md new file mode 100644 index 000000000..b50c79961 --- /dev/null +++ b/.changeset/giant-houses-cough.md @@ -0,0 +1,7 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Make HyperlaneDeployer.chainTimeoutMs public. +Remove HyperlaneDeployer.startingBlockNumbers as it's not used by any deployer. +Update HyperlaneDeployer.deploy for better logging and error handling. diff --git a/.changeset/twenty-rats-buy.md b/.changeset/twenty-rats-buy.md new file mode 100644 index 000000000..f8d44359b --- /dev/null +++ b/.changeset/twenty-rats-buy.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/utils': patch +--- + +Ensure runWithTimeout cleans up after itself properly diff --git a/typescript/infra/scripts/deploy.ts b/typescript/infra/scripts/deploy.ts index af41da2f3..111d85dbf 100644 --- a/typescript/infra/scripts/deploy.ts +++ b/typescript/infra/scripts/deploy.ts @@ -27,7 +27,7 @@ import { Contexts } from '../config/contexts.js'; import { core as coreConfig } from '../config/environments/mainnet3/core.js'; import { getEnvAddresses } from '../config/registry.js'; import { getWarpConfig } from '../config/warp.js'; -import { deployWithArtifacts } from '../src/deployment/deploy.js'; +import { DeployCache, deployWithArtifacts } from '../src/deployment/deploy.js'; import { TestQuerySenderDeployer } from '../src/deployment/testcontracts/testquerysender.js'; import { extractBuildArtifact, @@ -251,7 +251,7 @@ async function main() { const verification = path.join(modulePath, 'verification.json'); - const cache = { + const cache: DeployCache = { verification, read: environment !== 'test', write: !fork, @@ -290,6 +290,9 @@ async function main() { // Use chains if provided, otherwise deploy to all chains // If fork is provided, deploy to fork only targetNetworks: chains && chains.length > 0 ? chains : !fork ? [] : [fork], + module, + multiProvider, + concurrentDeploy, }); } diff --git a/typescript/infra/scripts/print-mailbox-owner.ts b/typescript/infra/scripts/print-mailbox-owner.ts index 78b4fea93..88b04598d 100644 --- a/typescript/infra/scripts/print-mailbox-owner.ts +++ b/typescript/infra/scripts/print-mailbox-owner.ts @@ -109,8 +109,8 @@ async function main() { } return { - address: ownerAddress, - owner: ownerType, + owner: ownerAddress, + type: ownerType, }; }, ), @@ -125,7 +125,7 @@ async function main() { Object.values(Owner).map((ownerType) => ({ 'Owner Type': ownerType, 'Chain Count': Object.values(mailboxOwners).filter( - ({ owner }) => owner === ownerType, + ({ type }) => type === ownerType, ).length, })), ); diff --git a/typescript/infra/src/deployment/deploy.ts b/typescript/infra/src/deployment/deploy.ts index 398820f8e..b50203343 100644 --- a/typescript/infra/src/deployment/deploy.ts +++ b/typescript/infra/src/deployment/deploy.ts @@ -1,10 +1,20 @@ +import chalk from 'chalk'; + import { ChainMap, ChainName, + HyperlaneContractsMap, HyperlaneDeployer, + HyperlaneFactories, + MultiProvider, serializeContractsMap, } from '@hyperlane-xyz/sdk'; -import { objFilter, objMerge } from '@hyperlane-xyz/utils'; +import { + ProtocolType, + objFilter, + objMerge, + runWithTimeout, +} from '@hyperlane-xyz/utils'; import { Modules, @@ -14,22 +24,47 @@ import { import { DeployEnvironment } from '../config/environment.js'; import { readJSONAtPath, writeJsonAtPath } from '../utils/utils.js'; +enum DeployStatus { + EMPTY = '🫥', + SUCCESS = '✅', + INFLIGHT = '⏳', + FAILURE = '❌', +} + +const deployStatus: ChainMap = {}; + +const standardDeployModules = [ + Modules.PROXY_FACTORY, + Modules.CORE, + Modules.TEST_RECIPIENT, + Modules.INTERCHAIN_GAS_PAYMASTER, + Modules.HOOK, +]; + +export interface DeployCache { + verification: string; + read: boolean; + write: boolean; + environment: DeployEnvironment; + module: Modules; +} + export async function deployWithArtifacts({ configMap, deployer, cache, targetNetworks, + module, + multiProvider, + concurrentDeploy, }: { configMap: ChainMap; deployer: HyperlaneDeployer; - cache: { - verification: string; - read: boolean; - write: boolean; - environment: DeployEnvironment; - module: Modules; - }; + cache: DeployCache; targetNetworks: ChainName[]; + module: Modules; + multiProvider: MultiProvider; + concurrentDeploy: boolean; }) { if (cache.read) { const addressesMap = getAddresses(cache.environment, cache.module); @@ -37,17 +72,58 @@ export async function deployWithArtifacts({ } // Filter the config map to only deploy the target networks - let targetConfigMap = configMap; - if (targetNetworks.length > 0) { - targetConfigMap = objFilter(configMap, (chain, _): _ is Config => - targetNetworks.includes(chain), - ); - } + const targetConfigMap = + targetNetworks.length > 0 + ? objFilter(configMap, (chain, _): _ is Config => + targetNetworks.includes(chain), + ) + : configMap; + // Run post-deploy steps const handleExit = async () => { - console.log('Running post-deploy steps'); - await postDeploy(deployer, cache); - console.log('Post-deploy completed'); + console.info(chalk.gray.italic('Running post-deploy steps')); + await runWithTimeout(5000, () => postDeploy(deployer, cache)) + .then(() => console.info('Post-deploy completed')) + .catch((error) => { + console.error( + chalk.red('Post-deploy steps timed out or failed'), + error, + ); + }); + + if (Object.keys(deployStatus).length > 0) { + const statusTable = Object.entries(deployStatus).map( + ([chain, status]) => ({ chain, status: status ?? DeployStatus.EMPTY }), + ); + console.table(statusTable); + + const failedChainNames = Object.entries(deployStatus) + .filter(([_, status]) => status === DeployStatus.FAILURE) + .map(([chain, _]) => chain); + + // If there are failed chains, exit with a non-zero status + if (failedChainNames.length > 0) { + console.error( + chalk.red.bold( + `\nFailed to deploy on ${failedChainNames.length} chain${ + failedChainNames.length === 1 ? '' : 's' + }:\n${failedChainNames.join(' ')}`, + ), + ); + process.exit(1); + } else { + const numTotalChains = Object.keys(targetConfigMap).length; + console.info( + chalk.green.bold( + `Successfully deployed contracts on ${numTotalChains} chain${ + numTotalChains === 1 ? '' : 's' + }`, + ), + ); + } + } + + process.exit(0); }; // Handle Ctrl+C @@ -56,33 +132,108 @@ export async function deployWithArtifacts({ // deployments exceeding the timeout are still written process.on('beforeExit', handleExit); - // Deploy the contracts - try { - await deployer.deploy(targetConfigMap); - } catch (e: any) { - if (e?.message.includes('Timed out')) { - console.warn('Contract deployment exceeding configured timeout', e); - } else { - console.error('Contract deployment failed', e); + // Standard deploy modules are the ones that can be deployed with the + // abstract HyperlaneDeployer's deploy function because they don't require any special logic + if (standardDeployModules.includes(module)) { + await baseDeploy( + targetConfigMap, + deployer, + multiProvider, + concurrentDeploy, + ); + } else { + try { + await deployer.deploy(targetConfigMap); + } catch (error: any) { + if (error?.message.includes('Timed out')) { + console.warn( + chalk.yellow('Contract deployment exceeding configured timeout'), + error, + ); + } else { + console.error(chalk.red('Contract deployment failed'), error); + } + } + } +} + +async function baseDeploy< + Config extends object, + Factories extends HyperlaneFactories, +>( + configMap: ChainMap, + deployer: HyperlaneDeployer, + multiProvider: MultiProvider, + concurrentDeploy: boolean, +): Promise> { + const configChains = Object.keys(configMap); + const ethereumConfigChains = configChains.filter( + (chain) => + multiProvider.getChainMetadata(chain).protocol === ProtocolType.Ethereum, + ); + + const targetChains = multiProvider.intersect( + ethereumConfigChains, + true, + ).intersection; + + console.info(`Start deploy to ${targetChains}`); + + const deployChain = async (chain: ChainName) => { + const signerAddress = await multiProvider.getSignerAddress(chain); + console.info( + chalk.gray.italic(`Deploying to ${chain} from ${signerAddress}`), + ); + + return runWithTimeout(deployer.chainTimeoutMs, async () => { + deployStatus[chain] = DeployStatus.INFLIGHT; + const contracts = await deployer.deployContracts(chain, configMap[chain]); + deployer.deployedContracts[chain] = { + ...deployer.deployedContracts[chain], + ...contracts, + }; + }) + .then(() => { + deployStatus[chain] = DeployStatus.SUCCESS; + const inFlightChains = Object.entries(deployStatus) + .filter(([_, status]) => status === DeployStatus.INFLIGHT) + .map(([chain, _]) => chain); + const numInFlight = inFlightChains.length; + console.info( + chalk.green.bold(`Successfully deployed contracts on ${chain}`), + chalk.blue.italic( + numInFlight === 0 + ? '\nAll chains deployed' + : `\n${numInFlight} chain${ + numInFlight === 1 ? '' : 's' + } still in-flight: ${inFlightChains.join(', ')}`, + ), + ); + }) + .catch((error) => { + deployStatus[chain] = DeployStatus.FAILURE; + console.error( + chalk.red.bold(`Deployment failed on ${chain}. ${error}`), + ); + }); + }; + + if (concurrentDeploy) { + await Promise.allSettled(targetChains.map(deployChain)); + } else { + for (const chain of targetChains) { + await deployChain(chain); } } - // Call the post-deploy hook to write artifacts - await postDeploy(deployer, cache); + return deployer.deployedContracts; } -export async function postDeploy( +async function postDeploy( deployer: HyperlaneDeployer, - cache: { - verification: string; - read: boolean; - write: boolean; - environment: DeployEnvironment; - module: Modules; - }, + cache: DeployCache, ) { if (cache.write) { - // TODO: dedupe deployedContracts with cachedAddresses const deployedAddresses = serializeContractsMap(deployer.deployedContracts); const cachedAddresses = deployer.cachedAddresses; const addresses = objMerge(deployedAddresses, cachedAddresses); @@ -94,7 +245,9 @@ export async function postDeploy( try { savedVerification = readJSONAtPath(cache.verification); } catch (e) { - console.error('Failed to load cached verification inputs'); + console.error( + chalk.red('Failed to load cached verification inputs. Error: ', e), + ); } // merge with existing cache of verification inputs diff --git a/typescript/sdk/src/deploy/HyperlaneDeployer.ts b/typescript/sdk/src/deploy/HyperlaneDeployer.ts index ef5acfc1b..8203c7919 100644 --- a/typescript/sdk/src/deploy/HyperlaneDeployer.ts +++ b/typescript/sdk/src/deploy/HyperlaneDeployer.ts @@ -73,10 +73,9 @@ export abstract class HyperlaneDeployer< public verificationInputs: ChainMap = {}; public cachedAddresses: HyperlaneAddressesMap = {}; public deployedContracts: HyperlaneContractsMap = {}; - public startingBlockNumbers: ChainMap = {}; protected logger: Logger; - protected chainTimeoutMs: number; + chainTimeoutMs: number; constructor( protected readonly multiProvider: MultiProvider, @@ -138,40 +137,41 @@ export abstract class HyperlaneDeployer< this.logger.debug(`Start deploy to ${targetChains}`); - const deployPromises = []; - for (const chain of targetChains) { + const failedChains: ChainName[] = []; + const deployChain = async (chain: ChainName) => { const signerUrl = await this.multiProvider.tryGetExplorerAddressUrl( chain, ); const signerAddress = await this.multiProvider.getSignerAddress(chain); const fromString = signerUrl || signerAddress; this.logger.info(`Deploying to ${chain} from ${fromString}`); - this.startingBlockNumbers[chain] = await this.multiProvider - .getProvider(chain) - .getBlockNumber(); - const deployPromise = runWithTimeout(this.chainTimeoutMs, async () => { + return runWithTimeout(this.chainTimeoutMs, async () => { const contracts = await this.deployContracts(chain, configMap[chain]); this.addDeployedContracts(chain, contracts); - this.logger.info(`Successfully deployed contracts on ${chain}`); - }); - if (this.options.concurrentDeploy) { - deployPromises.push(deployPromise); - } else { - await deployPromise; + }) + .then(() => { + this.logger.info(`Successfully deployed contracts on ${chain}`); + }) + .catch((error) => { + failedChains.push(chain); + this.logger.error(`Deployment failed on ${chain}. Error: ${error}`); + throw error; + }); + }; + + if (this.options.concurrentDeploy) { + await Promise.allSettled(targetChains.map(deployChain)); + } else { + for (const chain of targetChains) { + await deployChain(chain); } } - // Await all deploy promises. If concurrent deploy is not enabled, this will be a no-op. - const deployResults = await Promise.allSettled(deployPromises); - for (const [i, result] of deployResults.entries()) { - if (result.status === 'rejected') { - this.logger.error( - { chain: targetChains[i], error: result.reason }, - 'Deployment failed', - ); - throw result.reason; - } + if (failedChains.length > 0) { + throw new Error( + `Deployment failed on chains: ${failedChains.join(', ')}`, + ); } return this.deployedContracts; diff --git a/typescript/utils/src/async.ts b/typescript/utils/src/async.ts index c90f059b6..0aa4d7a8e 100644 --- a/typescript/utils/src/async.ts +++ b/typescript/utils/src/async.ts @@ -33,23 +33,26 @@ export function timeout( * @param timeoutMs How long to wait for the promise in milliseconds. * @param callback The callback to run. * @returns callback return value + * @throws Error if the timeout is reached before the callback completes */ export async function runWithTimeout( timeoutMs: number, callback: () => Promise, -): Promise { - let timeout: NodeJS.Timeout; - const timeoutProm = new Promise( - (_, reject) => - (timeout = setTimeout( - () => reject(new Error(`Timed out in ${timeoutMs}ms.`)), - timeoutMs, - )), - ); - const ret = await Promise.race([callback(), timeoutProm]); - // @ts-ignore timeout gets set immediately by the promise constructor - clearTimeout(timeout); - return ret; +): Promise { + let timeoutId: NodeJS.Timeout; + const timeoutProm = new Promise((_, reject) => { + timeoutId = setTimeout(() => { + reject(new Error(`Timed out in ${timeoutMs}ms.`)); + }, timeoutMs); + }); + + try { + const result = await Promise.race([callback(), timeoutProm]); + return result as T; + } finally { + // @ts-ignore timeout gets set immediately by the promise constructor + clearTimeout(timeoutId); + } } /** From ba15abef1793b04b50b3b33034c2d9b1ecc44722 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:36:45 -0400 Subject: [PATCH 077/224] feat: revamp testnet4 gasoracle/igp calculations (#4562) looking to resolve https://github.com/hyperlane-xyz/issues/issues/1374 more longer term feat: revamp testnet4 gasoracle/igp calculations - update print-gas-prices script to support testnets - update print-token-prices script to support testnets (requires https://github.com/hyperlane-xyz/hyperlane-registry/pull/228) - remove the common/rare/mythic nomenclature, use mainnet prices - refactor igp utils, reuse across both mainnet3 + testnet4 --- .changeset/popular-cars-burn.md | 2 +- .registryrc | 2 +- rust/main/config/mainnet_config.json | 4 +- rust/main/config/testnet_config.json | 42 +++++--- .../infra/config/environments/mainnet3/igp.ts | 50 ++------- .../config/environments/testnet4/chains.ts | 10 ++ .../environments/testnet4/gas-oracle.ts | 100 ------------------ .../environments/testnet4/gasPrices.json | 62 +++++++++++ .../infra/config/environments/testnet4/igp.ts | 41 +++---- .../environments/testnet4/tokenPrices.json | 17 +++ typescript/infra/scripts/print-gas-prices.ts | 19 +++- .../infra/scripts/print-token-prices.ts | 26 ++++- typescript/infra/src/config/gas-oracle.ts | 33 +++++- 13 files changed, 222 insertions(+), 186 deletions(-) delete mode 100644 typescript/infra/config/environments/testnet4/gas-oracle.ts create mode 100644 typescript/infra/config/environments/testnet4/gasPrices.json create mode 100644 typescript/infra/config/environments/testnet4/tokenPrices.json diff --git a/.changeset/popular-cars-burn.md b/.changeset/popular-cars-burn.md index e0faa46da..d402136d5 100644 --- a/.changeset/popular-cars-burn.md +++ b/.changeset/popular-cars-burn.md @@ -1,5 +1,5 @@ --- -"@hyperlane-xyz/sdk": patch +'@hyperlane-xyz/sdk': patch --- fix: warn on submodule metadata builder failures diff --git a/.registryrc b/.registryrc index 4a24b8cb7..9d73cdf16 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -v4.3.6 +d7dc44d8894962648a544686cdce4536ce9569ce diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index b3c01dccf..9a2257b5f 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -2758,10 +2758,10 @@ "solanamainnet": { "blockExplorers": [ { - "apiUrl": "https://explorer.solana.com?cluster=mainnet-beta", + "apiUrl": "https://solscan.io", "family": "other", "name": "Solana Explorer", - "url": "https://explorer.solana.com?cluster=mainnet-beta" + "url": "https://solscan.io" } ], "blocks": { diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index 3b9d19ac9..b5ac9c957 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -68,7 +68,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x3726EE36a2A9e11a40d1ffD7D9A1A16e0154cDA0", "staticMerkleRootWeightedMultisigIsmFactory": "0x374961678da5911083599314974B94094513F95c", - "staticMessageIdWeightedMultisigIsmFactory": "0x1Fa22d908f5a5E7F5429D9146E5a3740D8AC10d7" + "staticMessageIdWeightedMultisigIsmFactory": "0x1Fa22d908f5a5E7F5429D9146E5a3740D8AC10d7", + "gasCurrencyCoinGeckoId": "celo" }, "arbitrumsepolia": { "aggregationHook": "0xD2670EedcD21116c6F0B331Ce391eA4B3Bf1aB19", @@ -132,7 +133,8 @@ "testRecipient": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", "validatorAnnounce": "0x1b33611fCc073aB0737011d5512EF673Bff74962", "staticMerkleRootWeightedMultisigIsmFactory": "0x1aFD5191738d365C8079e955E4cEdDfe7e01C62d", - "staticMessageIdWeightedMultisigIsmFactory": "0xC81e6D1070aFA48DA4e4f35E744CC1aE43532a10" + "staticMessageIdWeightedMultisigIsmFactory": "0xC81e6D1070aFA48DA4e4f35E744CC1aE43532a10", + "gasCurrencyCoinGeckoId": "ethereum" }, "basesepolia": { "aggregationHook": "0xccA408a6A9A6dc405C3278647421eb4317466943", @@ -195,7 +197,8 @@ "testRecipient": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", "validatorAnnounce": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", "staticMerkleRootWeightedMultisigIsmFactory": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", - "staticMessageIdWeightedMultisigIsmFactory": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F" + "staticMessageIdWeightedMultisigIsmFactory": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "gasCurrencyCoinGeckoId": "ethereum" }, "bsctestnet": { "aggregationHook": "0x3d675bB93250Ab7603F40cbb9194bae210784627", @@ -266,7 +269,8 @@ }, "validatorAnnounce": "0xf09701B0a93210113D175461b6135a96773B5465", "staticMerkleRootWeightedMultisigIsmFactory": "0xCa152b249791Adf7A09C6c1bdbAb05e4A594966e", - "staticMessageIdWeightedMultisigIsmFactory": "0xaa80d23299861b7D7ab1bE665579029Ed9137BD1" + "staticMessageIdWeightedMultisigIsmFactory": "0xaa80d23299861b7D7ab1bE665579029Ed9137BD1", + "gasCurrencyCoinGeckoId": "binancecoin" }, "connextsepolia": { "aggregationHook": "0x331eb40963dc11F5BB271308c42d97ac6e41F124", @@ -327,7 +331,8 @@ "testRecipient": "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2", "validatorAnnounce": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", "staticMerkleRootWeightedMultisigIsmFactory": "0x8584590ad637C61C7cDF72eFF3381Ee1c3D1bC8E", - "staticMessageIdWeightedMultisigIsmFactory": "0xcCB305B1f21e5FbC85D1DD7Be5cd8d5bf5B7f863" + "staticMessageIdWeightedMultisigIsmFactory": "0xcCB305B1f21e5FbC85D1DD7Be5cd8d5bf5B7f863", + "gasCurrencyCoinGeckoId": "ethereum" }, "eclipsetestnet": { "blocks": { @@ -362,7 +367,8 @@ "http": "https://testnet.dev2.eclipsenetwork.xyz" } ], - "validatorAnnounce": "8qNYSi9EP1xSnRjtMpyof88A26GBbdcrsa61uSaHiwx3" + "validatorAnnounce": "8qNYSi9EP1xSnRjtMpyof88A26GBbdcrsa61uSaHiwx3", + "gasCurrencyCoinGeckoId": "ethereum" }, "ecotestnet": { "aggregationHook": "0xccA408a6A9A6dc405C3278647421eb4317466943", @@ -422,7 +428,8 @@ "testRecipient": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", "validatorAnnounce": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", "staticMerkleRootWeightedMultisigIsmFactory": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "staticMessageIdWeightedMultisigIsmFactory": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E" + "staticMessageIdWeightedMultisigIsmFactory": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", + "gasCurrencyCoinGeckoId": "ethereum" }, "fuji": { "aggregationHook": "0x8E9b4006171c6B75111823e7545Ee5400CEce0B3", @@ -489,7 +496,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x4f7179A691F8a684f56cF7Fed65171877d30739a", "staticMerkleRootWeightedMultisigIsmFactory": "0xff93F32997Ac5450995121385aCE96b184efe89E", - "staticMessageIdWeightedMultisigIsmFactory": "0x8eAB8cBb9037e818C321f675c0bc2EA4649003CF" + "staticMessageIdWeightedMultisigIsmFactory": "0x8eAB8cBb9037e818C321f675c0bc2EA4649003CF", + "gasCurrencyCoinGeckoId": "avalanche-2" }, "holesky": { "aggregationHook": "0xb1FfD51f03c69A0a3e5AFEBDE639752DB1d56bc9", @@ -549,7 +557,8 @@ "testRecipient": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", "validatorAnnounce": "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2", "staticMerkleRootWeightedMultisigIsmFactory": "0xFb55597F07417b08195Ba674f4dd58aeC9B89FBB", - "staticMessageIdWeightedMultisigIsmFactory": "0x0E18b28D98C2efDb59252c021320F203305b1B66" + "staticMessageIdWeightedMultisigIsmFactory": "0x0E18b28D98C2efDb59252c021320F203305b1B66", + "gasCurrencyCoinGeckoId": "ethereum" }, "optimismsepolia": { "aggregationHook": "0xccA408a6A9A6dc405C3278647421eb4317466943", @@ -744,7 +753,8 @@ "testRecipient": "0x04438ef7622f5412f82915F59caD4f704C61eA48", "validatorAnnounce": "0x11918DC33E067C5DA83EEF58E50F856398b8Df4C", "staticMerkleRootWeightedMultisigIsmFactory": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", - "staticMessageIdWeightedMultisigIsmFactory": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F" + "staticMessageIdWeightedMultisigIsmFactory": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "gasCurrencyCoinGeckoId": "polygon-ecosystem-token" }, "scrollsepolia": { "aggregationHook": "0x7b63Aa270335F8896717c2A809205F4b650E4268", @@ -823,7 +833,8 @@ }, "validatorAnnounce": "0x527768930D889662Fe7ACF64294871e86e4C2381", "staticMerkleRootWeightedMultisigIsmFactory": "0x339B46496D60b1b6B42e9715DeD8B3D2154dA0Bb", - "staticMessageIdWeightedMultisigIsmFactory": "0x63dFf524F1c7361f4F1bf07D658Bf7f2d5Dd5B20" + "staticMessageIdWeightedMultisigIsmFactory": "0x63dFf524F1c7361f4F1bf07D658Bf7f2d5Dd5B20", + "gasCurrencyCoinGeckoId": "ethereum" }, "sepolia": { "aggregationHook": "0xe3147d5618f5e2e100690B50ec923009a4cde14A", @@ -894,7 +905,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0xE6105C59480a1B7DD3E4f28153aFdbE12F4CfCD9", "staticMerkleRootWeightedMultisigIsmFactory": "0x4afB48e864d308409d0D80E98fB7d5d6aA5b245f", - "staticMessageIdWeightedMultisigIsmFactory": "0x196Ce28ED1Afdf015849ddEE82F03a903Bee9E94" + "staticMessageIdWeightedMultisigIsmFactory": "0x196Ce28ED1Afdf015849ddEE82F03a903Bee9E94", + "gasCurrencyCoinGeckoId": "ethereum" }, "solanatestnet": { "blockExplorers": [ @@ -938,7 +950,8 @@ "http": "https://api.testnet.solana.com" } ], - "validatorAnnounce": "8qNYSi9EP1xSnRjtMpyof88A26GBbdcrsa61uSaHiwx3" + "validatorAnnounce": "8qNYSi9EP1xSnRjtMpyof88A26GBbdcrsa61uSaHiwx3", + "gasCurrencyCoinGeckoId": "solana" }, "superpositiontestnet": { "aggregationHook": "0x331eb40963dc11F5BB271308c42d97ac6e41F124", @@ -995,7 +1008,8 @@ "testRecipient": "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2", "validatorAnnounce": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", "staticMerkleRootWeightedMultisigIsmFactory": "0xE67CfA164cDa449Ae38a0a09391eF6bCDf8e4e2c", - "staticMessageIdWeightedMultisigIsmFactory": "0x867f2089D09903f208AeCac84E599B90E5a4A821" + "staticMessageIdWeightedMultisigIsmFactory": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "gasCurrencyCoinGeckoId": "superposition" } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/mainnet3/igp.ts b/typescript/infra/config/environments/mainnet3/igp.ts index ca167f356..7275cbe02 100644 --- a/typescript/infra/config/environments/mainnet3/igp.ts +++ b/typescript/infra/config/environments/mainnet3/igp.ts @@ -1,20 +1,11 @@ -import { BigNumber, ethers } from 'ethers'; - -import { - ChainMap, - ChainName, - HookType, - IgpConfig, - TOKEN_EXCHANGE_RATE_DECIMALS, - defaultMultisigConfigs, - multisigIsmVerificationCost, -} from '@hyperlane-xyz/sdk'; +import { ChainMap, ChainName, HookType, IgpConfig } from '@hyperlane-xyz/sdk'; import { exclude, objMap } from '@hyperlane-xyz/utils'; import { AllStorageGasOracleConfigs, getAllStorageGasOracleConfigs, getTokenExchangeRateFromValues, + remoteOverhead, } from '../../../src/config/gas-oracle.js'; import { ethereumChainNames } from './chains.js'; @@ -25,43 +16,22 @@ import rawTokenPrices from './tokenPrices.json'; const tokenPrices: ChainMap = rawTokenPrices; -const FOREIGN_DEFAULT_OVERHEAD = 600_000; // cosmwasm warp route somewhat arbitrarily chosen - -function remoteOverhead(remote: ChainName) { - let overhead = ethereumChainNames.includes(remote as any) - ? multisigIsmVerificationCost( - defaultMultisigConfigs[remote].threshold, - defaultMultisigConfigs[remote].validators.length, - ) - : FOREIGN_DEFAULT_OVERHEAD; // non-ethereum overhead - if (remote === 'moonbeam') { - // Moonbeam has (roughly) 4x'd their gas costs, some context in https://discord.com/channels/935678348330434570/1287816893553705041 +const remoteOverheadWithOverrides = (chain: ChainName) => { + let overhead = remoteOverhead(chain, ethereumChainNames); + if (chain === 'moonbeam') { overhead *= 4; } return overhead; -} - -// Gets the exchange rate of the remote quoted in local tokens -function getTokenExchangeRate(local: ChainName, remote: ChainName): BigNumber { - const localValue = ethers.utils.parseUnits( - tokenPrices[local], - TOKEN_EXCHANGE_RATE_DECIMALS, - ); - const remoteValue = ethers.utils.parseUnits( - tokenPrices[remote], - TOKEN_EXCHANGE_RATE_DECIMALS, - ); - - return getTokenExchangeRateFromValues(local, localValue, remote, remoteValue); -} +}; const storageGasOracleConfig: AllStorageGasOracleConfigs = getAllStorageGasOracleConfigs( supportedChainNames, gasPrices, - getTokenExchangeRate, + (local, remote) => + getTokenExchangeRateFromValues(local, remote, tokenPrices), (local) => parseFloat(tokenPrices[local]), - (local) => remoteOverhead(local), + remoteOverheadWithOverrides, ); export const igp: ChainMap = objMap( @@ -79,7 +49,7 @@ export const igp: ChainMap = objMap( overhead: Object.fromEntries( exclude(local, supportedChainNames).map((remote) => [ remote, - remoteOverhead(remote), + remoteOverhead(remote, ethereumChainNames), ]), ), oracleConfig: storageGasOracleConfig[local], diff --git a/typescript/infra/config/environments/testnet4/chains.ts b/typescript/infra/config/environments/testnet4/chains.ts index 4d6923f3f..61073930f 100644 --- a/typescript/infra/config/environments/testnet4/chains.ts +++ b/typescript/infra/config/environments/testnet4/chains.ts @@ -1,5 +1,7 @@ +import { IRegistry } from '@hyperlane-xyz/registry'; import { ChainMap, ChainMetadata } from '@hyperlane-xyz/sdk'; +import { getRegistryForEnvironment } from '../../../src/config/chain.js'; import { isEthereumProtocolChain } from '../../../src/utils/utils.js'; import { supportedChainNames } from './supportedChainNames.js'; @@ -22,3 +24,11 @@ export const chainMetadataOverrides: ChainMap> = { }, }, }; + +export const getRegistry = async (useSecrets = true): Promise => + getRegistryForEnvironment( + environment, + supportedChainNames, + chainMetadataOverrides, + useSecrets, + ); diff --git a/typescript/infra/config/environments/testnet4/gas-oracle.ts b/typescript/infra/config/environments/testnet4/gas-oracle.ts deleted file mode 100644 index b09184c44..000000000 --- a/typescript/infra/config/environments/testnet4/gas-oracle.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { BigNumber, ethers } from 'ethers'; - -import { ChainName, TOKEN_EXCHANGE_RATE_DECIMALS } from '@hyperlane-xyz/sdk'; -import { objMap } from '@hyperlane-xyz/utils'; - -import { - AllStorageGasOracleConfigs, - getAllStorageGasOracleConfigs, - getTokenExchangeRateFromValues, -} from '../../../src/config/gas-oracle.js'; - -import { ethereumChainNames } from './chains.js'; -import { testnet4SupportedChainNames } from './supportedChainNames.js'; - -// Taken by looking at each testnet and overestimating gas prices -const gasPrices: Record< - (typeof testnet4SupportedChainNames)[number], - BigNumber -> = { - alfajores: ethers.utils.parseUnits('10', 'gwei'), - arbitrumsepolia: ethers.utils.parseUnits('0.5', 'gwei'), - basesepolia: ethers.utils.parseUnits('0.1', 'gwei'), - bsctestnet: ethers.utils.parseUnits('15', 'gwei'), - connextsepolia: ethers.utils.parseUnits('0.5', 'gwei'), - ecotestnet: ethers.utils.parseUnits('0.001', 'gwei'), - eclipsetestnet: ethers.BigNumber.from('28'), - fuji: ethers.utils.parseUnits('30', 'gwei'), - holesky: ethers.utils.parseUnits('10', 'gwei'), - optimismsepolia: ethers.utils.parseUnits('0.5', 'gwei'), - // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" - // plumetestnet: ethers.utils.parseUnits('0.01', 'gwei'), - polygonamoy: ethers.utils.parseUnits('100', 'gwei'), - scrollsepolia: ethers.utils.parseUnits('0.5', 'gwei'), - sepolia: ethers.utils.parseUnits('5', 'gwei'), - solanatestnet: ethers.BigNumber.from('28'), - superpositiontestnet: ethers.utils.parseUnits('0.001', 'gwei'), -}; - -// Used to categorize rarity of testnet tokens & approximate exchange rates. -// Unashamedly borrowed from Fortnite -enum Rarity { - Common, - Rare, - Mythic, -} - -// "Value" of the testnet tokens with 10 decimals of precision. -// Imagine these as quoted in USD -const RARITY_APPROXIMATE_VALUE: Record = { - [Rarity.Common]: ethers.utils.parseUnits('0.5', TOKEN_EXCHANGE_RATE_DECIMALS), - [Rarity.Rare]: ethers.utils.parseUnits('1', TOKEN_EXCHANGE_RATE_DECIMALS), - [Rarity.Mythic]: ethers.utils.parseUnits('5', TOKEN_EXCHANGE_RATE_DECIMALS), -}; - -const chainTokenRarity: Record< - (typeof testnet4SupportedChainNames)[number], - Rarity -> = { - alfajores: Rarity.Common, - arbitrumsepolia: Rarity.Common, - basesepolia: Rarity.Common, - bsctestnet: Rarity.Rare, - connextsepolia: Rarity.Common, - ecotestnet: Rarity.Rare, - eclipsetestnet: Rarity.Common, - fuji: Rarity.Rare, - holesky: Rarity.Common, - optimismsepolia: Rarity.Common, - // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" - // plumetestnet: Rarity.Common, - polygonamoy: Rarity.Rare, - scrollsepolia: Rarity.Rare, - sepolia: Rarity.Mythic, - solanatestnet: Rarity.Common, - superpositiontestnet: Rarity.Common, -}; - -// Gets the "value" of a testnet chain -function getApproximateValue(chain: ChainName): BigNumber { - const rarity = chainTokenRarity[chain as keyof typeof chainTokenRarity]; - return RARITY_APPROXIMATE_VALUE[rarity]; -} - -// Gets the exchange rate of the remote quoted in local tokens -function getTokenExchangeRate(local: ChainName, remote: ChainName): BigNumber { - const localValue = getApproximateValue(local); - const remoteValue = getApproximateValue(remote); - - return getTokenExchangeRateFromValues(local, localValue, remote, remoteValue); -} - -export const storageGasOracleConfig: AllStorageGasOracleConfigs = - getAllStorageGasOracleConfigs( - ethereumChainNames, - objMap(gasPrices, (_, gasPrice) => ({ - amount: gasPrice.toString(), - decimals: 1, - })), - getTokenExchangeRate, - ); diff --git a/typescript/infra/config/environments/testnet4/gasPrices.json b/typescript/infra/config/environments/testnet4/gasPrices.json new file mode 100644 index 000000000..0c8369fb3 --- /dev/null +++ b/typescript/infra/config/environments/testnet4/gasPrices.json @@ -0,0 +1,62 @@ +{ + "alfajores": { + "amount": "50.0", + "decimals": 9 + }, + "arbitrumsepolia": { + "amount": "0.1", + "decimals": 9 + }, + "basesepolia": { + "amount": "0.001000263", + "decimals": 9 + }, + "bsctestnet": { + "amount": "5.532492", + "decimals": 9 + }, + "connextsepolia": { + "amount": "0.1", + "decimals": 9 + }, + "ecotestnet": { + "amount": "0.001000252", + "decimals": 9 + }, + "eclipsetestnet": { + "amount": "0.001", + "decimals": 9 + }, + "fuji": { + "amount": "25.000000001", + "decimals": 9 + }, + "holesky": { + "amount": "0.191141087", + "decimals": 9 + }, + "optimismsepolia": { + "amount": "0.001000327", + "decimals": 9 + }, + "polygonamoy": { + "amount": "31.092000015", + "decimals": 9 + }, + "scrollsepolia": { + "amount": "0.059465192", + "decimals": 9 + }, + "sepolia": { + "amount": "7.101334009", + "decimals": 9 + }, + "solanatestnet": { + "amount": "0.001", + "decimals": 9 + }, + "superpositiontestnet": { + "amount": "0.01", + "decimals": 9 + } +} diff --git a/typescript/infra/config/environments/testnet4/igp.ts b/typescript/infra/config/environments/testnet4/igp.ts index a564a3360..92d0506d1 100644 --- a/typescript/infra/config/environments/testnet4/igp.ts +++ b/typescript/infra/config/environments/testnet4/igp.ts @@ -1,27 +1,30 @@ -import { - ChainMap, - ChainName, - HookType, - IgpConfig, - defaultMultisigConfigs, - multisigIsmVerificationCost, -} from '@hyperlane-xyz/sdk'; +import { ChainMap, HookType, IgpConfig } from '@hyperlane-xyz/sdk'; import { Address, exclude, objMap } from '@hyperlane-xyz/utils'; -import { isEthereumProtocolChain } from '../../../src/utils/utils.js'; +import { + AllStorageGasOracleConfigs, + getAllStorageGasOracleConfigs, + getTokenExchangeRateFromValues, + remoteOverhead, +} from '../../../src/config/gas-oracle.js'; -import { storageGasOracleConfig } from './gas-oracle.js'; +import { ethereumChainNames } from './chains.js'; +import gasPrices from './gasPrices.json'; import { owners } from './owners.js'; import { supportedChainNames } from './supportedChainNames.js'; +import rawTokenPrices from './tokenPrices.json'; + +const tokenPrices: ChainMap = rawTokenPrices; -const FOREIGN_DEFAULT_OVERHEAD = 600_000; // cosmwasm warp route somewhat arbitrarily chosen -const remoteOverhead = (remote: ChainName) => - supportedChainNames.filter(isEthereumProtocolChain).includes(remote as any) - ? multisigIsmVerificationCost( - defaultMultisigConfigs[remote].threshold, - defaultMultisigConfigs[remote].validators.length, - ) - : FOREIGN_DEFAULT_OVERHEAD; // non-ethereum overhead +export const storageGasOracleConfig: AllStorageGasOracleConfigs = + getAllStorageGasOracleConfigs( + supportedChainNames, + gasPrices, + (local, remote) => + getTokenExchangeRateFromValues(local, remote, tokenPrices), + (local) => parseFloat(tokenPrices[local]), + (local) => remoteOverhead(local, ethereumChainNames), + ); export const igp: ChainMap = objMap( owners, @@ -35,7 +38,7 @@ export const igp: ChainMap = objMap( overhead: Object.fromEntries( exclude(chain, supportedChainNames).map((remote) => [ remote, - remoteOverhead(remote), + remoteOverhead(remote, ethereumChainNames), ]), ), }; diff --git a/typescript/infra/config/environments/testnet4/tokenPrices.json b/typescript/infra/config/environments/testnet4/tokenPrices.json new file mode 100644 index 000000000..8f2f1eb53 --- /dev/null +++ b/typescript/infra/config/environments/testnet4/tokenPrices.json @@ -0,0 +1,17 @@ +{ + "alfajores": "0.538515", + "arbitrumsepolia": "2651.43", + "basesepolia": "2651.43", + "bsctestnet": "608.49", + "connextsepolia": "2651.43", + "ecotestnet": "2651.43", + "eclipsetestnet": "2651.43", + "fuji": "27.33", + "holesky": "2651.43", + "optimismsepolia": "2651.43", + "polygonamoy": "0.405534", + "scrollsepolia": "2651.43", + "sepolia": "2651.43", + "solanatestnet": "144.13", + "superpositiontestnet": "0.999824" +} diff --git a/typescript/infra/scripts/print-gas-prices.ts b/typescript/infra/scripts/print-gas-prices.ts index 4f94dd26a..805122ad1 100644 --- a/typescript/infra/scripts/print-gas-prices.ts +++ b/typescript/infra/scripts/print-gas-prices.ts @@ -8,19 +8,34 @@ import { ProtocolType } from '@hyperlane-xyz/utils'; // to avoid circular dependencies. import { getRegistry as getMainnet3Registry } from '../config/environments/mainnet3/chains.js'; import { supportedChainNames as mainnet3SupportedChainNames } from '../config/environments/mainnet3/supportedChainNames.js'; +import { getRegistry as getTestnet4Registry } from '../config/environments/testnet4/chains.js'; +import { supportedChainNames as testnet4SupportedChainNames } from '../config/environments/testnet4/supportedChainNames.js'; import { GasPriceConfig, getCosmosChainGasPrice, } from '../src/config/gas-oracle.js'; +import { getArgs } from './agent-utils.js'; + async function main() { - const registry = await getMainnet3Registry(); + const { environment } = await getArgs().argv; + const { registry, supportedChainNames } = + environment === 'mainnet3' + ? { + registry: await getMainnet3Registry(), + supportedChainNames: mainnet3SupportedChainNames, + } + : { + registry: await getTestnet4Registry(), + supportedChainNames: testnet4SupportedChainNames, + }; + const chainMetadata = await registry.getMetadata(); const mpp = new MultiProtocolProvider(chainMetadata); const prices: ChainMap = Object.fromEntries( await Promise.all( - mainnet3SupportedChainNames.map(async (chain) => [ + supportedChainNames.map(async (chain) => [ chain, await getGasPrice(mpp, chain), ]), diff --git a/typescript/infra/scripts/print-token-prices.ts b/typescript/infra/scripts/print-token-prices.ts index d2d2a941c..5a3e848eb 100644 --- a/typescript/infra/scripts/print-token-prices.ts +++ b/typescript/infra/scripts/print-token-prices.ts @@ -1,22 +1,38 @@ import { ChainMetadata } from '@hyperlane-xyz/sdk'; import { objMap, pick } from '@hyperlane-xyz/utils'; -// Intentionally circumvent `mainnet3/index.ts` and `getEnvironmentConfig('mainnet3')` +// Intentionally circumvent `{mainnet3,testnet4}/index.ts` and `getEnvironmentConfig({'mainnet3','testnet4'})` // to avoid circular dependencies. import { getRegistry as getMainnet3Registry } from '../config/environments/mainnet3/chains.js'; -import { mainnet3SupportedChainNames } from '../config/environments/mainnet3/supportedChainNames.js'; +import { supportedChainNames as mainnet3SupportedChainNames } from '../config/environments/mainnet3/supportedChainNames.js'; +import { getRegistry as getTestnet4Registry } from '../config/environments/testnet4/chains.js'; +import { supportedChainNames as testnet4SupportedChainNames } from '../config/environments/testnet4/supportedChainNames.js'; + +import { getArgs } from './agent-utils.js'; const CURRENCY = 'usd'; async function main() { - const registry = await getMainnet3Registry(); + const { environment } = await getArgs().argv; + + const { registry, supportedChainNames } = + environment === 'mainnet3' + ? { + registry: await getMainnet3Registry(), + supportedChainNames: mainnet3SupportedChainNames, + } + : { + registry: await getTestnet4Registry(), + supportedChainNames: testnet4SupportedChainNames, + }; + const chainMetadata = await registry.getMetadata(); const metadata = pick( chainMetadata as Record< - (typeof mainnet3SupportedChainNames)[number], + (typeof supportedChainNames)[number], ChainMetadata >, - [...mainnet3SupportedChainNames], + [...supportedChainNames], ); const ids = objMap( diff --git a/typescript/infra/src/config/gas-oracle.ts b/typescript/infra/src/config/gas-oracle.ts index acc232c5a..8cbc6194c 100644 --- a/typescript/infra/src/config/gas-oracle.ts +++ b/typescript/infra/src/config/gas-oracle.ts @@ -5,8 +5,11 @@ import { ChainMap, ChainName, StorageGasOracleConfig as DestinationOracleConfig, + TOKEN_EXCHANGE_RATE_DECIMALS, TOKEN_EXCHANGE_RATE_SCALE, + defaultMultisigConfigs, getCosmosRegistryChain, + multisigIsmVerificationCost, } from '@hyperlane-xyz/sdk'; import { ProtocolType, convertDecimals } from '@hyperlane-xyz/utils'; @@ -180,6 +183,22 @@ function getUsdQuote( return quoteUsd; } +// cosmwasm warp route somewhat arbitrarily chosen +const FOREIGN_DEFAULT_OVERHEAD = 600_000; + +// Overhead for interchain messaging +export function remoteOverhead( + remote: ChainName, + ethereumChainNames: ChainName[], +): number { + return ethereumChainNames.includes(remote as any) + ? multisigIsmVerificationCost( + defaultMultisigConfigs[remote].threshold, + defaultMultisigConfigs[remote].validators.length, + ) + : FOREIGN_DEFAULT_OVERHEAD; // non-ethereum overhead +} + // Gets the StorageGasOracleConfig for each local chain export function getAllStorageGasOracleConfigs( chainNames: ChainName[], @@ -204,12 +223,21 @@ export function getAllStorageGasOracleConfigs( }, {}) as AllStorageGasOracleConfigs; } +// Gets the exchange rate of the remote quoted in local tokens export function getTokenExchangeRateFromValues( local: ChainName, - localValue: BigNumber, remote: ChainName, - remoteValue: BigNumber, + tokenPrices: ChainMap, ): BigNumber { + const localValue = ethers.utils.parseUnits( + tokenPrices[local], + TOKEN_EXCHANGE_RATE_DECIMALS, + ); + const remoteValue = ethers.utils.parseUnits( + tokenPrices[remote], + TOKEN_EXCHANGE_RATE_DECIMALS, + ); + // This does not yet account for decimals! let exchangeRate = remoteValue.mul(TOKEN_EXCHANGE_RATE_SCALE).div(localValue); // Apply the premium @@ -224,6 +252,7 @@ export function getTokenExchangeRateFromValues( ); } +// Gets the gas price for a Cosmos chain export async function getCosmosChainGasPrice( chain: ChainName, ): Promise { From 0a22e96553b7dbdaf8454cfd5f9e6290abd85d78 Mon Sep 17 00:00:00 2001 From: Nam Chu Hoai Date: Wed, 25 Sep 2024 12:06:26 -0400 Subject: [PATCH 078/224] chore: don't ask for api key if it already exists (#4549) ### Description CLI will ask for API keys even if your (local) registry already includes the API key. This PR fixes that. Can't say i love the current code setup, it seems to me that it should be more like a pass on the registry and filter chains that don't have api keys, prompt for the api key and then persist that in the registry if its writable. But since i have so little context, kept it mostly this way to accomplish the desired product experience. --- typescript/cli/src/context/context.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/typescript/cli/src/context/context.ts b/typescript/cli/src/context/context.ts index d96c8a22b..30390f4b4 100644 --- a/typescript/cli/src/context/context.ts +++ b/typescript/cli/src/context/context.ts @@ -195,6 +195,10 @@ export async function getOrRequestApiKeys( const apiKeys: ChainMap = {}; for (const chain of chains) { + if (chainMetadata[chain]?.blockExplorers?.[0]?.apiKey) { + apiKeys[chain] = chainMetadata[chain]!.blockExplorers![0]!.apiKey!; + continue; + } const wantApiKey = await confirm({ default: false, message: `Do you want to use an API key to verify on this (${chain}) chain's block explorer`, From 8fee6aedc5e13ec1460ce3e3d8b216275299d6fe Mon Sep 17 00:00:00 2001 From: Roman V Date: Wed, 25 Sep 2024 18:24:15 +0200 Subject: [PATCH 079/224] fix: GCS correctly splitting storage location into bucket and folder (if present) (#4539) ### Description Previously Checkpoint Syncer wasn't correctly parsing the storage location string. If no folder was provided, it treated the object name as folder, e.g. reading `gs://bucket-name/gcsLatestIndexKey` initialized StorageClient with bucket `bucket-name` and folder `gcsLatestIndexKey`. This was due to incorrect logic for splitting the string by `/` that expected a folder to be present. In this PR I fixed this logic, treating a location with only one `/` as _bucket/object_ and with two `/`s as _bucket/folder/object_. ### Backward compatibility Yes ### Testing Manual --------- Co-authored-by: Trevor Porter --- .../src/settings/checkpoint_syncer.rs | 24 +++++++++++-------- .../main/hyperlane-base/tests/chain_config.rs | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs b/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs index cb4fa1c8d..81cf74985 100644 --- a/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs +++ b/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs @@ -73,21 +73,25 @@ impl FromStr for CheckpointSyncerConf { "gs" => { let service_account_key = env::var(GCS_SERVICE_ACCOUNT_KEY).ok(); let user_secrets = env::var(GCS_USER_SECRET).ok(); - if let Some(ind) = suffix.find('/') { - let (bucket, folder) = suffix.split_at(ind); - Ok(Self::Gcs { + let url_components = suffix.split('/').collect::>(); + let (bucket, folder): (&str, Option) = match url_components.len() { + 2 => Ok((url_components[0], None)), + 3 => Ok((url_components[0], Some(url_components[1].to_owned()))), + _ => Err(eyre!("Error parsing storage location; could not split bucket and folder ({suffix})")) + }?; + match folder { + None => Ok(CheckpointSyncerConf::Gcs { bucket: bucket.into(), - folder: Some(folder.into()), + folder: None, service_account_key, user_secrets, - }) - } else { - Ok(Self::Gcs { - bucket: suffix.into(), - folder: None, + }), + Some(folder) => Ok(CheckpointSyncerConf::Gcs { + bucket: bucket.into(), + folder: Some(folder), service_account_key, user_secrets, - }) + }), } } _ => Err(eyre!("Unknown storage location prefix `{prefix}`")), diff --git a/rust/main/hyperlane-base/tests/chain_config.rs b/rust/main/hyperlane-base/tests/chain_config.rs index f0695820c..9559280c1 100644 --- a/rust/main/hyperlane-base/tests/chain_config.rs +++ b/rust/main/hyperlane-base/tests/chain_config.rs @@ -92,7 +92,7 @@ fn chain_name_domain_records() -> BTreeSet { .flat_map(|x: &Settings| { x.chains.values().map(|v| ChainCoordinate { name: v.domain.name().into(), - domain: (&v.domain).try_into().expect("Invalid domain id"), + domain: (&v.domain).into(), }) }) .collect() From a513e1b51f03ccb1f824809e1cf044c630bcb5ad Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Wed, 25 Sep 2024 13:02:23 -0400 Subject: [PATCH 080/224] fix: override default with merkle hook for self relay (#4567) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description - Race condition in CLI `send message --relay` ### Related issues - Related to https://github.com/hyperlane-xyz/v3-docs/issues/174 ### Backward compatibility Yes ### Testing Manual Screenshot 2024-09-24 at 3 15 41 PM --- .changeset/bright-rings-jam.md | 5 +++++ typescript/cli/src/send/message.ts | 9 ++------- typescript/cli/src/send/transfer.ts | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 .changeset/bright-rings-jam.md diff --git a/.changeset/bright-rings-jam.md b/.changeset/bright-rings-jam.md new file mode 100644 index 000000000..d84431d78 --- /dev/null +++ b/.changeset/bright-rings-jam.md @@ -0,0 +1,5 @@ +--- +"@hyperlane-xyz/cli": patch +--- + +Override default with merkle hook for self relay diff --git a/typescript/cli/src/send/message.ts b/typescript/cli/src/send/message.ts index eaa69dcce..430d3b7bc 100644 --- a/typescript/cli/src/send/message.ts +++ b/typescript/cli/src/send/message.ts @@ -84,11 +84,6 @@ async function executeDelivery({ const chainAddresses = await registry.getAddresses(); const core = HyperlaneCore.fromAddressesMap(chainAddresses, multiProvider); - const hook = chainAddresses[origin]?.customHook; - if (hook) { - logBlue(`Using custom hook ${hook} for ${origin} -> ${destination}`); - } - try { const recipient = chainAddresses[destination].testRecipient; if (!recipient) { @@ -102,8 +97,8 @@ async function executeDelivery({ destination, formattedRecipient, messageBody, - hook, - undefined, + // override the the default hook (with IGP) for self-relay to avoid race condition with the production relayer + selfRelay ? chainAddresses[origin].merkleTreeHook : undefined, ); logBlue(`Sent message from ${origin} to ${recipient} on ${destination}.`); logBlue(`Message ID: ${message.id}`); diff --git a/typescript/cli/src/send/transfer.ts b/typescript/cli/src/send/transfer.ts index 0bfb4aa55..a2f56ef29 100644 --- a/typescript/cli/src/send/transfer.ts +++ b/typescript/cli/src/send/transfer.ts @@ -144,6 +144,7 @@ async function executeDelivery({ throw new Error('Error validating transfer'); } + // TODO: override hook address for self-relay const transferTxs = await warpCore.getTransferRemoteTxs({ originTokenAmount: new TokenAmount(amount, token), destination, From fd536a79a96bc078a657bdc02d27d2ae87f1eae2 Mon Sep 17 00:00:00 2001 From: J M Rossy Date: Wed, 25 Sep 2024 14:57:14 -0400 Subject: [PATCH 081/224] feat: Include priority fee instruction with SVM warp transfers (#4568) ### Description Update adapters to include priority fee instruction with sealevel collateral warp transfers ### Drive-by changes Hoist const to top of sealevel adapter file ### Related issues Fixes https://github.com/hyperlane-xyz/hyperlane-warp-ui-template/issues/264 ### Backward compatibility Yes ### Testing Tested in Warp UI --- .changeset/smooth-clocks-sin.md | 5 ++ .../token/adapters/SealevelTokenAdapter.ts | 83 ++++++++++++++++--- 2 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 .changeset/smooth-clocks-sin.md diff --git a/.changeset/smooth-clocks-sin.md b/.changeset/smooth-clocks-sin.md new file mode 100644 index 000000000..d6cb506b5 --- /dev/null +++ b/.changeset/smooth-clocks-sin.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Include priority fee instruction with SVM warp transfers diff --git a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts index 29ea30b24..0d5b99e13 100644 --- a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts @@ -20,6 +20,7 @@ import { Domain, addressToBytes, eqAddress, + median, } from '@hyperlane-xyz/utils'; import { BaseSealevelAdapter } from '../../app/MultiProtocolApp.js'; @@ -51,6 +52,29 @@ import { const NON_EXISTENT_ACCOUNT_ERROR = 'could not find account'; +/** + * The compute limit to set for the transfer remote instruction. + * This is typically around ~160k, but can be higher depending on + * the index in the merkle tree, which can result in more moderately + * more expensive merkle tree insertion. + * Because a higher compute limit doesn't increase the fee for a transaction, + * we generously request 1M units. + */ +const TRANSFER_REMOTE_COMPUTE_LIMIT = 1_000_000; + +/** + * The factor by which to multiply the median prioritization fee + * instruction added to transfer transactions. + */ +const PRIORITY_FEE_PADDING_FACTOR = 2; + +/** + * The minimum priority fee to use if the median fee is + * unavailable or too low, set in micro-lamports. + * 100,000 * 1e-6 * 1,000,000 (compute unit limit) / 1e9 == 0.0001 SOL + */ +const MINIMUM_PRIORITY_FEE = 100_000; + // Interacts with native currencies export class SealevelNativeTokenAdapter extends BaseSealevelAdapter @@ -173,14 +197,6 @@ interface HypTokenAddresses { mailbox: Address; } -// The compute limit to set for the transfer remote instruction. -// This is typically around ~160k, but can be higher depending on -// the index in the merkle tree, which can result in more moderately -// more expensive merkle tree insertion. -// Because a higher compute limit doesn't increase the fee for a transaction, -// we generously request 1M units. -const TRANSFER_REMOTE_COMPUTE_LIMIT = 1_000_000; - export abstract class SealevelHypTokenAdapter extends SealevelTokenAdapter implements IHypTokenAdapter @@ -297,11 +313,17 @@ export abstract class SealevelHypTokenAdapter }); const setComputeLimitInstruction = ComputeBudgetProgram.setComputeUnitLimit( - { - units: TRANSFER_REMOTE_COMPUTE_LIMIT, - }, + { units: TRANSFER_REMOTE_COMPUTE_LIMIT }, ); + // For more info about priority fees, see: + // https://solanacookbook.com/references/basic-transactions.html#how-to-change-compute-budget-fee-priority-for-a-transaction + // https://docs.phantom.app/developer-powertools/solana-priority-fees + // https://www.helius.dev/blog/priority-fees-understanding-solanas-transaction-fee-mechanics + const setPriorityFeeInstruction = ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: (await this.getMedianPriorityFee()) || 0, + }); + const recentBlockhash = ( await this.getProvider().getLatestBlockhash('finalized') ).blockhash; @@ -313,6 +335,7 @@ export abstract class SealevelHypTokenAdapter recentBlockhash, }) .add(setComputeLimitInstruction) + .add(setPriorityFeeInstruction) .add(transferRemoteInstruction); tx.partialSign(randomWallet); return tx; @@ -484,6 +507,38 @@ export abstract class SealevelHypTokenAdapter this.warpProgramPubKey, ); } + + /** + * Fetches the median prioritization fee for transfers of the collateralAddress token. + * @returns The median prioritization fee in micro-lamports + */ + async getMedianPriorityFee(): Promise { + this.logger.debug('Fetching priority fee history for token transfer'); + + const collateralAddress = this.addresses.token; + const fees = await this.getProvider().getRecentPrioritizationFees({ + lockedWritableAccounts: [new PublicKey(collateralAddress)], + }); + + const nonZeroFees = fees + .filter((fee) => fee.prioritizationFee > 0) + .map((fee) => fee.prioritizationFee); + + if (nonZeroFees.length < 3) { + this.logger.warn( + 'Insufficient historical prioritization fee data for padding, skipping', + ); + return MINIMUM_PRIORITY_FEE; + } + + const medianFee = Math.max( + Math.floor(median(nonZeroFees) * PRIORITY_FEE_PADDING_FACTOR), + MINIMUM_PRIORITY_FEE, + ); + + this.logger.debug(`Median priority fee: ${medianFee}`); + return medianFee; + } } // Interacts with Hyp Native token programs @@ -529,6 +584,12 @@ export class SealevelHypNativeAdapter extends SealevelHypTokenAdapter { return this.wrappedNative.getMetadata(); } + override async getMedianPriorityFee(): Promise { + // Native tokens don't have a collateral address, so we don't fetch + // prioritization fee history + return undefined; + } + getTransferInstructionKeyList(params: KeyListParams): Array { return [ ...super.getTransferInstructionKeyList(params), From 3857cfb65a98edd3cd1855c54bb3172591051653 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 25 Sep 2024 16:06:10 -0400 Subject: [PATCH 082/224] Version Packages (#4535) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/cli@5.3.0 ### Minor Changes - 35d4503b9: Update to registry v4.3.6 - aef3dbf4d: Remove mailbox choice prompt if it can be automatically detected from the registry ### Patch Changes - a513e1b51: Override default with merkle hook for self relay - Updated dependencies [eb47aaee8] - Updated dependencies [50319d8ba] - Updated dependencies [8de531fa4] - Updated dependencies [746eeb9d9] - Updated dependencies [fd536a79a] - Updated dependencies [50319d8ba] - @hyperlane-xyz/sdk@5.3.0 - @hyperlane-xyz/utils@5.3.0 ## @hyperlane-xyz/helloworld@5.3.0 ### Minor Changes - 35d4503b9: Update to registry v4.3.6 ### Patch Changes - Updated dependencies [eb47aaee8] - Updated dependencies [50319d8ba] - Updated dependencies [8de531fa4] - Updated dependencies [fd536a79a] - @hyperlane-xyz/sdk@5.3.0 - @hyperlane-xyz/core@5.3.0 ## @hyperlane-xyz/utils@5.3.0 ### Minor Changes - 746eeb9d9: Add parseTokenMessage util for decoding warp route transfers ### Patch Changes - 50319d8ba: Ensure runWithTimeout cleans up after itself properly ## @hyperlane-xyz/widgets@5.3.0 ### Minor Changes - 35d4503b9: Update to registry v4.3.6 ### Patch Changes - Updated dependencies [eb47aaee8] - Updated dependencies [50319d8ba] - Updated dependencies [8de531fa4] - Updated dependencies [fd536a79a] - @hyperlane-xyz/sdk@5.3.0 ## @hyperlane-xyz/core@5.3.0 ### Patch Changes - Updated dependencies [746eeb9d9] - Updated dependencies [50319d8ba] - @hyperlane-xyz/utils@5.3.0 ## @hyperlane-xyz/sdk@5.3.0 ### Patch Changes - eb47aaee8: Use collateral account for sealevel native warp route balance - 50319d8ba: Make HyperlaneDeployer.chainTimeoutMs public. Remove HyperlaneDeployer.startingBlockNumbers as it's not used by any deployer. Update HyperlaneDeployer.deploy for better logging and error handling. - 8de531fa4: fix: warn on submodule metadata builder failures - fd536a79a: Include priority fee instruction with SVM warp transfers - Updated dependencies [746eeb9d9] - Updated dependencies [50319d8ba] - @hyperlane-xyz/utils@5.3.0 - @hyperlane-xyz/core@5.3.0 ## @hyperlane-xyz/infra@5.3.0 ### Patch Changes - Updated dependencies [eb47aaee8] - Updated dependencies [50319d8ba] - Updated dependencies [35d4503b9] - Updated dependencies [8de531fa4] - Updated dependencies [746eeb9d9] - Updated dependencies [fd536a79a] - Updated dependencies [50319d8ba] - @hyperlane-xyz/sdk@5.3.0 - @hyperlane-xyz/helloworld@5.3.0 - @hyperlane-xyz/utils@5.3.0 ## @hyperlane-xyz/ccip-server@5.3.0 ## @hyperlane-xyz/github-proxy@5.3.0 Co-authored-by: github-actions[bot] --- .changeset/bright-rings-jam.md | 5 ----- .changeset/curvy-baboons-deliver.md | 5 ----- .changeset/giant-houses-cough.md | 7 ------- .changeset/hip-yaks-switch.md | 7 ------- .changeset/lazy-flies-sin.md | 5 ----- .changeset/popular-cars-burn.md | 5 ----- .changeset/shiny-dots-vanish.md | 5 ----- .changeset/smooth-clocks-sin.md | 5 ----- .changeset/twenty-rats-buy.md | 5 ----- solidity/CHANGELOG.md | 8 ++++++++ solidity/package.json | 4 ++-- typescript/ccip-server/CHANGELOG.md | 2 ++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 19 ++++++++++++++++++ typescript/cli/package.json | 6 +++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 2 ++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 15 ++++++++++++++ typescript/helloworld/package.json | 6 +++--- typescript/infra/CHANGELOG.md | 15 ++++++++++++++ typescript/infra/package.json | 8 ++++---- typescript/sdk/CHANGELOG.md | 15 ++++++++++++++ typescript/sdk/package.json | 6 +++--- typescript/utils/CHANGELOG.md | 10 ++++++++++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 14 +++++++++++++ typescript/widgets/package.json | 4 ++-- yarn.lock | 30 ++++++++++++++-------------- 29 files changed, 136 insertions(+), 85 deletions(-) delete mode 100644 .changeset/bright-rings-jam.md delete mode 100644 .changeset/curvy-baboons-deliver.md delete mode 100644 .changeset/giant-houses-cough.md delete mode 100644 .changeset/hip-yaks-switch.md delete mode 100644 .changeset/lazy-flies-sin.md delete mode 100644 .changeset/popular-cars-burn.md delete mode 100644 .changeset/shiny-dots-vanish.md delete mode 100644 .changeset/smooth-clocks-sin.md delete mode 100644 .changeset/twenty-rats-buy.md diff --git a/.changeset/bright-rings-jam.md b/.changeset/bright-rings-jam.md deleted file mode 100644 index d84431d78..000000000 --- a/.changeset/bright-rings-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperlane-xyz/cli": patch ---- - -Override default with merkle hook for self relay diff --git a/.changeset/curvy-baboons-deliver.md b/.changeset/curvy-baboons-deliver.md deleted file mode 100644 index 931472bac..000000000 --- a/.changeset/curvy-baboons-deliver.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Use collateral account for sealevel native warp route balance diff --git a/.changeset/giant-houses-cough.md b/.changeset/giant-houses-cough.md deleted file mode 100644 index b50c79961..000000000 --- a/.changeset/giant-houses-cough.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Make HyperlaneDeployer.chainTimeoutMs public. -Remove HyperlaneDeployer.startingBlockNumbers as it's not used by any deployer. -Update HyperlaneDeployer.deploy for better logging and error handling. diff --git a/.changeset/hip-yaks-switch.md b/.changeset/hip-yaks-switch.md deleted file mode 100644 index b11ef8f10..000000000 --- a/.changeset/hip-yaks-switch.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperlane-xyz/helloworld': minor -'@hyperlane-xyz/widgets': minor -'@hyperlane-xyz/cli': minor ---- - -Update to registry v4.3.6 diff --git a/.changeset/lazy-flies-sin.md b/.changeset/lazy-flies-sin.md deleted file mode 100644 index 33b439809..000000000 --- a/.changeset/lazy-flies-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor ---- - -Remove mailbox choice prompt if it can be automatically detected from the registry diff --git a/.changeset/popular-cars-burn.md b/.changeset/popular-cars-burn.md deleted file mode 100644 index d402136d5..000000000 --- a/.changeset/popular-cars-burn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -fix: warn on submodule metadata builder failures diff --git a/.changeset/shiny-dots-vanish.md b/.changeset/shiny-dots-vanish.md deleted file mode 100644 index 7b96ce512..000000000 --- a/.changeset/shiny-dots-vanish.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/utils': minor ---- - -Add parseTokenMessage util for decoding warp route transfers diff --git a/.changeset/smooth-clocks-sin.md b/.changeset/smooth-clocks-sin.md deleted file mode 100644 index d6cb506b5..000000000 --- a/.changeset/smooth-clocks-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Include priority fee instruction with SVM warp transfers diff --git a/.changeset/twenty-rats-buy.md b/.changeset/twenty-rats-buy.md deleted file mode 100644 index f8d44359b..000000000 --- a/.changeset/twenty-rats-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/utils': patch ---- - -Ensure runWithTimeout cleans up after itself properly diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index 0e695b0b7..dae564ba4 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/core +## 5.3.0 + +### Patch Changes + +- Updated dependencies [746eeb9d9] +- Updated dependencies [50319d8ba] + - @hyperlane-xyz/utils@5.3.0 + ## 5.2.1 ### Patch Changes diff --git a/solidity/package.json b/solidity/package.json index 843a4c856..e5fe859f0 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.2.1", + "version": "5.3.0", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.2.1", + "@hyperlane-xyz/utils": "5.3.0", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index 36e16dd74..c363576a6 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/ccip-server +## 5.3.0 + ## 5.2.1 ## 5.2.0 diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index 0714e7c2a..911771111 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.2.1", + "version": "5.3.0", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index 5edb0c00d..8a7fee418 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,24 @@ # @hyperlane-xyz/cli +## 5.3.0 + +### Minor Changes + +- 35d4503b9: Update to registry v4.3.6 +- aef3dbf4d: Remove mailbox choice prompt if it can be automatically detected from the registry + +### Patch Changes + +- a513e1b51: Override default with merkle hook for self relay +- Updated dependencies [eb47aaee8] +- Updated dependencies [50319d8ba] +- Updated dependencies [8de531fa4] +- Updated dependencies [746eeb9d9] +- Updated dependencies [fd536a79a] +- Updated dependencies [50319d8ba] + - @hyperlane-xyz/sdk@5.3.0 + - @hyperlane-xyz/utils@5.3.0 + ## 5.2.1 ### Patch Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index e28e89b7a..c3ba1e78e 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.2.1", + "version": "5.3.0", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.2.1", - "@hyperlane-xyz/utils": "5.2.1", + "@hyperlane-xyz/sdk": "5.3.0", + "@hyperlane-xyz/utils": "5.3.0", "@inquirer/prompts": "^3.0.0", "asn1.js": "^5.4.1", "bignumber.js": "^9.1.1", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index e1aa0bd55..1c1586937 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.2.1'; +export const VERSION = '5.3.0'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md index 70e5c73ec..8dc7b9be6 100644 --- a/typescript/github-proxy/CHANGELOG.md +++ b/typescript/github-proxy/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/github-proxy +## 5.3.0 + ## 5.2.1 ## 5.2.0 diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index 9a203f2bb..c4c002387 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.2.1", + "version": "5.3.0", "private": true, "scripts": { "deploy": "wrangler deploy", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index ad5881287..f2d2db3a6 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,20 @@ # @hyperlane-xyz/helloworld +## 5.3.0 + +### Minor Changes + +- 35d4503b9: Update to registry v4.3.6 + +### Patch Changes + +- Updated dependencies [eb47aaee8] +- Updated dependencies [50319d8ba] +- Updated dependencies [8de531fa4] +- Updated dependencies [fd536a79a] + - @hyperlane-xyz/sdk@5.3.0 + - @hyperlane-xyz/core@5.3.0 + ## 5.2.1 ### Patch Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index c53c002b9..14be666ff 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.2.1", + "version": "5.3.0", "dependencies": { - "@hyperlane-xyz/core": "5.2.1", + "@hyperlane-xyz/core": "5.3.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.2.1", + "@hyperlane-xyz/sdk": "5.3.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index 6bd879f45..b1bdb77d0 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,20 @@ # @hyperlane-xyz/infra +## 5.3.0 + +### Patch Changes + +- Updated dependencies [eb47aaee8] +- Updated dependencies [50319d8ba] +- Updated dependencies [35d4503b9] +- Updated dependencies [8de531fa4] +- Updated dependencies [746eeb9d9] +- Updated dependencies [fd536a79a] +- Updated dependencies [50319d8ba] + - @hyperlane-xyz/sdk@5.3.0 + - @hyperlane-xyz/helloworld@5.3.0 + - @hyperlane-xyz/utils@5.3.0 + ## 5.2.1 ### Patch Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 849387d06..768f2411a 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.2.1", + "version": "5.3.0", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.2.1", + "@hyperlane-xyz/helloworld": "5.3.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.2.1", - "@hyperlane-xyz/utils": "5.2.1", + "@hyperlane-xyz/sdk": "5.3.0", + "@hyperlane-xyz/utils": "5.3.0", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index da934b9e9..486a7ed3f 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,20 @@ # @hyperlane-xyz/sdk +## 5.3.0 + +### Patch Changes + +- eb47aaee8: Use collateral account for sealevel native warp route balance +- 50319d8ba: Make HyperlaneDeployer.chainTimeoutMs public. + Remove HyperlaneDeployer.startingBlockNumbers as it's not used by any deployer. + Update HyperlaneDeployer.deploy for better logging and error handling. +- 8de531fa4: fix: warn on submodule metadata builder failures +- fd536a79a: Include priority fee instruction with SVM warp transfers +- Updated dependencies [746eeb9d9] +- Updated dependencies [50319d8ba] + - @hyperlane-xyz/utils@5.3.0 + - @hyperlane-xyz/core@5.3.0 + ## 5.2.1 ### Patch Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 7c9d63e33..2e19bd9e7 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.2.1", + "version": "5.3.0", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.2.1", - "@hyperlane-xyz/utils": "5.2.1", + "@hyperlane-xyz/core": "5.3.0", + "@hyperlane-xyz/utils": "5.3.0", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index 61af4f186..fc4aed2e3 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @hyperlane-xyz/utils +## 5.3.0 + +### Minor Changes + +- 746eeb9d9: Add parseTokenMessage util for decoding warp route transfers + +### Patch Changes + +- 50319d8ba: Ensure runWithTimeout cleans up after itself properly + ## 5.2.1 ## 5.2.0 diff --git a/typescript/utils/package.json b/typescript/utils/package.json index 70a61f73b..59d4f0958 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.2.1", + "version": "5.3.0", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index 0d39df731..4145ac3ba 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,19 @@ # @hyperlane-xyz/widgets +## 5.3.0 + +### Minor Changes + +- 35d4503b9: Update to registry v4.3.6 + +### Patch Changes + +- Updated dependencies [eb47aaee8] +- Updated dependencies [50319d8ba] +- Updated dependencies [8de531fa4] +- Updated dependencies [fd536a79a] + - @hyperlane-xyz/sdk@5.3.0 + ## 5.2.1 ### Patch Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 604ebe3a1..2cfb3dafe 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.2.1", + "version": "5.3.0", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.2.1" + "@hyperlane-xyz/sdk": "5.3.0" }, "devDependencies": { "@storybook/addon-essentials": "^7.6.14", diff --git a/yarn.lock b/yarn.lock index 5255a6e82..b99daa980 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7591,8 +7591,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.2.1" - "@hyperlane-xyz/utils": "npm:5.2.1" + "@hyperlane-xyz/sdk": "npm:5.3.0" + "@hyperlane-xyz/utils": "npm:5.3.0" "@inquirer/prompts": "npm:^3.0.0" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:^18.14.5" @@ -7622,13 +7622,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.2.1, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.3.0, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.2.1" + "@hyperlane-xyz/utils": "npm:5.3.0" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7678,13 +7678,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.2.1, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.3.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.2.1" + "@hyperlane-xyz/core": "npm:5.3.0" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.2.1" + "@hyperlane-xyz/sdk": "npm:5.3.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7731,10 +7731,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.2.1" + "@hyperlane-xyz/helloworld": "npm:5.3.0" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.2.1" - "@hyperlane-xyz/utils": "npm:5.2.1" + "@hyperlane-xyz/sdk": "npm:5.3.0" + "@hyperlane-xyz/utils": "npm:5.3.0" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -7800,7 +7800,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.2.1, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.3.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -7808,8 +7808,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.2.1" - "@hyperlane-xyz/utils": "npm:5.2.1" + "@hyperlane-xyz/core": "npm:5.3.0" + "@hyperlane-xyz/utils": "npm:5.3.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -7850,7 +7850,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.2.1, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.3.0, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -7875,7 +7875,7 @@ __metadata: resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.2.1" + "@hyperlane-xyz/sdk": "npm:5.3.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From 9f5a17b7a47b9250cbc9d3d81caf8722573259e8 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 25 Sep 2024 18:07:08 -0400 Subject: [PATCH 083/224] fix: gas oracle overhead calculation (#4571) fix: gas oracle overhead calculation as spotted by @tkporter https://canary.discord.com/channels/935678348330434570/1288601439006097498/1288602404950114334 --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .../infra/config/environments/mainnet3/igp.ts | 12 ++++++------ .../infra/config/environments/test/igp.ts | 4 ++-- .../infra/config/environments/testnet4/igp.ts | 6 +++--- typescript/infra/src/config/gas-oracle.ts | 17 +++++++++-------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/igp.ts b/typescript/infra/config/environments/mainnet3/igp.ts index 7275cbe02..2833db1a1 100644 --- a/typescript/infra/config/environments/mainnet3/igp.ts +++ b/typescript/infra/config/environments/mainnet3/igp.ts @@ -4,8 +4,8 @@ import { exclude, objMap } from '@hyperlane-xyz/utils'; import { AllStorageGasOracleConfigs, getAllStorageGasOracleConfigs, + getOverhead, getTokenExchangeRateFromValues, - remoteOverhead, } from '../../../src/config/gas-oracle.js'; import { ethereumChainNames } from './chains.js'; @@ -16,9 +16,9 @@ import rawTokenPrices from './tokenPrices.json'; const tokenPrices: ChainMap = rawTokenPrices; -const remoteOverheadWithOverrides = (chain: ChainName) => { - let overhead = remoteOverhead(chain, ethereumChainNames); - if (chain === 'moonbeam') { +const getOverheadWithOverrides = (local: ChainName, remote: ChainName) => { + let overhead = getOverhead(local, remote, ethereumChainNames); + if (remote === 'moonbeam') { overhead *= 4; } return overhead; @@ -31,7 +31,7 @@ const storageGasOracleConfig: AllStorageGasOracleConfigs = (local, remote) => getTokenExchangeRateFromValues(local, remote, tokenPrices), (local) => parseFloat(tokenPrices[local]), - remoteOverheadWithOverrides, + getOverheadWithOverrides, ); export const igp: ChainMap = objMap( @@ -49,7 +49,7 @@ export const igp: ChainMap = objMap( overhead: Object.fromEntries( exclude(local, supportedChainNames).map((remote) => [ remote, - remoteOverhead(remote, ethereumChainNames), + getOverheadWithOverrides(local, remote), ]), ), oracleConfig: storageGasOracleConfig[local], diff --git a/typescript/infra/config/environments/test/igp.ts b/typescript/infra/config/environments/test/igp.ts index e63e3de59..0463d9279 100644 --- a/typescript/infra/config/environments/test/igp.ts +++ b/typescript/infra/config/environments/test/igp.ts @@ -17,8 +17,8 @@ export const igp: ChainMap = objMap( exclude(chain, testChainNames).map((remote) => [ remote, multisigIsmVerificationCost( - multisigIsm[remote].threshold, - multisigIsm[remote].validators.length, + multisigIsm[chain].threshold, + multisigIsm[chain].validators.length, ), ]), ); diff --git a/typescript/infra/config/environments/testnet4/igp.ts b/typescript/infra/config/environments/testnet4/igp.ts index 92d0506d1..3c0189e3a 100644 --- a/typescript/infra/config/environments/testnet4/igp.ts +++ b/typescript/infra/config/environments/testnet4/igp.ts @@ -4,8 +4,8 @@ import { Address, exclude, objMap } from '@hyperlane-xyz/utils'; import { AllStorageGasOracleConfigs, getAllStorageGasOracleConfigs, + getOverhead, getTokenExchangeRateFromValues, - remoteOverhead, } from '../../../src/config/gas-oracle.js'; import { ethereumChainNames } from './chains.js'; @@ -23,7 +23,7 @@ export const storageGasOracleConfig: AllStorageGasOracleConfigs = (local, remote) => getTokenExchangeRateFromValues(local, remote, tokenPrices), (local) => parseFloat(tokenPrices[local]), - (local) => remoteOverhead(local, ethereumChainNames), + (local, remote) => getOverhead(local, remote, ethereumChainNames), ); export const igp: ChainMap = objMap( @@ -38,7 +38,7 @@ export const igp: ChainMap = objMap( overhead: Object.fromEntries( exclude(chain, supportedChainNames).map((remote) => [ remote, - remoteOverhead(remote, ethereumChainNames), + getOverhead(chain, remote, ethereumChainNames), ]), ), }; diff --git a/typescript/infra/src/config/gas-oracle.ts b/typescript/infra/src/config/gas-oracle.ts index 8cbc6194c..f992a141b 100644 --- a/typescript/infra/src/config/gas-oracle.ts +++ b/typescript/infra/src/config/gas-oracle.ts @@ -49,7 +49,7 @@ function getLocalStorageGasOracleConfig( gasPrices: ChainMap, getTokenExchangeRate: (local: ChainName, remote: ChainName) => BigNumber, getTokenUsdPrice?: (chain: ChainName) => number, - remoteOverhead?: (remote: ChainName) => number, + getOverhead?: (local: ChainName, remote: ChainName) => number, ): StorageGasOracleConfig { return remotes.reduce((agg, remote) => { let exchangeRate = getTokenExchangeRate(local, remote); @@ -96,8 +96,8 @@ function getLocalStorageGasOracleConfig( // If we have access to these, let's use the USD prices to apply some minimum // typical USD payment heuristics. - if (getTokenUsdPrice && remoteOverhead) { - const typicalRemoteGasAmount = remoteOverhead(remote) + 50_000; + if (getTokenUsdPrice && getOverhead) { + const typicalRemoteGasAmount = getOverhead(local, remote) + 50_000; const typicalIgpQuoteUsd = getUsdQuote( local, gasPriceBn, @@ -187,14 +187,15 @@ function getUsdQuote( const FOREIGN_DEFAULT_OVERHEAD = 600_000; // Overhead for interchain messaging -export function remoteOverhead( +export function getOverhead( + local: ChainName, remote: ChainName, ethereumChainNames: ChainName[], ): number { return ethereumChainNames.includes(remote as any) ? multisigIsmVerificationCost( - defaultMultisigConfigs[remote].threshold, - defaultMultisigConfigs[remote].validators.length, + defaultMultisigConfigs[local].threshold, + defaultMultisigConfigs[local].validators.length, ) : FOREIGN_DEFAULT_OVERHEAD; // non-ethereum overhead } @@ -205,7 +206,7 @@ export function getAllStorageGasOracleConfigs( gasPrices: ChainMap, getTokenExchangeRate: (local: ChainName, remote: ChainName) => BigNumber, getTokenUsdPrice?: (chain: ChainName) => number, - remoteOverhead?: (remote: ChainName) => number, + getOverhead?: (local: ChainName, remote: ChainName) => number, ): AllStorageGasOracleConfigs { return chainNames.filter(isEthereumProtocolChain).reduce((agg, local) => { const remotes = chainNames.filter((chain) => local !== chain); @@ -217,7 +218,7 @@ export function getAllStorageGasOracleConfigs( gasPrices, getTokenExchangeRate, getTokenUsdPrice, - remoteOverhead, + getOverhead, ), }; }, {}) as AllStorageGasOracleConfigs; From 471002bd1a3c1d36e26bf7f54c5d0bed70bf1543 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 26 Sep 2024 18:54:06 +0100 Subject: [PATCH 084/224] feat: add warp route monitoring for new Eclipse deploys (#4573) ### Description - Updates the monitoring script to support native balance getting and synthetic total supply getting - Drive-by to update `tokenProgramPubKey` -> `tokenMintPubKey`, which is more accurate (the mint isn't a program) ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../warp/eclipse-SOL-deployments.yaml | 23 +++++++++ .../warp/eclipse-USDC-deployments.yaml | 33 +++++++++++++ .../warp/eclipse-WIF-deployments.yaml | 24 ++++++++++ .../warp/eclipse-tETH-deployments.yaml | 24 ++++++++++ .../monitor-warp-routes-balances.ts | 47 ++++++++++++++++--- typescript/infra/src/warp/helm.ts | 2 +- .../token/adapters/SealevelTokenAdapter.ts | 15 ++++-- 7 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml create mode 100644 typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml create mode 100644 typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml create mode 100644 typescript/infra/config/environments/mainnet3/warp/eclipse-tETH-deployments.yaml diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml new file mode 100644 index 000000000..0469f45eb --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml @@ -0,0 +1,23 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +# Between injective and inevm +description: Hyperlane Warp Route artifacts +timestamp: '2024-09-19T16:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + solanamainnet: + protocolType: sealevel + type: native + hypAddress: '8DtAGQpcMuD5sG3KdxDy49ydqXUggR1LQtebh2TECbAc' + name: Solana + symbol: SOL + decimals: 9 + eclipsemainnet: + protocolType: sealevel + type: synthetic + hypAddress: 'FJu4E1BDYKVg7aTWdwATZRUvytJZ8ZZ2gQuvPfMWAz9y' + tokenAddress: 'BeRUj3h7BqkbdfFU7FBNYbodgf8GCHodzKvF9aVjNNfL' + isSpl2022: true + name: Solana + symbol: SOL + decimals: 9 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml new file mode 100644 index 000000000..2955d2c84 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml @@ -0,0 +1,33 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +# Between injective and inevm +description: Hyperlane Warp Route artifacts +timestamp: '2024-09-19T16:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + ethereum: + protocolType: ethereum + type: collateral + hypAddress: '0xe1De9910fe71cC216490AC7FCF019e13a34481D7' + tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' # USDC + name: USDC + symbol: USDC + decimals: 6 + solanamainnet: + protocolType: sealevel + type: collateral + hypAddress: '3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm' + tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' + isSpl2022: false + name: USDC + symbol: USDC + decimals: 6 + eclipsemainnet: + protocolType: sealevel + type: synthetic + hypAddress: 'EqRSt9aUDMKYKhzd1DGMderr3KNp29VZH3x5P7LFTC8m' + tokenAddress: 'AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE' + isSpl2022: true + name: USDC + symbol: USDC + decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml new file mode 100644 index 000000000..94e44a8b1 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml @@ -0,0 +1,24 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +# Between injective and inevm +description: Hyperlane Warp Route artifacts +timestamp: '2024-09-19T16:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + solanamainnet: + protocolType: sealevel + type: collateral + hypAddress: 'CuQmsT4eSF4dYiiGUGYYQxJ7c58pUAD5ADE3BbFGzQKx' + tokenAddress: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm' + name: dogwifhat + symbol: WIF + decimals: 9 + eclipsemainnet: + protocolType: sealevel + type: synthetic + hypAddress: '6tBGmKNxirxBYnm9khkaTtcr2fhJ9YviCgRm1RWM8NJv' + tokenAddress: '841P4tebEgNux2jaWSjCoi9LhrVr9eHGjLc758Va3RPH' + isSpl2022: false + name: dogwifhat + symbol: WIF + decimals: 9 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-tETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-tETH-deployments.yaml new file mode 100644 index 000000000..1f77a34e5 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-tETH-deployments.yaml @@ -0,0 +1,24 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +# Between injective and inevm +description: Hyperlane Warp Route artifacts +timestamp: '2024-09-19T16:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + ethereum: + protocolType: ethereum + type: collateral + hypAddress: '0xc2495f3183F043627CAECD56dAaa726e3B2D9c09' + tokenAddress: '0x19e099B7aEd41FA52718D780dDA74678113C0b32' + name: Turbo Eth + symbol: tETH + decimals: 18 + eclipsemainnet: + protocolType: sealevel + type: synthetic + hypAddress: '6GM7hy6M6LjhadG1xuKXPQ3jPC1eieEszR8DforoRzUp' + tokenAddress: 'GU7NS9xCwgNPiAdJ69iusFrRfawjDDPjeMBovhV1d4kn' + isSpl2022: false + name: Turbo Eth + symbol: tETH + decimals: 9 diff --git a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts index e06031096..160a777f5 100644 --- a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts +++ b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts @@ -17,6 +17,8 @@ import { CwNativeTokenAdapter, MultiProtocolProvider, SealevelHypCollateralAdapter, + SealevelHypNativeAdapter, + SealevelHypSyntheticAdapter, TokenType, WarpRouteConfig, WarpRouteConfigSchema, @@ -135,8 +137,24 @@ async function checkBalance( ); } case ProtocolType.Sealevel: - // TODO - solana native - return 0; + const adapter = new SealevelHypNativeAdapter( + chain, + multiProtocolProvider, + { + token: token.tokenAddress, + warpRouter: token.hypAddress, + // Mailbox only required for transfers, using system as placeholder + mailbox: SystemProgram.programId.toBase58(), + }, + // Not used for native tokens, but required for the adapter + token?.isSpl2022 ?? false, + ); + const balance = ethers.BigNumber.from( + await adapter.getBalance(token.hypAddress), + ); + return parseFloat( + ethers.utils.formatUnits(balance, token.decimals), + ); case ProtocolType.Cosmos: { if (!token.ibcDenom) throw new Error('IBC denom missing for native token'); @@ -174,7 +192,7 @@ async function checkBalance( } case ProtocolType.Sealevel: { if (!token.tokenAddress) - throw new Error('Token address missing for synthetic token'); + throw new Error('Token address missing for collateral token'); const adapter = new SealevelHypCollateralAdapter( chain, multiProtocolProvider, @@ -228,10 +246,27 @@ async function checkBalance( ); } case ProtocolType.Sealevel: - // TODO - solana native - return 0; + if (!token.tokenAddress) + throw new Error('Token address missing for synthetic token'); + const adapter = new SealevelHypSyntheticAdapter( + chain, + multiProtocolProvider, + { + token: token.tokenAddress, + warpRouter: token.hypAddress, + // Mailbox only required for transfers, using system as placeholder + mailbox: SystemProgram.programId.toBase58(), + }, + token?.isSpl2022 ?? false, + ); + const syntheticBalance = ethers.BigNumber.from( + await adapter.getTotalSupply(), + ); + return parseFloat( + ethers.utils.formatUnits(syntheticBalance, token.decimals), + ); case ProtocolType.Cosmos: - // TODO - cosmos native + // TODO - cosmos synthetic return 0; } break; diff --git a/typescript/infra/src/warp/helm.ts b/typescript/infra/src/warp/helm.ts index f1207f9a6..4633ddd83 100644 --- a/typescript/infra/src/warp/helm.ts +++ b/typescript/infra/src/warp/helm.ts @@ -27,7 +27,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager { return { image: { repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: 'fce6adf-20240905-094435', + tag: 'd4d5501-20240925-222735', }, configFilePath: pathRelativeToMonorepoRoot, fullnameOverride: this.helmReleaseName, diff --git a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts index 0d5b99e13..8287fa07b 100644 --- a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts @@ -119,7 +119,7 @@ export class SealevelTokenAdapter extends BaseSealevelAdapter implements ITokenAdapter { - public readonly tokenProgramPubKey: PublicKey; + public readonly tokenMintPubKey: PublicKey; constructor( public readonly chainName: ChainName, @@ -128,7 +128,7 @@ export class SealevelTokenAdapter public readonly isSpl2022: boolean = false, ) { super(chainName, multiProvider, addresses); - this.tokenProgramPubKey = new PublicKey(addresses.token); + this.tokenMintPubKey = new PublicKey(addresses.token); } async getBalance(owner: Address): Promise { @@ -183,7 +183,7 @@ export class SealevelTokenAdapter deriveAssociatedTokenAccount(owner: PublicKey): PublicKey { return getAssociatedTokenAddressSync( - this.tokenProgramPubKey, + this.tokenMintPubKey, owner, true, this.getTokenProgramId(), @@ -639,7 +639,7 @@ export class SealevelHypCollateralAdapter extends SealevelHypTokenAdapter { /// 9. [executable] The SPL token program for the mint. { pubkey: this.getTokenProgramId(), isSigner: false, isWritable: false }, /// 10. [writeable] The mint. - { pubkey: this.tokenProgramPubKey, isSigner: false, isWritable: true }, + { pubkey: this.tokenMintPubKey, isSigner: false, isWritable: true }, /// 11. [writeable] The token sender's associated token account, from which tokens will be sent. { pubkey: this.deriveAssociatedTokenAccount(params.sender), @@ -696,6 +696,13 @@ export class SealevelHypSyntheticAdapter extends SealevelHypTokenAdapter { } } + async getTotalSupply(): Promise { + const response = await this.getProvider().getTokenSupply( + this.tokenMintPubKey, + ); + return BigInt(response.value.amount); + } + deriveMintAuthorityAccount(): PublicKey { return super.derivePda( ['hyperlane_token', '-', 'mint'], From 642a349b7f99d10620de008009c422e222442789 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:21:05 -0400 Subject: [PATCH 085/224] feat: sep 24 testnet deployments (#4574) feat: add more testnets - `berabartio` - `camptestnet` - `formtestnet` - `soneiumtestnet` - `suavetoliman` if RPCs get sorted: - `citreatestnet` - `hyperliquidevmtestnet` --- .registryrc | 2 +- rust/main/config/testnet_config.json | 464 +++++++++++- .../config/environments/testnet4/agent.ts | 28 +- .../testnet4/aw-validators/hyperlane.json | 15 + .../config/environments/testnet4/chains.ts | 5 - .../testnet4/core/verification.json | 532 ++++++++++++++ .../config/environments/testnet4/funding.ts | 9 +- .../environments/testnet4/gasPrices.json | 46 +- .../infra/config/environments/testnet4/igp.ts | 2 - .../testnet4/ism/verification.json | 688 ++++++++++++++++++ .../middleware/accounts/verification.json | 149 +++- .../testnet4/supportedChainNames.ts | 7 + .../environments/testnet4/tokenPrices.json | 37 +- .../environments/testnet4/validators.ts | 114 ++- .../infra/scripts/print-token-prices.ts | 25 +- typescript/infra/src/config/gas-oracle.ts | 12 +- typescript/sdk/src/consts/multisigIsm.ts | 35 + 17 files changed, 2084 insertions(+), 86 deletions(-) diff --git a/.registryrc b/.registryrc index 9d73cdf16..ff673418e 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -d7dc44d8894962648a544686cdce4536ce9569ce +3df435f02b4787a58faf3e3c7411e62959b6db38 diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index b5ac9c957..769aa6c9c 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -37,7 +37,7 @@ "interchainAccountIsm": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", "interchainAccountRouter": "0xEbA64c8a9b4a61a9210d5fe7E4375380999C821b", "interchainGasPaymaster": "0x44769b0f4a6f01339e131a691cc2eebbb519d297", - "interchainSecurityModule": "0xEE179dd1b1beD39449e81c003D9629e92A5c0085", + "interchainSecurityModule": "0x0a89d18D16Fd969b1f864B3354290d9c4aD91C4c", "isTestnet": true, "mailbox": "0xEf9F292fcEBC3848bF4bB92a96a04F9ECBb78E59", "merkleTreeHook": "0x221FA9CBaFcd6c1C3d206571Cf4427703e023FFa", @@ -100,7 +100,7 @@ "from": 49690504 }, "interchainGasPaymaster": "0xc756cFc1b7d0d4646589EDf10eD54b201237F5e8", - "interchainSecurityModule": "0x29cEAFEE1F76B9CE271750f86B2bD12C23F9dDb6", + "interchainSecurityModule": "0xB071d45FFDB9c6BC3D6d91dA6565786D93eB2D6f", "isTestnet": true, "mailbox": "0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8", "merkleTreeHook": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", @@ -165,7 +165,7 @@ "from": 13851043 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x815a9642497Ee1E9F061f8b828C85Eb7193DecfC", + "interchainSecurityModule": "0x8fE91D229bb2d4872E94D5130246A3E287E77c47", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -232,7 +232,7 @@ "interchainAccountIsm": "0xa9D8Ec959F34272B1a56D09AF00eeee58970d3AE", "interchainAccountRouter": "0x6d2B3e304E58c2a19f1492E7cf15CaF63Ce6e0d2", "interchainGasPaymaster": "0x0dD20e410bdB95404f71c5a4e7Fa67B892A5f949", - "interchainSecurityModule": "0xE758870D4E50c2aF2b03341808d54d79F5ec3c1E", + "interchainSecurityModule": "0x8842eDc6080e6A37F72eEe64cdae9fE0bCa9AeB8", "isTestnet": true, "mailbox": "0xF9F6F5646F478d5ab4e20B0F910C92F1CCC9Cc6D", "merkleTreeHook": "0xc6cbF39A747f5E28d1bDc8D9dfDAb2960Abd5A8f", @@ -301,7 +301,7 @@ "from": 4950 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0x415a45C98288059Cce9c32AE4a09AB19C91d5056", + "interchainSecurityModule": "0xBD64f3dd712Ef0c372A8F9410c2296ff3AB7C3A4", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -399,7 +399,7 @@ "from": 1606754 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x815a9642497Ee1E9F061f8b828C85Eb7193DecfC", + "interchainSecurityModule": "0x85f5aE8393c3051057444eEaB78bA9567C95BCD1", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -462,7 +462,7 @@ "interchainAccountIsm": "0xfaB4815BDC5c60c6bD625459C8577aFdD79D9311", "interchainAccountRouter": "0xeEF6933122894fF217a7dd07510b3D64b747e29b", "interchainGasPaymaster": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", - "interchainSecurityModule": "0x3dA17519c799f86000FADb7bfCCdc0CaB0D36fDd", + "interchainSecurityModule": "0x6E1eAddcA9708Af27c17b86DA132A27F316fF126", "isTestnet": true, "mailbox": "0x5b6CFf85442B851A8e6eaBd2A4E4507B5135B3B0", "merkleTreeHook": "0x9ff6ac3dAf63103620BBf76136eA1AFf43c2F612", @@ -528,7 +528,7 @@ "from": 1543015 }, "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9", - "interchainSecurityModule": "0x7C32096A30Ef0bC550e3b8AcB0D87F72A3910D04", + "interchainSecurityModule": "0x4F893EbE13724C6A2d2Cd34FAE509116c25b9B62", "isTestnet": true, "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc", "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE", @@ -590,7 +590,7 @@ "from": 15833917 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x815a9642497Ee1E9F061f8b828C85Eb7193DecfC", + "interchainSecurityModule": "0x85f5aE8393c3051057444eEaB78bA9567C95BCD1", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -715,7 +715,7 @@ "from": 10634605 }, "interchainGasPaymaster": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", - "interchainSecurityModule": "0x831Ee59F524C94A320821f4d30B6581Ace69379d", + "interchainSecurityModule": "0x32247eBC716c3B8bB5710c0b7CEb4D3a2A9A6205", "isTestnet": true, "mailbox": "0x54148470292C24345fb828B003461a9444414517", "merkleTreeHook": "0xddf4C3e791caCaFd26D7fb275549739B38ae6e75", @@ -787,7 +787,7 @@ "interchainAccountIsm": "0xE023239c8dfc172FF008D8087E7442d3eBEd9350", "interchainAccountRouter": "0xe17c37212d785760E8331D4A4395B17b34Ba8cDF", "interchainGasPaymaster": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", - "interchainSecurityModule": "0x476a8f40c81E69f5d676ccaA9709c0dE61F907E1", + "interchainSecurityModule": "0xacc87264e624bA17d4116800BbA6178a3378A9C8", "isTestnet": true, "mailbox": "0x3C5154a193D6e2955650f9305c8d80c18C814A68", "merkleTreeHook": "0x863E8c26621c52ACa1849C53500606e73BA272F0", @@ -868,7 +868,7 @@ "interchainAccountIsm": "0x83a3068B719F764d413625dA77468ED74789ae02", "interchainAccountRouter": "0x8e131c8aE5BF1Ed38D05a00892b6001a7d37739d", "interchainGasPaymaster": "0x6f2756380FD49228ae25Aa7F2817993cB74Ecc56", - "interchainSecurityModule": "0x76B21a2241f6A6FbaE624A7Fe5d7D3919C9ce3E3", + "interchainSecurityModule": "0x932C1D184b3A792c5470f700fBB60c35FB86D9eD", "isTestnet": true, "mailbox": "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766", "merkleTreeHook": "0x4917a9746A7B6E0A57159cCb7F5a6744247f2d0d", @@ -978,7 +978,7 @@ "from": 3111622 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0x415a45C98288059Cce9c32AE4a09AB19C91d5056", + "interchainSecurityModule": "0xBD64f3dd712Ef0c372A8F9410c2296ff3AB7C3A4", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -1010,6 +1010,444 @@ "staticMerkleRootWeightedMultisigIsmFactory": "0xE67CfA164cDa449Ae38a0a09391eF6bCDf8e4e2c", "staticMessageIdWeightedMultisigIsmFactory": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "gasCurrencyCoinGeckoId": "superposition" + }, + "berabartio": { + "blockExplorers": [ + { + "apiUrl": "https://api.routescan.io/v2/network/testnet/evm/80084/etherscan/api/", + "family": "routescan", + "name": "Bartio Testnet Explorer", + "url": "https://bartio.beratrail.io/" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 1 + }, + "chainId": 80084, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Berachain bArtio", + "domainId": 80084, + "gasCurrencyCoinGeckoId": "berachain", + "isTestnet": true, + "name": "berabartio", + "nativeToken": { + "decimals": 18, + "name": "BERA", + "symbol": "BERA" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://bartio.rpc.berachain.com/" + }, + { + "http": "https://bartio.drpc.org" + }, + { + "http": "https://bera-testnet.nodeinfra.com" + } + ], + "aggregationHook": "0xf24d9D6be85576a1e831a9b2dbF79fC862a1dD03", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", + "interchainAccountIsm": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "interchainAccountRouter": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "interchainGasPaymaster": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "interchainSecurityModule": "0xd38BAC111B9C96953fddBA8fA52C90a2bD99dC45", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", + "pausableHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", + "pausableIsm": "0xEe421285728284000ec6c6C55C6F9161faeFfa99", + "protocolFee": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0x7c05c43D5601204c9d732F036fA539C67c7b1329", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0xeAEfB1458b032e75de3e9A3a480d005c426FB1c5", + "testRecipient": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "index": { + "from": 4772111 + } + }, + "camptestnet": { + "blockExplorers": [ + { + "apiUrl": "https://camp-network-testnet.blockscout.com/api", + "family": "blockscout", + "name": "Camp Network Testnet Explorer", + "url": "https://camp-network-testnet.blockscout.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 325000, + "displayName": "Camp Network Testnet V2", + "domainId": 325000, + "gasCurrencyCoinGeckoId": "ethereum", + "isTestnet": true, + "name": "camptestnet", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc-campnetwork.xyz" + } + ], + "aggregationHook": "0xb97D172479E9EC2501524E02703B42247559A1bD", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "pausableIsm": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "protocolFee": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "testRecipient": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "index": { + "from": 4591544 + } + }, + "citreatestnet": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.testnet.citrea.xyz/api", + "family": "blockscout", + "name": "Citrea Testnet Explorer", + "url": "https://explorer.testnet.citrea.xyz" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 5115, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Citrea Testnet", + "domainId": 5115, + "gasCurrencyCoinGeckoId": "bitcoin", + "isTestnet": true, + "name": "citreatestnet", + "nativeToken": { + "decimals": 18, + "name": "Citrea BTC", + "symbol": "cBTC" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.testnet.citrea.xyz" + } + ], + "aggregationHook": "0xE1b1579C643BF6d27af5E1f1777150E5DBc271E0", + "domainRoutingIsm": "0x47824122ab0fD5186EB7509f8B26bb1045f1F3A7", + "domainRoutingIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "fallbackRoutingHook": "0xeAEfB1458b032e75de3e9A3a480d005c426FB1c5", + "interchainAccountIsm": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "interchainAccountRouter": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", + "interchainGasPaymaster": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "interchainSecurityModule": "0xb6D42522D79897d776966955fe4a2558BB1E0B7c", + "mailbox": "0xB08d78F439e55D02C398519eef61606A5926245F", + "merkleTreeHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", + "pausableHook": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c", + "pausableIsm": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", + "protocolFee": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "proxyAdmin": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "staticAggregationHookFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticAggregationIsm": "0x39738A5d90711Be0C93F5efe8F46cD150D6867c1", + "staticAggregationIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "staticMerkleRootMultisigIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootWeightedMultisigIsmFactory": "0x54148470292C24345fb828B003461a9444414517", + "staticMessageIdMultisigIsmFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticMessageIdWeightedMultisigIsmFactory": "0x589C201a07c26b4725A4A829d772f24423da480B", + "storageGasOracle": "0xae7a78916Ba4c507aCB2F0e474ace545Ff4bF841", + "testRecipient": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "index": { + "from": 334706 + } + }, + "formtestnet": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.form.network/api", + "family": "blockscout", + "name": "Form Testnet Explorer", + "url": "https://explorer.form.network" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 132902, + "displayName": "Form Testnet", + "domainId": 132902, + "gasCurrencyCoinGeckoId": "ethereum", + "isTestnet": true, + "name": "formtestnet", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://testnet-rpc.form.network/http" + } + ], + "aggregationHook": "0xb97D172479E9EC2501524E02703B42247559A1bD", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "pausableIsm": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "protocolFee": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "testRecipient": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "index": { + "from": 12137144 + } + }, + "hyperliquidevmtestnet": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.hyperliquid.xyz/api", + "family": "other", + "name": "Hyperliquid EVM Testnet Explorer", + "url": "https://explorer.hyperliquid.xyz" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 998, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Hyperliquid EVM Testnet", + "domainId": 998, + "gasCurrencyCoinGeckoId": "ethereum", + "isTestnet": true, + "name": "hyperliquidevmtestnet", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://api.hyperliquid-testnet.xyz/evm" + } + ], + "aggregationHook": "0x5689Ad17c798d5114dc60Ba3c98e4853dF70403D", + "domainRoutingIsm": "0x4ac19e0bafc2aF6B98094F0a1B817dF196551219", + "domainRoutingIsmFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "fallbackRoutingHook": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", + "interchainAccountIsm": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "interchainAccountRouter": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "interchainGasPaymaster": "0x11918DC33E067C5DA83EEF58E50F856398b8Df4C", + "interchainSecurityModule": "0x59ea2E87C4775E6B963d71101AB879068898CBA8", + "mailbox": "0x589C201a07c26b4725A4A829d772f24423da480B", + "merkleTreeHook": "0x1b33611fCc073aB0737011d5512EF673Bff74962", + "pausableHook": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", + "pausableIsm": "0x75f3E2a4f424401195A5E176246Ecc9f7e7680ff", + "protocolFee": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "proxyAdmin": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "staticAggregationHookFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticAggregationIsm": "0xa20C93076e832388483356fa65c5C2B5F3A4d50c", + "staticAggregationIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMerkleRootMultisigIsmFactory": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8", + "staticMerkleRootWeightedMultisigIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "staticMessageIdMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMessageIdWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "storageGasOracle": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", + "testRecipient": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "index": { + "from": 7032169 + } + }, + "soneiumtestnet": { + "blockExplorers": [ + { + "apiUrl": "https://explorer-testnet.soneium.org/api", + "family": "blockscout", + "name": "Soneium Minato Testnet Explorer", + "url": "https://explorer-testnet.soneium.org" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 1946, + "displayName": "Soneium Minato Testnet", + "domainId": 1946, + "gasCurrencyCoinGeckoId": "ethereum", + "isTestnet": true, + "name": "soneiumtestnet", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.minato.soneium.org" + } + ], + "aggregationHook": "0xb97D172479E9EC2501524E02703B42247559A1bD", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "pausableIsm": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "protocolFee": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "testRecipient": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "index": { + "from": 2054457 + } + }, + "suavetoliman": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.toliman.suave.flashbots.net/api", + "family": "blockscout", + "name": "SUAVE Toliman Testnet Explorer", + "url": "https://explorer.toliman.suave.flashbots.net" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 4, + "reorgPeriod": 1 + }, + "chainId": 33626250, + "displayName": "SUAVE Toliman Testnet", + "domainId": 33626250, + "gasCurrencyCoinGeckoId": "ethereum", + "isTestnet": true, + "name": "suavetoliman", + "nativeToken": { + "decimals": 18, + "name": "TEEth", + "symbol": "TEEth" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.toliman.suave.flashbots.net" + } + ], + "aggregationHook": "0xb97D172479E9EC2501524E02703B42247559A1bD", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "pausableIsm": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "protocolFee": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "testRecipient": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "index": { + "from": 1921514 + } } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index f1c5d0ad6..0705dd7ee 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -1,7 +1,6 @@ import { GasPaymentEnforcement, GasPaymentEnforcementPolicyType, - MatchingList, RpcConsensusType, } from '@hyperlane-xyz/sdk'; @@ -45,12 +44,17 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< alfajores: true, arbitrumsepolia: true, basesepolia: true, + berabartio: true, bsctestnet: true, + camptestnet: true, + // citreatestnet: false, connextsepolia: true, ecotestnet: true, eclipsetestnet: false, + formtestnet: true, fuji: true, holesky: true, + // hyperliquidevmtestnet: false, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -58,18 +62,25 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< scrollsepolia: true, sepolia: true, solanatestnet: false, + soneiumtestnet: true, + suavetoliman: true, superpositiontestnet: true, }, [Role.Relayer]: { alfajores: true, arbitrumsepolia: true, basesepolia: true, + berabartio: true, bsctestnet: true, + camptestnet: true, + // citreatestnet: false, connextsepolia: true, ecotestnet: true, eclipsetestnet: false, + formtestnet: true, fuji: true, holesky: true, + // hyperliquidevmtestnet: false, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -77,19 +88,26 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< scrollsepolia: true, sepolia: true, solanatestnet: false, + soneiumtestnet: true, + suavetoliman: true, superpositiontestnet: true, }, [Role.Scraper]: { alfajores: true, arbitrumsepolia: true, basesepolia: true, + berabartio: true, bsctestnet: true, + camptestnet: true, + // citreatestnet: false, connextsepolia: false, ecotestnet: true, // Cannot scrape non-EVM chains eclipsetestnet: false, + formtestnet: true, fuji: true, holesky: true, + // hyperliquidevmtestnet: false, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -98,6 +116,8 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< sepolia: true, // Cannot scrape non-EVM chains solanatestnet: false, + soneiumtestnet: true, + suavetoliman: true, superpositiontestnet: false, }, }; @@ -177,7 +197,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '5a0d68b-20240916-144115', + tag: 'a436832-20240925-232333', }, blacklist: [...releaseCandidateHelloworldMatchingList, ...relayBlacklist], gasPaymentEnforcement, @@ -199,7 +219,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '73c232b-20240912-124300', + tag: 'a436832-20240925-232333', }, chains: validatorChainConfig(Contexts.Hyperlane), resources: validatorResources, @@ -208,7 +228,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '73c232b-20240912-124300', + tag: 'a436832-20240925-232333', }, resources: scraperResources, }, diff --git a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json index ae0fcf160..93ce9742f 100644 --- a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json @@ -12,6 +12,9 @@ "basesepolia": { "validators": ["0x82e3b437a2944e3ff00258c93e72cd1ba5e0e921"] }, + "berabartio": { + "validators": ["0x541dd3cb282cf869d72883557badae245b63e1fd"] + }, "bsctestnet": { "validators": [ "0x242d8a855a8c932dec51f7999ae7d1e48b10c95e", @@ -19,12 +22,18 @@ "0x1f030345963c54ff8229720dd3a711c15c554aeb" ] }, + "camptestnet": { + "validators": ["0x238f40f055a7ff697ea6dbff3ae943c9eae7a38e"] + }, "connextsepolia": { "validators": ["0xffbbec8c499585d80ef69eb613db624d27e089ab"] }, "ecotestnet": { "validators": ["0xb3191420d463c2af8bd9b4a395e100ec5c05915a"] }, + "formtestnet": { + "validators": ["0x72ad7fddf16d17ff902d788441151982fa31a7bc"] + }, "fuji": { "validators": [ "0xd8154f73d04cc7f7f0c332793692e6e6f6b2402e", @@ -55,6 +64,12 @@ "0xd3c75dcf15056012a4d74c483a0c6ea11d8c2b83" ] }, + "soneiumtestnet": { + "validators": ["0x2e2101020ccdbe76aeda1c27823b0150f43d0c63"] + }, + "suavetoliman": { + "validators": ["0xf58f6e30aabba34e8dd7f79b3168507192e2cc9b"] + }, "superpositiontestnet": { "validators": ["0x1d3168504b23b73cdf9c27f13bb0a595d7f1a96a"] } diff --git a/typescript/infra/config/environments/testnet4/chains.ts b/typescript/infra/config/environments/testnet4/chains.ts index 61073930f..7406081ed 100644 --- a/typescript/infra/config/environments/testnet4/chains.ts +++ b/typescript/infra/config/environments/testnet4/chains.ts @@ -18,11 +18,6 @@ export const chainMetadataOverrides: ChainMap> = { gasPrice: 8 * 10 ** 9, // 8 gwei }, }, - scrollsepolia: { - transactionOverrides: { - gasPrice: 5 * 10 ** 8, // 0.5 gwei - }, - }, }; export const getRegistry = async (useSecrets = true): Promise => diff --git a/typescript/infra/config/environments/testnet4/core/verification.json b/typescript/infra/config/environments/testnet4/core/verification.json index d6947e4e3..316cded26 100644 --- a/typescript/infra/config/environments/testnet4/core/verification.json +++ b/typescript/infra/config/environments/testnet4/core/verification.json @@ -1104,5 +1104,537 @@ "isProxy": false, "name": "ValidatorAnnounce" } + ], + "berabartio": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000138d4", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0xEe421285728284000ec6c6C55C6F9161faeFfa99", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c0000000000000000000000006c13643b3927c57db92c790e4e3e7ee81e13f78c", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xeAEfB1458b032e75de3e9A3a480d005c426FB1c5", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xae7a78916Ba4c507aCB2F0e474ace545Ff4bF841", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "constructorArguments": "000000000000000000000000ae7a78916ba4c507acb2f0e474ace545ff4bf84100000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xae7a78916Ba4c507aCB2F0e474ace545Ff4bF841" + }, + { + "name": "ProtocolFee", + "address": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } + ], + "citreatestnet": [ + { + "name": "ProxyAdmin", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x33dB966328Ea213b0f76eF96CA368AB37779F065", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000013fb", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xB08d78F439e55D02C398519eef61606A5926245F", + "constructorArguments": "00000000000000000000000033db966328ea213b0f76ef96ca368ab37779f065000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x33dB966328Ea213b0f76eF96CA368AB37779F065" + }, + { + "name": "PausableIsm", + "address": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", + "constructorArguments": "000000000000000000000000b08d78f439e55d02c398519eef61606a5926245f", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xeAEfB1458b032e75de3e9A3a480d005c426FB1c5", + "constructorArguments": "000000000000000000000000b08d78f439e55d02c398519eef61606a5926245f000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000783c4a0bb6663359281ad4a637d5af68f83ae213", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xae7a78916Ba4c507aCB2F0e474ace545Ff4bF841", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "constructorArguments": "00000000000000000000000004438ef7622f5412f82915f59cad4f704c61ea48000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x04438ef7622f5412f82915F59caD4f704C61eA48" + }, + { + "name": "ProtocolFee", + "address": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "constructorArguments": "000000000000000000000000b08d78f439e55d02c398519eef61606a5926245f", + "isProxy": false + } + ], + "hyperliquidevmtestnet": [ + { + "name": "ProxyAdmin", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000003e6", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "00000000000000000000000054148470292c24345fb828b003461a94444145170000000000000000000000006966b0e55883d49bfb24539356a2f8a673e0203900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x54148470292C24345fb828B003461a9444414517" + }, + { + "name": "PausableIsm", + "address": "0x75f3E2a4f424401195A5E176246Ecc9f7e7680ff", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x1b33611fCc073aB0737011d5512EF673Bff74962", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c0000000000000000000000001b33611fcc073ab0737011d5512ef673bff74962", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x11918DC33E067C5DA83EEF58E50F856398b8Df4C", + "constructorArguments": "00000000000000000000000066b71a4e18fbe09a6977a6520b47feddffa82a1c0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e0203900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c" + }, + { + "name": "ProtocolFee", + "address": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b", + "isProxy": false + } + ], + "soneiumtestnet": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000079a", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000d5eb5fa3f470ebbb93a4a58c644c87031268a04a", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000e0b988062a0c6492177d64823ab95a9c256c2a5f00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F" + }, + { + "name": "ProtocolFee", + "address": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } + ], + "formtestnet": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000020726", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000d5eb5fa3f470ebbb93a4a58c644c87031268a04a", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000e0b988062a0c6492177d64823ab95a9c256c2a5f00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F" + }, + { + "name": "ProtocolFee", + "address": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } + ], + "camptestnet": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000004f588", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000d5eb5fa3f470ebbb93a4a58c644c87031268a04a", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000e0b988062a0c6492177d64823ab95a9c256c2a5f00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F" + }, + { + "name": "ProtocolFee", + "address": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } + ], + "suavetoliman": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000201188a", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0x04438ef7622f5412f82915F59caD4f704C61eA48", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000d5eb5fa3f470ebbb93a4a58c644c87031268a04a", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000e0b988062a0c6492177d64823ab95a9c256c2a5f00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F" + }, + { + "name": "ProtocolFee", + "address": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/testnet4/funding.ts b/typescript/infra/config/environments/testnet4/funding.ts index 12f9cf622..a7227c27c 100644 --- a/typescript/infra/config/environments/testnet4/funding.ts +++ b/typescript/infra/config/environments/testnet4/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '344aa49-20240916-102227', + tag: 'a436832-20240925-232318', }, // We're currently using the same deployer key as testnet2. // To minimize nonce clobbering we offset the key funder cron @@ -29,13 +29,18 @@ export const keyFunderConfig: KeyFunderConfig< alfajores: '5', arbitrumsepolia: '0.1', basesepolia: '0.1', + berabartio: '0.1', bsctestnet: '5', + camptestnet: '0.1', + // citreatestnet: '0.001', connextsepolia: '1', ecotestnet: '0.02', // no funding for solana eclipsetestnet: '0', + formtestnet: '0.1', fuji: '5', holesky: '5', + // hyperliquidevmtestnet: '0.1', optimismsepolia: '0.1', // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: '0.2', @@ -44,6 +49,8 @@ export const keyFunderConfig: KeyFunderConfig< sepolia: '5', // no funding for solana solanatestnet: '0', + soneiumtestnet: '0.1', + suavetoliman: '0.1', superpositiontestnet: '1', }, desiredKathyBalancePerChain: { diff --git a/typescript/infra/config/environments/testnet4/gasPrices.json b/typescript/infra/config/environments/testnet4/gasPrices.json index 0c8369fb3..3e420afb0 100644 --- a/typescript/infra/config/environments/testnet4/gasPrices.json +++ b/typescript/infra/config/environments/testnet4/gasPrices.json @@ -4,15 +4,27 @@ "decimals": 9 }, "arbitrumsepolia": { - "amount": "0.1", + "amount": "0.10127", "decimals": 9 }, "basesepolia": { - "amount": "0.001000263", + "amount": "0.001000266", + "decimals": 9 + }, + "berabartio": { + "amount": "0.001000009", "decimals": 9 }, "bsctestnet": { - "amount": "5.532492", + "amount": "5.0", + "decimals": 9 + }, + "camptestnet": { + "amount": "0.001000253", + "decimals": 9 + }, + "citreatestnet": { + "amount": "1.01", "decimals": 9 }, "connextsepolia": { @@ -27,34 +39,50 @@ "amount": "0.001", "decimals": 9 }, + "formtestnet": { + "amount": "0.00100005", + "decimals": 9 + }, "fuji": { - "amount": "25.000000001", + "amount": "25.0", "decimals": 9 }, "holesky": { - "amount": "0.191141087", + "amount": "0.783743361", + "decimals": 9 + }, + "hyperliquidevmtestnet": { + "amount": "0.000000007", "decimals": 9 }, "optimismsepolia": { - "amount": "0.001000327", + "amount": "0.001000262", "decimals": 9 }, "polygonamoy": { - "amount": "31.092000015", + "amount": "37.870000015", "decimals": 9 }, "scrollsepolia": { - "amount": "0.059465192", + "amount": "0.497427713", "decimals": 9 }, "sepolia": { - "amount": "7.101334009", + "amount": "148.376099624", "decimals": 9 }, "solanatestnet": { "amount": "0.001", "decimals": 9 }, + "soneiumtestnet": { + "amount": "0.001000252", + "decimals": 9 + }, + "suavetoliman": { + "amount": "1.0", + "decimals": 9 + }, "superpositiontestnet": { "amount": "0.01", "decimals": 9 diff --git a/typescript/infra/config/environments/testnet4/igp.ts b/typescript/infra/config/environments/testnet4/igp.ts index 3c0189e3a..302d6aeb7 100644 --- a/typescript/infra/config/environments/testnet4/igp.ts +++ b/typescript/infra/config/environments/testnet4/igp.ts @@ -22,8 +22,6 @@ export const storageGasOracleConfig: AllStorageGasOracleConfigs = gasPrices, (local, remote) => getTokenExchangeRateFromValues(local, remote, tokenPrices), - (local) => parseFloat(tokenPrices[local]), - (local, remote) => getOverhead(local, remote, ethereumChainNames), ); export const igp: ChainMap = objMap( diff --git a/typescript/infra/config/environments/testnet4/ism/verification.json b/typescript/infra/config/environments/testnet4/ism/verification.json index 72cb4c65a..22e1df29d 100644 --- a/typescript/infra/config/environments/testnet4/ism/verification.json +++ b/typescript/infra/config/environments/testnet4/ism/verification.json @@ -1248,5 +1248,693 @@ "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" } + ], + "mevmdevnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x209e7F9d40954E230008B9bb076a0901d32695e5", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + } + ], + "berabartio": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } + ], + "citreatestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x10c9FF6EEE4BaD29734322467f541C84001422C2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xD6B8D6C372e07f67FeAb75403c0Ec88E3cce7Ab7", + "constructorArguments": "", + "isProxy": true + } + ], + "hyperliquidevmtestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x209e7F9d40954E230008B9bb076a0901d32695e5", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + } + ], + "camptestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } + ], + "formtestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } + ], + "suavetoliman": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } + ], + "soneiumtestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json b/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json index a37f20f74..ab0ed9c9b 100644 --- a/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json @@ -115,5 +115,152 @@ "name": "TransparentUpgradeableProxy" } ], - "sepolia": [] + "sepolia": [], + "berabartio": [ + { + "name": "InterchainAccountIsm", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "constructorArguments": "000000000000000000000000628bc518ed1e0e8c6cbcd574eba0ee29e7f6943e00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2cf52064c921c11adcd83588cbea08cc3bff5d8000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E" + } + ], + "citreatestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "constructorArguments": "000000000000000000000000b08d78f439e55d02c398519eef61606a5926245f", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "constructorArguments": "000000000000000000000000b08d78f439e55d02c398519eef61606a5926245f", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", + "constructorArguments": "000000000000000000000000a3ab7e6ce24e6293bd5320a53329ef2f4de73fca000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffa913705484c9baea32ffe9945bea099a1dff72000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA" + } + ], + "hyperliquidevmtestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "constructorArguments": "000000000000000000000000a2cf52064c921c11adcd83588cbea08cc3bff5d80000000000000000000000006966b0e55883d49bfb24539356a2f8a673e0203900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c5b5bda7f1d1f70a6678abb4d894612fc76498f000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8" + } + ], + "formtestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x01812D60958798695391dacF092BAc4a715B1718", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "constructorArguments": "00000000000000000000000001812d60958798695391dacf092bac4a715b171800000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d356c996277efb7f75ee8bd61b31cc781a12f54f000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x01812D60958798695391dacF092BAc4a715B1718" + } + ], + "camptestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x01812D60958798695391dacF092BAc4a715B1718", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "constructorArguments": "00000000000000000000000001812d60958798695391dacf092bac4a715b171800000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d356c996277efb7f75ee8bd61b31cc781a12f54f000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x01812D60958798695391dacF092BAc4a715B1718" + } + ], + "suavetoliman": [ + { + "name": "InterchainAccountIsm", + "address": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x01812D60958798695391dacF092BAc4a715B1718", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "constructorArguments": "00000000000000000000000001812d60958798695391dacf092bac4a715b171800000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d356c996277efb7f75ee8bd61b31cc781a12f54f000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x01812D60958798695391dacF092BAc4a715B1718" + } + ], + "soneiumtestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x01812D60958798695391dacF092BAc4a715B1718", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "constructorArguments": "00000000000000000000000001812d60958798695391dacf092bac4a715b171800000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d356c996277efb7f75ee8bd61b31cc781a12f54f000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x01812D60958798695391dacF092BAc4a715B1718" + } + ] } diff --git a/typescript/infra/config/environments/testnet4/supportedChainNames.ts b/typescript/infra/config/environments/testnet4/supportedChainNames.ts index d0fb545c7..5078cb18d 100644 --- a/typescript/infra/config/environments/testnet4/supportedChainNames.ts +++ b/typescript/infra/config/environments/testnet4/supportedChainNames.ts @@ -3,12 +3,17 @@ export const testnet4SupportedChainNames = [ 'alfajores', 'arbitrumsepolia', 'basesepolia', + 'berabartio', 'bsctestnet', + 'camptestnet', + // 'citreatestnet', 'connextsepolia', 'ecotestnet', 'eclipsetestnet', + 'formtestnet', 'fuji', 'holesky', + // 'hyperliquidevmtestnet', 'optimismsepolia', // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // 'plumetestnet', @@ -16,6 +21,8 @@ export const testnet4SupportedChainNames = [ 'scrollsepolia', 'sepolia', 'solanatestnet', + 'soneiumtestnet', + 'suavetoliman', 'superpositiontestnet', ] as const; diff --git a/typescript/infra/config/environments/testnet4/tokenPrices.json b/typescript/infra/config/environments/testnet4/tokenPrices.json index 8f2f1eb53..2f74606fe 100644 --- a/typescript/infra/config/environments/testnet4/tokenPrices.json +++ b/typescript/infra/config/environments/testnet4/tokenPrices.json @@ -1,17 +1,24 @@ { - "alfajores": "0.538515", - "arbitrumsepolia": "2651.43", - "basesepolia": "2651.43", - "bsctestnet": "608.49", - "connextsepolia": "2651.43", - "ecotestnet": "2651.43", - "eclipsetestnet": "2651.43", - "fuji": "27.33", - "holesky": "2651.43", - "optimismsepolia": "2651.43", - "polygonamoy": "0.405534", - "scrollsepolia": "2651.43", - "sepolia": "2651.43", - "solanatestnet": "144.13", - "superpositiontestnet": "0.999824" + "alfajores": "0.672791", + "arbitrumsepolia": "2580.94", + "basesepolia": "2580.94", + "berabartio": "10", + "bsctestnet": "589.38", + "camptestnet": "2580.94", + "citreatestnet": "63497", + "connextsepolia": "2580.94", + "ecotestnet": "2580.94", + "eclipsetestnet": "2580.94", + "formtestnet": "2580.94", + "fuji": "27.56", + "holesky": "2580.94", + "hyperliquidevmtestnet": "2580.94", + "optimismsepolia": "2580.94", + "polygonamoy": "0.412898", + "scrollsepolia": "2580.94", + "sepolia": "2580.94", + "solanatestnet": "150.38", + "soneiumtestnet": "2580.94", + "suavetoliman": "2580.94", + "superpositiontestnet": "10" } diff --git a/typescript/infra/config/environments/testnet4/validators.ts b/typescript/infra/config/environments/testnet4/validators.ts index e65968e60..ef74e8046 100644 --- a/typescript/infra/config/environments/testnet4/validators.ts +++ b/typescript/infra/config/environments/testnet4/validators.ts @@ -173,72 +173,124 @@ export const validatorChainConfig = ( 'sepolia', ), }, - plumetestnet: { + superpositiontestnet: { + interval: 1, + reorgPeriod: getReorgPeriod('superpositiontestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x1d3168504b23b73cdf9c27f13bb0a595d7f1a96a'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'superpositiontestnet', + ), + }, + optimismsepolia: { interval: 5, - reorgPeriod: getReorgPeriod('plumetestnet'), + reorgPeriod: getReorgPeriod('optimismsepolia'), validators: validatorsConfig( { - [Contexts.Hyperlane]: [ - '0xe765a214849f3ecdf00793b97d00422f2d408ea6', - '0xb59998f71efc65190a85ac5e81b66bd72a192a3b', - '0xc906470a73e6b5aad65a4ceb4acd73e3eaf80e2c', - ], - [Contexts.ReleaseCandidate]: [ - '0xe6e6aeecbf7755cdbc50c2683df9f2d100f6399d', - '0x27946c13a475233a3b1eb47f0bd0f7cdec3a3983', - '0x2596413213368475c96ddfb1ae26666d22093a8b', - ], + [Contexts.Hyperlane]: ['0x03efe4d0632ee15685d7e8f46dea0a874304aa29'], + [Contexts.ReleaseCandidate]: [], [Contexts.Neutron]: [], }, - 'plumetestnet', + 'optimismsepolia', ), }, - solanatestnet: { - interval: 1, - reorgPeriod: getReorgPeriod('solanatestnet'), + polygonamoy: { + interval: 5, + reorgPeriod: getReorgPeriod('polygonamoy'), validators: validatorsConfig( { - [Contexts.Hyperlane]: ['0xd4ce8fa138d4e083fc0e480cca0dbfa4f5f30bd5'], + [Contexts.Hyperlane]: ['0xf0290b06e446b320bd4e9c4a519420354d7ddccd'], [Contexts.ReleaseCandidate]: [], [Contexts.Neutron]: [], }, - 'solanatestnet', + 'polygonamoy', ), }, - superpositiontestnet: { - interval: 1, - reorgPeriod: getReorgPeriod('superpositiontestnet'), + hyperliquidevmtestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('hyperliquidevmtestnet'), validators: validatorsConfig( { - [Contexts.Hyperlane]: ['0x1d3168504b23b73cdf9c27f13bb0a595d7f1a96a'], + [Contexts.Hyperlane]: ['0xea673a92a23ca319b9d85cc16b248645cd5158da'], [Contexts.ReleaseCandidate]: [], [Contexts.Neutron]: [], }, - 'superpositiontestnet', + 'hyperliquidevmtestnet', ), }, - optimismsepolia: { + berabartio: { interval: 5, - reorgPeriod: getReorgPeriod('optimismsepolia'), + reorgPeriod: getReorgPeriod('berabartio'), validators: validatorsConfig( { - [Contexts.Hyperlane]: ['0x03efe4d0632ee15685d7e8f46dea0a874304aa29'], + [Contexts.Hyperlane]: ['0x541dd3cb282cf869d72883557badae245b63e1fd'], [Contexts.ReleaseCandidate]: [], [Contexts.Neutron]: [], }, - 'optimismsepolia', + 'berabartio', ), }, - polygonamoy: { + citreatestnet: { interval: 5, - reorgPeriod: getReorgPeriod('polygonamoy'), + reorgPeriod: getReorgPeriod('citreatestnet'), validators: validatorsConfig( { - [Contexts.Hyperlane]: ['0xf0290b06e446b320bd4e9c4a519420354d7ddccd'], + [Contexts.Hyperlane]: ['0x60d7380a41eb95c49be18f141efd2fde5e3dba20'], [Contexts.ReleaseCandidate]: [], [Contexts.Neutron]: [], }, - 'polygonamoy', + 'citreatestnet', + ), + }, + camptestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('camptestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x238f40f055a7ff697ea6dbff3ae943c9eae7a38e'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'camptestnet', + ), + }, + formtestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('formtestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x72ad7fddf16d17ff902d788441151982fa31a7bc'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'formtestnet', + ), + }, + soneiumtestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('soneiumtestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x2e2101020ccdbe76aeda1c27823b0150f43d0c63'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'soneiumtestnet', + ), + }, + suavetoliman: { + interval: 5, + reorgPeriod: getReorgPeriod('suavetoliman'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xf58f6e30aabba34e8dd7f79b3168507192e2cc9b'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'suavetoliman', ), }, }; diff --git a/typescript/infra/scripts/print-token-prices.ts b/typescript/infra/scripts/print-token-prices.ts index 5a3e848eb..730faff11 100644 --- a/typescript/infra/scripts/print-token-prices.ts +++ b/typescript/infra/scripts/print-token-prices.ts @@ -1,3 +1,5 @@ +import chalk from 'chalk'; + import { ChainMetadata } from '@hyperlane-xyz/sdk'; import { objMap, pick } from '@hyperlane-xyz/utils'; @@ -12,6 +14,12 @@ import { getArgs } from './agent-utils.js'; const CURRENCY = 'usd'; +const DEFAULT_PRICE = { + mainnet3: '1', + testnet4: '10', + test: '100', +}; + async function main() { const { environment } = await getArgs().argv; @@ -50,15 +58,26 @@ async function main() { const prices = objMap(ids, (_, id) => { const idData = idPrices[id]; + if (!idData) { - throw new Error( - `No data for ${id}, did you set gasCurrencyCoinGeckoId in the metadata?`, + console.warn( + chalk.yellow( + `No data for ${id}, using ${DEFAULT_PRICE[environment]} as a default`, + ), ); + return DEFAULT_PRICE[environment]; } + const price = idData[CURRENCY]; if (!price) { - throw new Error(`No ${CURRENCY} price for ${id}`); + console.warn( + chalk.yellow( + `No ${CURRENCY} price for ${id}, using ${DEFAULT_PRICE[environment]} as a default`, + ), + ); + return DEFAULT_PRICE[environment]; } + return price.toString(); }); diff --git a/typescript/infra/src/config/gas-oracle.ts b/typescript/infra/src/config/gas-oracle.ts index f992a141b..0f2e45a91 100644 --- a/typescript/infra/src/config/gas-oracle.ts +++ b/typescript/infra/src/config/gas-oracle.ts @@ -1,3 +1,4 @@ +import chalk from 'chalk'; import { BigNumber, ethers } from 'ethers'; import { @@ -54,7 +55,9 @@ function getLocalStorageGasOracleConfig( return remotes.reduce((agg, remote) => { let exchangeRate = getTokenExchangeRate(local, remote); if (!gasPrices[remote]) { - throw new Error(`No gas price found for chain ${remote}`); + // Will run into this case when adding new chains + console.warn(chalk.yellow(`No gas price set for ${remote}`)); + return agg; } // First parse as a number, so we have floating point precision. @@ -230,6 +233,13 @@ export function getTokenExchangeRateFromValues( remote: ChainName, tokenPrices: ChainMap, ): BigNumber { + // Workaround for chicken-egg dependency problem. + // We need to provide some default value here to satisfy the config on initial load, + // whilst knowing that it will get overwritten when a script actually gets run. + if (!tokenPrices[local] || !tokenPrices[remote]) { + return BigNumber.from(1); + } + const localValue = ethers.utils.parseUnits( tokenPrices[local], TOKEN_EXCHANGE_RATE_DECIMALS, diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index 5e43d8623..a602dd28c 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -80,6 +80,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0x82e3b437a2944e3ff00258c93e72cd1ba5e0e921'], }, + berabartio: { + threshold: 1, + validators: ['0x541dd3cb282cf869d72883557badae245b63e1fd'], + }, + bitlayer: { threshold: 2, validators: [ @@ -126,6 +131,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + camptestnet: { + threshold: 1, + validators: ['0x238f40f055a7ff697ea6dbff3ae943c9eae7a38e'], + }, + celo: { threshold: 3, validators: [ @@ -154,6 +164,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + citreatestnet: { + threshold: 1, + validators: ['0x60d7380a41eb95c49be18f141efd2fde5e3dba20'], + }, + connextsepolia: { threshold: 1, validators: ['0xffbbec8c499585d80ef69eb613db624d27e089ab'], @@ -255,6 +270,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + formtestnet: { + threshold: 1, + validators: ['0x72ad7fddf16d17ff902d788441151982fa31a7bc'], + }, + fraxtal: { threshold: 2, validators: [ @@ -297,6 +317,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0x7ab28ad88bb45867137ea823af88e2cb02359c03'], // TODO }, + hyperliquidevmtestnet: { + threshold: 1, + validators: ['0xea673a92a23ca319b9d85cc16b248645cd5158da'], + }, + inevm: { threshold: 2, validators: [ @@ -609,6 +634,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0xd4ce8fa138d4e083fc0e480cca0dbfa4f5f30bd5'], }, + soneiumtestnet: { + threshold: 1, + validators: ['0x2e2101020ccdbe76aeda1c27823b0150f43d0c63'], + }, + stride: { threshold: 6, validators: [ @@ -625,6 +655,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + suavetoliman: { + threshold: 1, + validators: ['0xf58f6e30aabba34e8dd7f79b3168507192e2cc9b'], + }, + superpositiontestnet: { threshold: 1, validators: ['0x1d3168504b23b73cdf9c27f13bb0a595d7f1a96a'], From bf53f087c368a7d620868999c11119f6d4b743de Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Thu, 26 Sep 2024 23:24:56 +0100 Subject: [PATCH 086/224] fix(relayer): dry-run before sending txs (#4565) ### Description Fixes a bug in the individual submission logic. There is a race condition where a message can become undeliverable between when it was simulated in the `prepare` step and when it's actually submitted. ### Context The bug was discovered as part of batched messages but affects chains without batching too. - when delivery fails inside batch submission simulation, we fall back to individual submission - individual submission doesn't simulate the tx outcome, and instead just submits directly - this is wrong, because the batch may cause messages to become undeliverable for long periods of time (such as when a mint cap is reached) - I believe simulation used to happen in the individual submission step, but we switched to using the already computed gas estimate from the IGP check in the `prepare` step, to save an RPC call - this results in senders being charged from their IGP allowance unnecessarily, and messages becoming undeliverable due to insufficient gas The correct flow requires three delivery simulations: 1. in the `prepare` step, to estimate gas and check the IGP policy 2. in the batch submission logic, to filter messages that are made invalid by earlier messages in the batch 3. right before submitting again, in case the batch caused the message to not be deliverable ### Solution Dry-run right before submitting an operation, and if it fails send it back to the prep queue --- rust/main/agents/relayer/src/msg/op_queue.rs | 2 +- .../agents/relayer/src/msg/op_submitter.rs | 60 ++++++++++++++++--- .../agents/relayer/src/msg/pending_message.rs | 25 +++++++- .../src/traits/pending_operation.rs | 5 +- 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/rust/main/agents/relayer/src/msg/op_queue.rs b/rust/main/agents/relayer/src/msg/op_queue.rs index 7ea122c61..30f78edda 100644 --- a/rust/main/agents/relayer/src/msg/op_queue.rs +++ b/rust/main/agents/relayer/src/msg/op_queue.rs @@ -196,7 +196,7 @@ pub mod test { /// Submit this operation to the blockchain and report if it was successful /// or not. - async fn submit(&mut self) { + async fn submit(&mut self) -> PendingOperationResult { todo!() } diff --git a/rust/main/agents/relayer/src/msg/op_submitter.rs b/rust/main/agents/relayer/src/msg/op_submitter.rs index bacc7f747..e72c5ef14 100644 --- a/rust/main/agents/relayer/src/msg/op_submitter.rs +++ b/rust/main/agents/relayer/src/msg/op_submitter.rs @@ -12,6 +12,7 @@ use hyperlane_core::BatchResult; use hyperlane_core::ConfirmReason::*; use hyperlane_core::PendingOperation; use hyperlane_core::PendingOperationStatus; +use hyperlane_core::ReprepareReason; use itertools::Either; use itertools::Itertools; use prometheus::{IntCounter, IntGaugeVec}; @@ -182,6 +183,7 @@ impl SerialSubmitter { &task_monitor, submit_task( domain.clone(), + prepare_queue.clone(), submit_queue, confirm_queue.clone(), max_batch_size, @@ -310,6 +312,7 @@ async fn prepare_task( #[instrument(skip_all, fields(%domain))] async fn submit_task( domain: HyperlaneDomain, + mut prepare_queue: OpQueue, mut submit_queue: OpQueue, mut confirm_queue: OpQueue, max_batch_size: u32, @@ -327,11 +330,11 @@ async fn submit_task( } std::cmp::Ordering::Equal => { let op = batch.pop().unwrap(); - submit_single_operation(op, &mut confirm_queue, &metrics).await; + submit_single_operation(op, &mut prepare_queue, &mut confirm_queue, &metrics).await; } std::cmp::Ordering::Greater => { OperationBatch::new(batch, domain.clone()) - .submit(&mut confirm_queue, &metrics) + .submit(&mut prepare_queue, &mut confirm_queue, &metrics) .await; } } @@ -340,12 +343,45 @@ async fn submit_task( #[instrument(skip(confirm_queue, metrics), ret, level = "debug")] async fn submit_single_operation( + mut op: QueueOperation, + prepare_queue: &mut OpQueue, + confirm_queue: &mut OpQueue, + metrics: &SerialSubmitterMetrics, +) { + let status = op.submit().await; + match status { + PendingOperationResult::Reprepare(reprepare_reason) => { + prepare_queue + .push(op, Some(PendingOperationStatus::Retry(reprepare_reason))) + .await; + } + PendingOperationResult::NotReady => { + // This `match` arm isn't expected to be hit, but it's here for completeness, + // hence the hardcoded `ReprepareReason` + prepare_queue + .push( + op, + Some(PendingOperationStatus::Retry( + ReprepareReason::ErrorSubmitting, + )), + ) + .await; + } + PendingOperationResult::Drop => { + // Not expected to hit this case in `submit`, but it's here for completeness + } + PendingOperationResult::Success | PendingOperationResult::Confirm(_) => { + confirm_op(op, confirm_queue, metrics).await + } + } +} + +async fn confirm_op( mut op: QueueOperation, confirm_queue: &mut OpQueue, metrics: &SerialSubmitterMetrics, ) { let destination = op.destination_domain().clone(); - op.submit().await; debug!(?op, "Operation submitted"); op.set_next_attempt_after(CONFIRM_DELAY); confirm_queue @@ -486,7 +522,12 @@ struct OperationBatch { } impl OperationBatch { - async fn submit(self, confirm_queue: &mut OpQueue, metrics: &SerialSubmitterMetrics) { + async fn submit( + self, + prepare_queue: &mut OpQueue, + confirm_queue: &mut OpQueue, + metrics: &SerialSubmitterMetrics, + ) { let excluded_ops = match self.try_submit_as_batch(metrics).await { Ok(batch_result) => { Self::handle_batch_result(self.operations, batch_result, confirm_queue).await @@ -500,7 +541,7 @@ impl OperationBatch { if !excluded_ops.is_empty() { warn!(excluded_ops=?excluded_ops, "Either the batch tx would revert, or the operations would revert in the batch. Falling back to serial submission."); OperationBatch::new(excluded_ops, self.domain) - .submit_serially(confirm_queue, metrics) + .submit_serially(prepare_queue, confirm_queue, metrics) .await; } } @@ -565,9 +606,14 @@ impl OperationBatch { } } - async fn submit_serially(self, confirm_queue: &mut OpQueue, metrics: &SerialSubmitterMetrics) { + async fn submit_serially( + self, + prepare_queue: &mut OpQueue, + confirm_queue: &mut OpQueue, + metrics: &SerialSubmitterMetrics, + ) { for op in self.operations.into_iter() { - submit_single_operation(op, confirm_queue, metrics).await; + submit_single_operation(op, prepare_queue, confirm_queue, metrics).await; } } } diff --git a/rust/main/agents/relayer/src/msg/pending_message.rs b/rust/main/agents/relayer/src/msg/pending_message.rs index 5d7d824b0..7abfd07cd 100644 --- a/rust/main/agents/relayer/src/msg/pending_message.rs +++ b/rust/main/agents/relayer/src/msg/pending_message.rs @@ -76,6 +76,9 @@ pub struct PendingMessage { #[new(default)] #[serde(skip_serializing)] submission_outcome: Option, + #[new(default)] + #[serde(skip_serializing)] + metadata: Option>, } impl Debug for PendingMessage { @@ -254,6 +257,7 @@ impl PendingOperation for PendingMessage { return self.on_reprepare(Some(err), ReprepareReason::ErrorBuildingMetadata); } }; + self.metadata = metadata.clone(); let Some(metadata) = metadata else { return self.on_reprepare::(None, ReprepareReason::CouldNotFetchMetadata); @@ -269,7 +273,7 @@ impl PendingOperation for PendingMessage { .process_estimate_costs(&self.message, &metadata) .await { - Ok(metadata) => metadata, + Ok(tx_cost_estimate) => tx_cost_estimate, Err(err) => { return self.on_reprepare(Some(err), ReprepareReason::ErrorEstimatingGas); } @@ -321,10 +325,10 @@ impl PendingOperation for PendingMessage { } #[instrument] - async fn submit(&mut self) { + async fn submit(&mut self) -> PendingOperationResult { if self.submitted { // this message has already been submitted, possibly not by us - return; + return PendingOperationResult::Success; } let state = self @@ -332,6 +336,19 @@ impl PendingOperation for PendingMessage { .clone() .expect("Pending message must be prepared before it can be submitted"); + // To avoid spending gas on a tx that will revert, dry-run just before submitting. + if let Some(metadata) = self.metadata.as_ref() { + if self + .ctx + .destination_mailbox + .process_estimate_costs(&self.message, metadata) + .await + .is_err() + { + return self.on_reprepare::(None, ReprepareReason::ErrorEstimatingGas); + } + } + // We use the estimated gas limit from the prior call to // `process_estimate_costs` to avoid a second gas estimation. let tx_outcome = self @@ -342,9 +359,11 @@ impl PendingOperation for PendingMessage { match tx_outcome { Ok(outcome) => { self.set_operation_outcome(outcome, state.gas_limit); + PendingOperationResult::Confirm(ConfirmReason::SubmittedBySelf) } Err(e) => { error!(error=?e, "Error when processing message"); + return PendingOperationResult::Reprepare(ReprepareReason::ErrorSubmitting); } } } diff --git a/rust/main/hyperlane-core/src/traits/pending_operation.rs b/rust/main/hyperlane-core/src/traits/pending_operation.rs index 599a0e400..9dfbd93c7 100644 --- a/rust/main/hyperlane-core/src/traits/pending_operation.rs +++ b/rust/main/hyperlane-core/src/traits/pending_operation.rs @@ -83,7 +83,7 @@ pub trait PendingOperation: Send + Sync + Debug + TryBatchAs { async fn prepare(&mut self) -> PendingOperationResult; /// Submit this operation to the blockchain - async fn submit(&mut self); + async fn submit(&mut self) -> PendingOperationResult; /// Set the outcome of the `submit` call fn set_submission_outcome(&mut self, outcome: TxOutcome); @@ -188,6 +188,9 @@ pub enum ReprepareReason { #[strum(to_string = "Error getting message metadata builder")] /// Error getting message metadata builder ErrorGettingMetadataBuilder, + #[strum(to_string = "Error submitting")] + /// Error submitting + ErrorSubmitting, #[strum(to_string = "Error building metadata")] /// Error building metadata ErrorBuildingMetadata, From f42a570e7f2a2e901bb2e3fe3d90e4afd2ef474e Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:55:30 +0100 Subject: [PATCH 087/224] chore: Update agent.ts (#4584) ### Description updates the image to include the relayer submission fix from https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4565 --- typescript/infra/config/environments/mainnet3/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 5565c0962..20bae5623 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -393,7 +393,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '5cb1787-20240924-192934', + tag: 'bf53f08-20240926-223824', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, From 6e787a9b3964a4892674f095709557b19763dc41 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Fri, 27 Sep 2024 20:04:10 +0100 Subject: [PATCH 088/224] feat: Generate cosmos account addresses for Injective (#4576) ### Description Injective uses different logic on generating account addresses from public key. It is implemented in this PR so that sender address is correctly generated from signer info of transaction. ### Backward compatibility Yes ### Testing Added unit tests Manual testing with Injective blockchain --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- rust/main/Cargo.lock | 101 ++++++++++-------- rust/main/Cargo.toml | 7 +- rust/main/chains/hyperlane-cosmos/Cargo.toml | 1 + .../main/chains/hyperlane-cosmos/src/error.rs | 11 +- .../hyperlane-cosmos/src/libs/account.rs | 33 ++++++ .../src/libs/account/tests.rs | 70 ++++++++++++ .../hyperlane-cosmos/src/libs/address.rs | 6 +- .../src/providers/cosmos/provider.rs | 66 +++++++++++- rust/main/utils/crypto/Cargo.toml | 14 +++ rust/main/utils/crypto/src/key.rs | 51 +++++++++ rust/main/utils/crypto/src/lib.rs | 4 + 11 files changed, 308 insertions(+), 56 deletions(-) create mode 100644 rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs create mode 100644 rust/main/utils/crypto/Cargo.toml create mode 100644 rust/main/utils/crypto/src/key.rs create mode 100644 rust/main/utils/crypto/src/lib.rs diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index f58a90d40..b47cce795 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -515,7 +515,7 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "itoa", @@ -545,7 +545,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.11", + "http 0.2.12", "http-body", "mime", "rustversion", @@ -1256,7 +1256,7 @@ dependencies = [ "coins-core 0.8.7", "digest 0.10.7", "hmac 0.12.1", - "k256 0.13.3", + "k256 0.13.4", "serde", "sha2 0.10.8", "thiserror", @@ -1564,7 +1564,7 @@ dependencies = [ "ecdsa 0.16.9", "eyre", "getrandom 0.2.15", - "k256 0.13.3", + "k256 0.13.4", "rand_core 0.6.4", "serde", "serde_json", @@ -1589,7 +1589,7 @@ checksum = "0f862b355f7e47711e0acfe6af92cb3fd8fd5936b66a9eaa338b51edabd1e77d" dependencies = [ "digest 0.10.7", "ed25519-zebra 3.1.0", - "k256 0.13.3", + "k256 0.13.4", "rand_core 0.6.4", "thiserror", ] @@ -1608,7 +1608,7 @@ dependencies = [ "digest 0.10.7", "ecdsa 0.16.9", "ed25519-zebra 4.0.3", - "k256 0.13.3", + "k256 0.13.4", "num-traits", "p256", "rand_core 0.6.4", @@ -1798,6 +1798,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto" +version = "0.1.0" +dependencies = [ + "elliptic-curve 0.13.8", + "hex 0.4.3", + "k256 0.13.4", + "thiserror", +] + [[package]] name = "crypto-bigint" version = "0.4.9" @@ -2505,7 +2515,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve 0.13.8", "rfc6979 0.4.0", - "signature 2.2.0", + "signature 2.0.0", "spki 0.7.3", ] @@ -2535,7 +2545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8 0.10.2", - "signature 2.2.0", + "signature 2.0.0", ] [[package]] @@ -3078,7 +3088,7 @@ dependencies = [ "getrandom 0.2.15", "hashers", "hex 0.4.3", - "http 0.2.11", + "http 0.2.12", "once_cell", "parking_lot 0.11.2", "pin-project", @@ -3484,7 +3494,7 @@ dependencies = [ "ecdsa 0.16.9", "ed25519-dalek 2.1.1", "fuel-types", - "k256 0.13.3", + "k256 0.13.4", "lazy_static", "p256", "rand 0.8.5", @@ -3979,7 +3989,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.11", + "http 0.2.12", "indexmap 2.5.0", "slab", "tokio", @@ -4074,7 +4084,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http 0.2.11", + "http 0.2.12", "httpdate", "mime", "sha1", @@ -4086,7 +4096,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http 0.2.11", + "http 0.2.12", ] [[package]] @@ -4230,9 +4240,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -4257,7 +4267,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.11", + "http 0.2.12", "pin-project-lite", ] @@ -4300,7 +4310,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "httparse", "httpdate", @@ -4322,7 +4332,7 @@ dependencies = [ "bytes", "futures", "headers", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-rustls 0.22.1", "rustls-native-certs 0.5.0", @@ -4357,7 +4367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.11", + "http 0.2.12", "hyper", "log", "rustls 0.21.12", @@ -4502,10 +4512,11 @@ dependencies = [ "bech32 0.9.1", "cosmrs", "cosmwasm-std 2.1.3", + "crypto", "derive-new", "futures", "hex 0.4.3", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-tls", "hyperlane-core", @@ -5091,16 +5102,16 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa 0.16.9", "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.8", - "signature 2.2.0", + "signature 2.0.0", ] [[package]] @@ -5480,7 +5491,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 0.2.11", + "http 0.2.12", "httparse", "log", "memchr", @@ -7027,7 +7038,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "hyper-rustls 0.24.2", @@ -7228,7 +7239,7 @@ dependencies = [ "hyperlane-cosmos", "hyperlane-cosmwasm-interface", "jobserver", - "k256 0.13.3", + "k256 0.13.4", "macro_rules_attribute", "maplit", "nix 0.26.4", @@ -7258,7 +7269,7 @@ dependencies = [ "bytes", "crc32fast", "futures", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-tls", "lazy_static", @@ -7330,7 +7341,7 @@ dependencies = [ "futures", "hex 0.4.3", "hmac 0.11.0", - "http 0.2.11", + "http 0.2.12", "hyper", "log", "md-5 0.9.1", @@ -8280,9 +8291,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.2.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", @@ -9391,7 +9402,7 @@ dependencies = [ "base64 0.13.1", "bytes", "chrono", - "http 0.2.11", + "http 0.2.12", "percent-encoding", "serde", "serde_json", @@ -9430,7 +9441,7 @@ dependencies = [ "ed25519-consensus", "flex-error", "futures", - "k256 0.13.3", + "k256 0.13.4", "num-traits", "once_cell", "prost 0.11.9", @@ -9441,7 +9452,7 @@ dependencies = [ "serde_json", "serde_repr", "sha2 0.10.8", - "signature 2.2.0", + "signature 2.0.0", "subtle", "subtle-encoding", "tendermint-proto 0.32.2 (git+https://github.com/hyperlane-xyz/tendermint-rs.git?branch=trevor/0.32.2-fork)", @@ -9507,7 +9518,7 @@ dependencies = [ "flex-error", "futures", "getrandom 0.2.15", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-proxy", "hyper-rustls 0.22.1", @@ -9563,18 +9574,18 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2 1.0.86", "quote 1.0.37", @@ -9891,7 +9902,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "hyper-timeout", @@ -9921,7 +9932,7 @@ dependencies = [ "base64 0.21.7", "bytes", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "hyper-timeout", @@ -10103,7 +10114,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "bytes", - "http 0.2.11", + "http 0.2.12", "httparse", "log", "rand 0.8.5", @@ -10375,7 +10386,7 @@ dependencies = [ "hyperlane-cosmos", "hyperlane-ethereum", "hyperlane-test", - "k256 0.13.3", + "k256 0.13.4", "prometheus", "reqwest", "serde", @@ -10458,7 +10469,7 @@ dependencies = [ "futures-channel", "futures-util", "headers", - "http 0.2.11", + "http 0.2.12", "hyper", "log", "mime", @@ -10948,7 +10959,7 @@ checksum = "acaf2e321fc6f853572b372962fa253cba1b62a0025116bb463ce3c00b4394dc" dependencies = [ "cfg-if", "futures", - "http 0.2.11", + "http 0.2.12", "humantime-serde", "hyper", "hyper-rustls 0.24.2", @@ -10994,7 +11005,7 @@ dependencies = [ "async-trait", "base64 0.13.1", "futures", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-rustls 0.24.2", "itertools 0.10.5", diff --git a/rust/main/Cargo.toml b/rust/main/Cargo.toml index 06619dcd4..3e2dec820 100644 --- a/rust/main/Cargo.toml +++ b/rust/main/Cargo.toml @@ -13,6 +13,7 @@ members = [ "hyperlane-test", "utils/abigen", "utils/backtrace-oneline", + "utils/crypto", "utils/hex", "utils/run-locally", ] @@ -68,10 +69,10 @@ futures-util = "0.3" generic-array = { version = "0.14", features = ["serde", "more_lengths"] } # Required for WASM support https://docs.rs/getrandom/latest/getrandom/#webassembly-support bech32 = "0.9.1" -elliptic-curve = "0.12.3" +elliptic-curve = "0.13.8" getrandom = { version = "0.2", features = ["js"] } hex = "0.4.3" -http = "*" +http = "0.2.12" hyper = "0.14" hyper-tls = "0.5.0" hyperlane-cosmwasm-interface = "=0.0.6-rc6" @@ -80,7 +81,7 @@ injective-std = "=0.1.5" itertools = "*" jobserver = "=0.1.26" jsonrpc-core = "18.0" -k256 = { version = "0.13.1", features = ["std", "ecdsa"] } +k256 = { version = "0.13.4", features = ["arithmetic", "std", "ecdsa"] } log = "0.4" macro_rules_attribute = "0.2" maplit = "1.0" diff --git a/rust/main/chains/hyperlane-cosmos/Cargo.toml b/rust/main/chains/hyperlane-cosmos/Cargo.toml index e8b1af668..ce936ec1f 100644 --- a/rust/main/chains/hyperlane-cosmos/Cargo.toml +++ b/rust/main/chains/hyperlane-cosmos/Cargo.toml @@ -14,6 +14,7 @@ base64 = { workspace = true } bech32 = { workspace = true } cosmrs = { workspace = true, features = ["cosmwasm", "tokio", "grpc", "rpc"] } cosmwasm-std = { workspace = true } +crypto = { path = "../../utils/crypto" } derive-new = { workspace = true } futures = { workspace = true } hex = { workspace = true } diff --git a/rust/main/chains/hyperlane-cosmos/src/error.rs b/rust/main/chains/hyperlane-cosmos/src/error.rs index abe61fd92..8ceacd601 100644 --- a/rust/main/chains/hyperlane-cosmos/src/error.rs +++ b/rust/main/chains/hyperlane-cosmos/src/error.rs @@ -1,6 +1,9 @@ +use std::fmt::Debug; + use cosmrs::proto::prost; + +use crypto::PublicKeyError; use hyperlane_core::ChainCommunicationError; -use std::fmt::Debug; /// Errors from the crates specific to the hyperlane-cosmos /// implementation. @@ -60,3 +63,9 @@ impl From for ChainCommunicationError { ChainCommunicationError::from_other(value) } } + +impl From for HyperlaneCosmosError { + fn from(value: PublicKeyError) -> Self { + HyperlaneCosmosError::PublicKeyError(value.to_string()) + } +} diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs index bac0fe4bc..7f471b211 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs @@ -1,7 +1,9 @@ use cosmrs::{crypto::PublicKey, AccountId}; +use hyperlane_cosmwasm_interface::types::keccak256_hash; use tendermint::account::Id as TendermintAccountId; use tendermint::public_key::PublicKey as TendermintPublicKey; +use crypto::decompress_public_key; use hyperlane_core::Error::Overflow; use hyperlane_core::{ChainCommunicationError, ChainResult, H256}; @@ -16,7 +18,18 @@ impl<'a> CosmosAccountId<'a> { Self { account_id } } + /// Calculate AccountId from public key depending on provided prefix pub fn account_id_from_pubkey(pub_key: PublicKey, prefix: &str) -> ChainResult { + match prefix { + "neutron" | "osmo" => Self::bitcoin_style(pub_key, prefix), + "inj" => Self::ethereum_style(pub_key, prefix), + _ => Err(HyperlaneCosmosError::CosmosError(cosmrs::Error::Crypto))?, + } + } + + /// Returns a Bitcoin style address: RIPEMD160(SHA256(pubkey)) + /// Source: `` + fn bitcoin_style(pub_key: PublicKey, prefix: &str) -> ChainResult { // Get the inner type let tendermint_pub_key = TendermintPublicKey::from(pub_key); // Get the RIPEMD160(SHA256(pub_key)) @@ -27,6 +40,23 @@ impl<'a> CosmosAccountId<'a> { Ok(account_id) } + + /// Returns an Ethereum style address: KECCAK256(pubkey)[20] + /// Parameter `pub_key` is a compressed public key. + fn ethereum_style(pub_key: PublicKey, prefix: &str) -> ChainResult { + let decompressed_public_key = decompress_public_key(&pub_key.to_bytes()) + .map_err(Into::::into)?; + + let hash = keccak256_hash(&decompressed_public_key[1..]); + + let mut bytes = [0u8; 20]; + bytes.copy_from_slice(&hash.as_slice()[12..]); + + let account_id = + AccountId::new(prefix, bytes.as_slice()).map_err(Into::::into)?; + + Ok(account_id) + } } impl TryFrom<&CosmosAccountId<'_>> for H256 { @@ -55,3 +85,6 @@ impl TryFrom> for H256 { (&account_id).try_into() } } + +#[cfg(test)] +mod tests; diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs new file mode 100644 index 000000000..d00c0019c --- /dev/null +++ b/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs @@ -0,0 +1,70 @@ +use cosmrs::crypto::PublicKey; +use cosmwasm_std::HexBinary; + +use crypto::decompress_public_key; + +use crate::libs::account::CosmosAccountId; + +const COMPRESSED_PUBLIC_KEY: &str = + "02962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f4"; +const INJECTIVE_ADDRESS: &str = "inj1m6ada382hfuxvuke4h9p4uswhn2qcca7mlg0dr"; +const NEUTRON_ADDRESS: &str = "neutron1mydju5alsmhnfsawy0j4lyns70l7qukgdgy45w"; + +#[test] +fn test_account_id() { + // given + let pub_key = compressed_public_key(); + + // when + let neutron_account_id = CosmosAccountId::account_id_from_pubkey(pub_key, "neutron").unwrap(); + let injective_account_id = CosmosAccountId::account_id_from_pubkey(pub_key, "inj").unwrap(); + + // then + assert_eq!(neutron_account_id.as_ref(), NEUTRON_ADDRESS); + assert_eq!(injective_account_id.as_ref(), INJECTIVE_ADDRESS); +} + +#[test] +fn test_bitcoin_style() { + // given + let compressed = compressed_public_key(); + let decompressed = decompressed_public_key(); + + // when + let from_compressed = CosmosAccountId::bitcoin_style(compressed, "neutron").unwrap(); + let from_decompressed = CosmosAccountId::bitcoin_style(decompressed, "neutron").unwrap(); + + // then + assert_eq!(from_compressed.as_ref(), NEUTRON_ADDRESS); + assert_eq!(from_decompressed.as_ref(), NEUTRON_ADDRESS); +} + +#[test] +fn test_ethereum_style() { + // given + let compressed = compressed_public_key(); + let decompressed = decompressed_public_key(); + + // when + let from_compressed = CosmosAccountId::ethereum_style(compressed, "inj").unwrap(); + let from_decompressed = CosmosAccountId::ethereum_style(decompressed, "inj").unwrap(); + + // then + assert_eq!(from_compressed.as_ref(), INJECTIVE_ADDRESS); + assert_eq!(from_decompressed.as_ref(), INJECTIVE_ADDRESS); +} + +fn compressed_public_key() -> PublicKey { + let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); + let tendermint = tendermint::PublicKey::from_raw_secp256k1(&hex).unwrap(); + let pub_key = PublicKey::from(tendermint); + pub_key +} + +fn decompressed_public_key() -> PublicKey { + let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); + let decompressed = decompress_public_key(&hex).unwrap(); + let tendermint = tendermint::PublicKey::from_raw_secp256k1(&decompressed).unwrap(); + let pub_key = PublicKey::from(tendermint); + pub_key +} diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs index 41a5ab6ab..78cb393de 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs @@ -20,8 +20,7 @@ pub struct CosmosAddress { } impl CosmosAddress { - /// Returns a Bitcoin style address: RIPEMD160(SHA256(pubkey)) - /// Source: `` + /// Calculates an account address depending on prefix pub fn from_pubkey(pubkey: PublicKey, prefix: &str) -> ChainResult { let account_id = CosmosAccountId::account_id_from_pubkey(pubkey, prefix)?; Self::from_account_id(account_id) @@ -35,8 +34,7 @@ impl CosmosAddress { Self::from_pubkey(pubkey, prefix) } - /// Returns a Bitcoin style address calculated from Bech32 encoding - /// Source: `` + /// Returns an account address calculated from Bech32 encoding pub fn from_account_id(account_id: AccountId) -> ChainResult { // Hex digest let digest = H256::try_from(&CosmosAccountId::new(&account_id))?; diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index 62931e69e..000495a75 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -1,8 +1,10 @@ +use std::str::FromStr; + use async_trait::async_trait; use cosmrs::cosmwasm::MsgExecuteContract; use cosmrs::crypto::PublicKey; -use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo}; -use cosmrs::{AccountId, Any, Coin, Tx}; +use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo, SignerPublicKey}; +use cosmrs::{proto, AccountId, Any, Coin, Tx}; use itertools::Itertools; use once_cell::sync::Lazy; use tendermint::hash::Algorithm; @@ -11,6 +13,7 @@ use tendermint_rpc::{client::CompatMode, Client, HttpClient}; use time::OffsetDateTime; use tracing::{error, warn}; +use crypto::decompress_public_key; use hyperlane_core::{ BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, TxnInfo, TxnReceiptInfo, H256, U256, @@ -25,6 +28,9 @@ use crate::{ConnectionConf, CosmosAmount, HyperlaneCosmosError, Signer}; /// Exponent value for atto units (10^-18). const ATTO_EXPONENT: u32 = 18; +/// Injective public key type URL for protobuf Any +const INJECTIVE_PUBLIC_KEY_TYPE_URL: &str = "/injective.crypto.v1beta1.ethsecp256k1.PubKey"; + /// Abstraction over a connection to a Cosmos chain #[derive(Debug, Clone)] pub struct CosmosProvider { @@ -93,7 +99,8 @@ impl CosmosProvider { HyperlaneCosmosError::PublicKeyError("no public key for default signer".to_owned()) })?; - let public_key = PublicKey::try_from(signer_public_key)?; + let key = self.normalize_public_key(signer_public_key)?; + let public_key = PublicKey::try_from(key)?; let account_id = CosmosAccountId::account_id_from_pubkey( public_key, @@ -103,6 +110,59 @@ impl CosmosProvider { Ok((account_id, signer_info.sequence)) } + fn normalize_public_key( + &self, + signer_public_key: SignerPublicKey, + ) -> ChainResult { + let public_key = match signer_public_key { + SignerPublicKey::Single(pk) => SignerPublicKey::from(pk), + SignerPublicKey::LegacyAminoMultisig(pk) => SignerPublicKey::from(pk), + SignerPublicKey::Any(pk) => { + if pk.type_url != PublicKey::ED25519_TYPE_URL + && pk.type_url != PublicKey::SECP256K1_TYPE_URL + && pk.type_url != INJECTIVE_PUBLIC_KEY_TYPE_URL + { + let msg = format!( + "can only normalize public keys with a known TYPE_URL: {}, {}, {}", + PublicKey::ED25519_TYPE_URL, + PublicKey::SECP256K1_TYPE_URL, + INJECTIVE_PUBLIC_KEY_TYPE_URL + ); + warn!(pk.type_url, msg); + Err(HyperlaneCosmosError::PublicKeyError(msg.to_owned()))? + } + + let pub_key = if pk.type_url == INJECTIVE_PUBLIC_KEY_TYPE_URL { + let any = Any { + type_url: PublicKey::SECP256K1_TYPE_URL.to_owned(), + value: pk.value, + }; + + let proto = proto::cosmos::crypto::secp256k1::PubKey::from_any(&any) + .map_err(Into::::into)?; + + let decompressed = decompress_public_key(&proto.key) + .map_err(|e| HyperlaneCosmosError::PublicKeyError(e.to_string()))?; + + let tendermint = tendermint::PublicKey::from_raw_secp256k1(&decompressed) + .ok_or_else(|| { + HyperlaneCosmosError::PublicKeyError( + "cannot create tendermint public key".to_owned(), + ) + })?; + + PublicKey::from(tendermint) + } else { + PublicKey::try_from(pk)? + }; + + SignerPublicKey::Single(pub_key) + } + }; + + Ok(public_key) + } + /// Calculates the sender and the nonce for the transaction. /// We use `payer` of the fees as the sender of the transaction, and we search for `payer` /// signature information to find the nonce. diff --git a/rust/main/utils/crypto/Cargo.toml b/rust/main/utils/crypto/Cargo.toml new file mode 100644 index 000000000..de5b64535 --- /dev/null +++ b/rust/main/utils/crypto/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "crypto" +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +publish.workspace = true +version.workspace = true + +[dependencies] +elliptic-curve = { workspace = true, features = ["sec1"] } +hex = { workspace = true } +k256 = { workspace = true } +thiserror = { workspace = true } diff --git a/rust/main/utils/crypto/src/key.rs b/rust/main/utils/crypto/src/key.rs new file mode 100644 index 000000000..601431f28 --- /dev/null +++ b/rust/main/utils/crypto/src/key.rs @@ -0,0 +1,51 @@ +use std::fmt::{Display, Formatter}; + +use elliptic_curve::sec1::ToEncodedPoint; + +#[derive(Debug, thiserror::Error)] +pub enum PublicKeyError { + Decode(String), +} + +impl Display for PublicKeyError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + +/// Decompresses public key of secp256k1 if it was compressed +/// +/// Public key can be expressed in compressed or decompressed forms. +/// Compressed form contains one byte as prefix and x component of the public key. +/// Decompressed form contains one byte as prefix, x and y components of the public key. +pub fn decompress_public_key(public_key: &[u8]) -> Result, PublicKeyError> { + let elliptic: elliptic_curve::PublicKey = + elliptic_curve::PublicKey::from_sec1_bytes(public_key) + .map_err(|e| PublicKeyError::Decode(e.to_string()))?; + + // if public key was compressed, encoding into the point will decompress it. + let point = elliptic.to_encoded_point(false); + let decompressed = point.to_bytes().to_vec(); + Ok(decompressed) +} + +#[cfg(test)] +mod tests { + use crate::key::decompress_public_key; + + #[test] + fn test_decompress_public_key() { + // given + let compressed = "02962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f4"; + let hex = hex::decode(compressed).unwrap(); + + // when + let decompressed = hex::encode(decompress_public_key(&hex).unwrap()); + + // then + assert_eq!( + "04962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f40cb1152fb9e61ec7493a0d9a35d2e8a57198e109613854abdd3be5603d504008", + decompressed + ); + } +} diff --git a/rust/main/utils/crypto/src/lib.rs b/rust/main/utils/crypto/src/lib.rs new file mode 100644 index 000000000..edd7a4f4d --- /dev/null +++ b/rust/main/utils/crypto/src/lib.rs @@ -0,0 +1,4 @@ +pub use key::decompress_public_key; +pub use key::PublicKeyError; + +mod key; From 330b0580e240f0e57f1b10574e7e901c5561e701 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:11:26 -0400 Subject: [PATCH 089/224] chore: enable citreatestnet + testnet igp fixes (#4583) chore: enable citreatestnet + igp fixes - enable citreatestnet - set chunk size to 999 - flat price for testnet tokens - avoids problem where chains that have a non-eth native gas token end up paying way higher IGP fees than required --- .registryrc | 2 +- rust/main/config/testnet_config.json | 42 +++++++++---------- .../config/environments/testnet4/agent.ts | 12 +++--- .../testnet4/aw-validators/hyperlane.json | 3 ++ .../config/environments/testnet4/funding.ts | 4 +- .../environments/testnet4/gasPrices.json | 14 +++---- .../testnet4/igp/verification.json | 1 + .../testnet4/supportedChainNames.ts | 2 +- .../testnet4/testrecipient/verification.json | 1 + .../environments/testnet4/tokenPrices.json | 39 +++++++++-------- 10 files changed, 59 insertions(+), 61 deletions(-) create mode 100644 typescript/infra/config/environments/testnet4/igp/verification.json create mode 100644 typescript/infra/config/environments/testnet4/testrecipient/verification.json diff --git a/.registryrc b/.registryrc index ff673418e..2c81d3cdd 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -3df435f02b4787a58faf3e3c7411e62959b6db38 +a87a555d19834d6d3dada72ccdcb3661ba9ff003 diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index 769aa6c9c..77617bb75 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -37,7 +37,7 @@ "interchainAccountIsm": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", "interchainAccountRouter": "0xEbA64c8a9b4a61a9210d5fe7E4375380999C821b", "interchainGasPaymaster": "0x44769b0f4a6f01339e131a691cc2eebbb519d297", - "interchainSecurityModule": "0x0a89d18D16Fd969b1f864B3354290d9c4aD91C4c", + "interchainSecurityModule": "0x83D62A2cA5609bA703c2685c557d72A64CB52173", "isTestnet": true, "mailbox": "0xEf9F292fcEBC3848bF4bB92a96a04F9ECBb78E59", "merkleTreeHook": "0x221FA9CBaFcd6c1C3d206571Cf4427703e023FFa", @@ -100,7 +100,7 @@ "from": 49690504 }, "interchainGasPaymaster": "0xc756cFc1b7d0d4646589EDf10eD54b201237F5e8", - "interchainSecurityModule": "0xB071d45FFDB9c6BC3D6d91dA6565786D93eB2D6f", + "interchainSecurityModule": "0xf6e44F2c394Bd4db6757a858BCF231BE8779D73D", "isTestnet": true, "mailbox": "0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8", "merkleTreeHook": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", @@ -165,7 +165,7 @@ "from": 13851043 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x8fE91D229bb2d4872E94D5130246A3E287E77c47", + "interchainSecurityModule": "0x85f5aE8393c3051057444eEaB78bA9567C95BCD1", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -232,7 +232,7 @@ "interchainAccountIsm": "0xa9D8Ec959F34272B1a56D09AF00eeee58970d3AE", "interchainAccountRouter": "0x6d2B3e304E58c2a19f1492E7cf15CaF63Ce6e0d2", "interchainGasPaymaster": "0x0dD20e410bdB95404f71c5a4e7Fa67B892A5f949", - "interchainSecurityModule": "0x8842eDc6080e6A37F72eEe64cdae9fE0bCa9AeB8", + "interchainSecurityModule": "0x07c5B572D29A70C308Ef96fA98a635fA22dA44c9", "isTestnet": true, "mailbox": "0xF9F6F5646F478d5ab4e20B0F910C92F1CCC9Cc6D", "merkleTreeHook": "0xc6cbF39A747f5E28d1bDc8D9dfDAb2960Abd5A8f", @@ -301,7 +301,7 @@ "from": 4950 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0xBD64f3dd712Ef0c372A8F9410c2296ff3AB7C3A4", + "interchainSecurityModule": "0xc6B9CA04fDB54E63Aff6B3617C2E0A1228a19C67", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -399,7 +399,7 @@ "from": 1606754 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x85f5aE8393c3051057444eEaB78bA9567C95BCD1", + "interchainSecurityModule": "0x6Cf48F7b26374a741EE5290ECB58b23cCA171baa", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -462,7 +462,7 @@ "interchainAccountIsm": "0xfaB4815BDC5c60c6bD625459C8577aFdD79D9311", "interchainAccountRouter": "0xeEF6933122894fF217a7dd07510b3D64b747e29b", "interchainGasPaymaster": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", - "interchainSecurityModule": "0x6E1eAddcA9708Af27c17b86DA132A27F316fF126", + "interchainSecurityModule": "0xd0FBdaEC5b7Beba18E23492F1d3A8a15f8685E6E", "isTestnet": true, "mailbox": "0x5b6CFf85442B851A8e6eaBd2A4E4507B5135B3B0", "merkleTreeHook": "0x9ff6ac3dAf63103620BBf76136eA1AFf43c2F612", @@ -528,7 +528,7 @@ "from": 1543015 }, "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9", - "interchainSecurityModule": "0x4F893EbE13724C6A2d2Cd34FAE509116c25b9B62", + "interchainSecurityModule": "0xa5A3004174cd16AB6C4e69a7558f4f84a51D2cfB", "isTestnet": true, "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc", "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE", @@ -590,7 +590,7 @@ "from": 15833917 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x85f5aE8393c3051057444eEaB78bA9567C95BCD1", + "interchainSecurityModule": "0x6Cf48F7b26374a741EE5290ECB58b23cCA171baa", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -715,7 +715,7 @@ "from": 10634605 }, "interchainGasPaymaster": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", - "interchainSecurityModule": "0x32247eBC716c3B8bB5710c0b7CEb4D3a2A9A6205", + "interchainSecurityModule": "0x782Dc499C9b9EE59e79D243322beC5b03e017819", "isTestnet": true, "mailbox": "0x54148470292C24345fb828B003461a9444414517", "merkleTreeHook": "0xddf4C3e791caCaFd26D7fb275549739B38ae6e75", @@ -787,7 +787,7 @@ "interchainAccountIsm": "0xE023239c8dfc172FF008D8087E7442d3eBEd9350", "interchainAccountRouter": "0xe17c37212d785760E8331D4A4395B17b34Ba8cDF", "interchainGasPaymaster": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", - "interchainSecurityModule": "0xacc87264e624bA17d4116800BbA6178a3378A9C8", + "interchainSecurityModule": "0xb0ED7B7CD2572D45f1439069a2B973d8Dc0C5970", "isTestnet": true, "mailbox": "0x3C5154a193D6e2955650f9305c8d80c18C814A68", "merkleTreeHook": "0x863E8c26621c52ACa1849C53500606e73BA272F0", @@ -828,9 +828,6 @@ "testRecipient": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", "testTokenRecipient": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "gasPrice": 500000000 - }, "validatorAnnounce": "0x527768930D889662Fe7ACF64294871e86e4C2381", "staticMerkleRootWeightedMultisigIsmFactory": "0x339B46496D60b1b6B42e9715DeD8B3D2154dA0Bb", "staticMessageIdWeightedMultisigIsmFactory": "0x63dFf524F1c7361f4F1bf07D658Bf7f2d5Dd5B20", @@ -868,7 +865,7 @@ "interchainAccountIsm": "0x83a3068B719F764d413625dA77468ED74789ae02", "interchainAccountRouter": "0x8e131c8aE5BF1Ed38D05a00892b6001a7d37739d", "interchainGasPaymaster": "0x6f2756380FD49228ae25Aa7F2817993cB74Ecc56", - "interchainSecurityModule": "0x932C1D184b3A792c5470f700fBB60c35FB86D9eD", + "interchainSecurityModule": "0x5E01E8FEc4733a8e113c21EF75f5bd793B7eE8fe", "isTestnet": true, "mailbox": "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766", "merkleTreeHook": "0x4917a9746A7B6E0A57159cCb7F5a6744247f2d0d", @@ -978,7 +975,7 @@ "from": 3111622 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0xBD64f3dd712Ef0c372A8F9410c2296ff3AB7C3A4", + "interchainSecurityModule": "0xc6B9CA04fDB54E63Aff6B3617C2E0A1228a19C67", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -1059,7 +1056,7 @@ "interchainAccountIsm": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", "interchainAccountRouter": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", "interchainGasPaymaster": "0x04438ef7622f5412f82915F59caD4f704C61eA48", - "interchainSecurityModule": "0xd38BAC111B9C96953fddBA8fA52C90a2bD99dC45", + "interchainSecurityModule": "0x58B923EE9F79479E3cf226fCC32EdF42079A56b1", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", "pausableHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", @@ -1119,7 +1116,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1183,7 +1180,7 @@ "interchainAccountIsm": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", "interchainAccountRouter": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", "interchainGasPaymaster": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", - "interchainSecurityModule": "0xb6D42522D79897d776966955fe4a2558BB1E0B7c", + "interchainSecurityModule": "0xe51dbFbD86a345a818dc93ab8589ab8dB94ab593", "mailbox": "0xB08d78F439e55D02C398519eef61606A5926245F", "merkleTreeHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", "pausableHook": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c", @@ -1202,6 +1199,7 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", "index": { + "chunk": 999, "from": 334706 } }, @@ -1243,7 +1241,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1367,7 +1365,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1427,7 +1425,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x77d4B4090B666d84b4451C7425682B8F51Dbd827", + "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index 0705dd7ee..d4a83d81a 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -47,7 +47,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< berabartio: true, bsctestnet: true, camptestnet: true, - // citreatestnet: false, + citreatestnet: true, connextsepolia: true, ecotestnet: true, eclipsetestnet: false, @@ -73,7 +73,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< berabartio: true, bsctestnet: true, camptestnet: true, - // citreatestnet: false, + citreatestnet: true, connextsepolia: true, ecotestnet: true, eclipsetestnet: false, @@ -99,7 +99,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< berabartio: true, bsctestnet: true, camptestnet: true, - // citreatestnet: false, + citreatestnet: true, connextsepolia: false, ecotestnet: true, // Cannot scrape non-EVM chains @@ -197,7 +197,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'a436832-20240925-232333', + tag: '6c45a05-20240927-172800', }, blacklist: [...releaseCandidateHelloworldMatchingList, ...relayBlacklist], gasPaymentEnforcement, @@ -219,7 +219,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'a436832-20240925-232333', + tag: '6c45a05-20240927-172800', }, chains: validatorChainConfig(Contexts.Hyperlane), resources: validatorResources, @@ -228,7 +228,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'a436832-20240925-232333', + tag: '6c45a05-20240927-172800', }, resources: scraperResources, }, diff --git a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json index 93ce9742f..2d78729bf 100644 --- a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json @@ -25,6 +25,9 @@ "camptestnet": { "validators": ["0x238f40f055a7ff697ea6dbff3ae943c9eae7a38e"] }, + "citreatestnet": { + "validators": ["0x60d7380a41eb95c49be18f141efd2fde5e3dba20"] + }, "connextsepolia": { "validators": ["0xffbbec8c499585d80ef69eb613db624d27e089ab"] }, diff --git a/typescript/infra/config/environments/testnet4/funding.ts b/typescript/infra/config/environments/testnet4/funding.ts index a7227c27c..07821e157 100644 --- a/typescript/infra/config/environments/testnet4/funding.ts +++ b/typescript/infra/config/environments/testnet4/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: 'a436832-20240925-232318', + tag: '2bb7168-20240927-154029', }, // We're currently using the same deployer key as testnet2. // To minimize nonce clobbering we offset the key funder cron @@ -32,7 +32,7 @@ export const keyFunderConfig: KeyFunderConfig< berabartio: '0.1', bsctestnet: '5', camptestnet: '0.1', - // citreatestnet: '0.001', + citreatestnet: '0.001', connextsepolia: '1', ecotestnet: '0.02', // no funding for solana diff --git a/typescript/infra/config/environments/testnet4/gasPrices.json b/typescript/infra/config/environments/testnet4/gasPrices.json index 3e420afb0..c61aed013 100644 --- a/typescript/infra/config/environments/testnet4/gasPrices.json +++ b/typescript/infra/config/environments/testnet4/gasPrices.json @@ -12,7 +12,7 @@ "decimals": 9 }, "berabartio": { - "amount": "0.001000009", + "amount": "0.010488335", "decimals": 9 }, "bsctestnet": { @@ -24,7 +24,7 @@ "decimals": 9 }, "citreatestnet": { - "amount": "1.01", + "amount": "1.0", "decimals": 9 }, "connextsepolia": { @@ -48,11 +48,7 @@ "decimals": 9 }, "holesky": { - "amount": "0.783743361", - "decimals": 9 - }, - "hyperliquidevmtestnet": { - "amount": "0.000000007", + "amount": "0.858734023", "decimals": 9 }, "optimismsepolia": { @@ -64,11 +60,11 @@ "decimals": 9 }, "scrollsepolia": { - "amount": "0.497427713", + "amount": "1", "decimals": 9 }, "sepolia": { - "amount": "148.376099624", + "amount": "277.866557179", "decimals": 9 }, "solanatestnet": { diff --git a/typescript/infra/config/environments/testnet4/igp/verification.json b/typescript/infra/config/environments/testnet4/igp/verification.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/typescript/infra/config/environments/testnet4/igp/verification.json @@ -0,0 +1 @@ +{} diff --git a/typescript/infra/config/environments/testnet4/supportedChainNames.ts b/typescript/infra/config/environments/testnet4/supportedChainNames.ts index 5078cb18d..ad4d18cb2 100644 --- a/typescript/infra/config/environments/testnet4/supportedChainNames.ts +++ b/typescript/infra/config/environments/testnet4/supportedChainNames.ts @@ -6,7 +6,7 @@ export const testnet4SupportedChainNames = [ 'berabartio', 'bsctestnet', 'camptestnet', - // 'citreatestnet', + 'citreatestnet', 'connextsepolia', 'ecotestnet', 'eclipsetestnet', diff --git a/typescript/infra/config/environments/testnet4/testrecipient/verification.json b/typescript/infra/config/environments/testnet4/testrecipient/verification.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/typescript/infra/config/environments/testnet4/testrecipient/verification.json @@ -0,0 +1 @@ +{} diff --git a/typescript/infra/config/environments/testnet4/tokenPrices.json b/typescript/infra/config/environments/testnet4/tokenPrices.json index 2f74606fe..234899427 100644 --- a/typescript/infra/config/environments/testnet4/tokenPrices.json +++ b/typescript/infra/config/environments/testnet4/tokenPrices.json @@ -1,24 +1,23 @@ { - "alfajores": "0.672791", - "arbitrumsepolia": "2580.94", - "basesepolia": "2580.94", + "alfajores": "10", + "arbitrumsepolia": "10", + "basesepolia": "10", "berabartio": "10", - "bsctestnet": "589.38", - "camptestnet": "2580.94", - "citreatestnet": "63497", - "connextsepolia": "2580.94", - "ecotestnet": "2580.94", - "eclipsetestnet": "2580.94", - "formtestnet": "2580.94", - "fuji": "27.56", - "holesky": "2580.94", - "hyperliquidevmtestnet": "2580.94", - "optimismsepolia": "2580.94", - "polygonamoy": "0.412898", - "scrollsepolia": "2580.94", - "sepolia": "2580.94", - "solanatestnet": "150.38", - "soneiumtestnet": "2580.94", - "suavetoliman": "2580.94", + "bsctestnet": "10", + "camptestnet": "10", + "citreatestnet": "10", + "connextsepolia": "10", + "ecotestnet": "10", + "eclipsetestnet": "10", + "formtestnet": "10", + "fuji": "10", + "holesky": "10", + "optimismsepolia": "10", + "polygonamoy": "10", + "scrollsepolia": "10", + "sepolia": "10", + "solanatestnet": "10", + "soneiumtestnet": "10", + "suavetoliman": "10", "superpositiontestnet": "10" } From bd68ae01e2e6aaaff3fc9b2a3189869f92923677 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:32:32 +0100 Subject: [PATCH 090/224] chore: check if HEAD is behind main before deploying agents (#4593) chore: check if HEAD is behind main before deploying agents ![image](https://github.com/user-attachments/assets/9c2b5f9c-d037-42c7-be44-daf97fc37709) ![image](https://github.com/user-attachments/assets/df52f9f7-5962-4b60-b75b-e4cc87a9897f) --- .../infra/scripts/agents/deploy-agents.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/typescript/infra/scripts/agents/deploy-agents.ts b/typescript/infra/scripts/agents/deploy-agents.ts index 98981b0b5..44443dd84 100644 --- a/typescript/infra/scripts/agents/deploy-agents.ts +++ b/typescript/infra/scripts/agents/deploy-agents.ts @@ -1,9 +1,52 @@ +import { confirm } from '@inquirer/prompts'; +import chalk from 'chalk'; +import { execSync } from 'child_process'; + import { createAgentKeysIfNotExists } from '../../src/agents/key-utils.js'; import { HelmCommand } from '../../src/utils/helm.js'; import { getConfigsBasedOnArgs } from '../core-utils.js'; import { AgentCli } from './utils.js'; +async function fetchLatestMain() { + try { + console.log( + chalk.grey.italic('Fetching latest changes from origin/main...'), + ); + execSync('git fetch origin main', { stdio: 'inherit' }); + console.log(chalk.grey.italic('Fetch completed successfully.')); + } catch (error) { + console.error(chalk.red('Error fetching from origin/main:', error)); + process.exit(1); + } +} + +async function getCommitsBehindMain(): Promise { + // Fetch latest changes before checking if current branch is up-to-date + await fetchLatestMain(); + + try { + console.log( + chalk.grey.italic( + 'Checking if current branch is up-to-date with origin/main...', + ), + ); + const execResult = execSync( + 'git rev-list --left-right --count origin/main...HEAD', + ); + + // The output of the git command is something like: + // $ git rev-list --left-right --count origin/main...HEAD + // 0 2 + // We only care about the first number, which is the number of commits behind origin/main. + const [behindCount] = execResult.toString().trim().split('\t'); + return parseInt(behindCount); + } catch (error) { + console.error(chalk.red('Error checking git status:', error)); + process.exit(1); + } +} + async function main() { // Note the create-keys script should be ran prior to running this script. // At the moment, `runAgentHelmCommand` has the side effect of creating keys / users @@ -15,6 +58,29 @@ async function main() { const { agentConfig } = await getConfigsBasedOnArgs(); await createAgentKeysIfNotExists(agentConfig); + // Check if current branch is up-to-date with the main branch + const commitsBehind = await getCommitsBehindMain(); + + // If the current branch is not up-to-date with origin/main, prompt the user to continue + if (commitsBehind > 0) { + const shouldContinue = await confirm({ + message: chalk.yellow.bold( + `Warning: Current branch is ${commitsBehind} commit${ + commitsBehind === 1 ? '' : 's' + } behind origin/main. Are you sure you want to continue?`, + ), + default: false, + }); + if (!shouldContinue) { + console.log(chalk.red.bold('Exiting...')); + process.exit(1); + } + } else { + console.log( + chalk.green.bold('Current branch is up-to-date with origin/main.'), + ); + } + await new AgentCli().runHelmCommand(HelmCommand.InstallOrUpgrade); } From d010772bb87aaaf7496cedbff883ae033359e72d Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:56:50 +0100 Subject: [PATCH 091/224] chore: delete test-skipped workflow (#4601) chore: delete test-skipped workflow - despite recent changes to improve filtering for MD files, our test/test-skipped triggers are still throwing up problems e.g. https://canary.discord.com/channels/935678348330434570/935678739663192184/1290706562796617728 - given a MD-only change is unlikely, and we're likely to have MD files for changesets more often than not, better to remove test-skipped altogether until it becomes essential to skip tests - given our CI has gotten cheaper+faster lately, not a huge overhead to run for MD-only changes --- .github/workflows/test-skipped.yml | 95 ------------------------------ .github/workflows/test.yml | 6 -- 2 files changed, 101 deletions(-) delete mode 100644 .github/workflows/test-skipped.yml diff --git a/.github/workflows/test-skipped.yml b/.github/workflows/test-skipped.yml deleted file mode 100644 index c8dc05e69..000000000 --- a/.github/workflows/test-skipped.yml +++ /dev/null @@ -1,95 +0,0 @@ -# This is here to satisfy the PR requirements when only markdown changes occur. -name: test - -on: - # Auto-pass tests if only md files are changed - push: - branches: [main] - paths: - - '!**/*' - - '**/*.md' - # Auto-pass tests if only md files are changed - pull_request: - branches: - - '*' - paths: - - '!**/*' - - '**/*.md' - -concurrency: - group: e2e-${{ github.ref }} - cancel-in-progress: ${{ github.ref_name != 'main' }} - -jobs: - yarn-install: - runs-on: ubuntu-latest - steps: - - name: Instant pass - run: echo "yarn-install job passed" - - lint-prettier: - runs-on: ubuntu-latest - steps: - - name: Instant pass - run: echo "lint-prettier job passed" - - yarn-test: - runs-on: ubuntu-latest - steps: - - name: Instant pass - run: echo "yarn-test job passed" - - agent-configs: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - environment: [mainnet3, testnet4] - steps: - - name: Instant pass - run: echo "agent-configs job passed" - - e2e-matrix: - runs-on: ubuntu-latest - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main') || github.event_name == 'merge_group' - strategy: - matrix: - e2e-type: [cosmwasm, non-cosmwasm] - steps: - - name: Instant pass - run: echo "e2e-matrix job passed" - - cli-advanced-e2e: - runs-on: ubuntu-latest - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main') || github.event_name == 'merge_group' - strategy: - matrix: - include: - - test-type: preset_hook_enabled - - test-type: configure_hook_enabled - - test-type: pi_with_core_chain - steps: - - name: Instant pass - run: echo "cli-advanced-e2e job passed" - - env-test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - environment: [mainnet3] - chain: [ethereum, arbitrum, optimism, inevm, viction] - module: [core, igp] - include: - - environment: testnet4 - chain: sepolia - module: core - steps: - - name: Instant pass - run: echo "env-test job passed" - - coverage: - runs-on: ubuntu-latest - steps: - - name: Instant pass - run: echo "coverage job passed" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2e3516326..e6fcb5b6d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,16 +4,10 @@ on: # Triggers the workflow on pushes to main branch, ignoring md files push: branches: [main] - paths: - - '**/*' - - '!**/*.md' # Triggers on pull requests, ignoring md files pull_request: branches: - '*' - paths: - - '**/*' - - '!**/*.md' merge_group: workflow_dispatch: From b04dd9a8de40dc30c4573090eee5985e073465c0 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Wed, 2 Oct 2024 13:54:19 +0100 Subject: [PATCH 092/224] chore: update Eclipse related gas oracles (#4591) ### Description Updates some gas oracles. Before change: - All exchange rates were set to 10, gas prices 1, and token decimals 9, which surprisingly wasn't so inaccurate - Costs before were as follows: - Solana -> Eclipse - On Solana, IGP paid 0.000431 SOL * $154 = $0.066374 - On Eclipse delivery, relayer 0.00001263 ETH * 2604 = $0.03288 plus ATA payer 0.000020264 ETH * 2604 = $0.05276 - Eclipse -> Solana - On eclipse, igp paid 0.000268 ETH * 2604 = $0.6978 - on solana delivery, relayer 0.0017926 SOL * 154 = 0.27 plus ata payer 0.00203928 SOL * 154 = 0.314 - Eclipse -> Ethereum - on eclipse, igp paid 0.000248339 ETH * 2604 = 0.6466 - on Ethereum delivery, relayer 0.002222450816005406 ETH * 2604 = 5.78 - Ethereum -> Eclipse - on ethereum, IGP paid 0.00086103 ETH * 2604 = $2.24 - on eclipse delivery, same as above solana - Costs after: - Solana -> Eclipse: now charges approx 33 cents - Eclipse -> Solana: now charges approx $1.20 - Eclipse -> Ethereum: now charges approx $10 - Ethereum -> Eclipse: unchanged Exchange rates and gas prices are more or less taken from looking at exchange rates, applying a premium, and figuring out approx gas prices on SVM by looking at amount paid divided by compute units used ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../gas-oracle-configs-eclipsemainnet.json | 20 +++++++++++++++++++ .../mainnet3/gas-oracle-configs.json | 1 - .../gas-oracle-configs-solanamainnet.json | 11 ++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json delete mode 100644 rust/sealevel/environments/mainnet3/gas-oracle-configs.json create mode 100644 rust/sealevel/environments/mainnet3/solanamainnet/gas-oracle-configs-solanamainnet.json diff --git a/rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json b/rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json new file mode 100644 index 000000000..95b108c96 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json @@ -0,0 +1,20 @@ +[ + { + "domain": 1, + "gasOracle": { + "type": "remoteGasData", + "tokenExchangeRate": "15000000000000000000", + "gasPrice": "10000000000", + "tokenDecimals": 18 + } + }, + { + "domain": 1399811149, + "gasOracle": { + "type": "remoteGasData", + "tokenExchangeRate": "887000000000000000", + "gasPrice": "15", + "tokenDecimals": 9 + } + } +] diff --git a/rust/sealevel/environments/mainnet3/gas-oracle-configs.json b/rust/sealevel/environments/mainnet3/gas-oracle-configs.json deleted file mode 100644 index 0637a088a..000000000 --- a/rust/sealevel/environments/mainnet3/gas-oracle-configs.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet3/solanamainnet/gas-oracle-configs-solanamainnet.json b/rust/sealevel/environments/mainnet3/solanamainnet/gas-oracle-configs-solanamainnet.json new file mode 100644 index 000000000..44f00e80a --- /dev/null +++ b/rust/sealevel/environments/mainnet3/solanamainnet/gas-oracle-configs-solanamainnet.json @@ -0,0 +1,11 @@ +[ + { + "domain": 1408864445, + "gasOracle": { + "type": "remoteGasData", + "tokenExchangeRate": "25036363636360000000", + "gasPrice": "2", + "tokenDecimals": 9 + } + } +] From 3c8c68856d241ea787dcb71810fc5c9a428bc336 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Wed, 2 Oct 2024 12:07:11 -0400 Subject: [PATCH 093/224] fix(CLI): do not double info log approval requirement (#4605) ### Description Got this log during `warp send` ``` Approval is required for transfer of deUSD Approval required for transfer of deUSD Approval is required for transfer of deUSD Approval required for transfer of deUSD ``` --- typescript/sdk/src/warp/WarpCore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/sdk/src/warp/WarpCore.ts b/typescript/sdk/src/warp/WarpCore.ts index 753045908..16903b5fa 100644 --- a/typescript/sdk/src/warp/WarpCore.ts +++ b/typescript/sdk/src/warp/WarpCore.ts @@ -528,7 +528,7 @@ export class WarpCore { token.addressOrDenom, amount, ); - this.logger.info( + this.logger.debug( `Approval is${isRequired ? '' : ' not'} required for transfer of ${ token.symbol }`, From 22871425d6119761f7cc33d8255eb71e31c72a50 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Thu, 3 Oct 2024 12:24:54 +0100 Subject: [PATCH 094/224] feat: Dispatch messages before and after start of the agents (#4604) ### Description Dispatch messages before and after start of the agents so that we test both forward and backward looking sequence based indexers. ### Related issues - Successfully scrape Cosmos chains in e2e test #3355 ### Backward compatibility Yes ### Testing - E2E Cosmos Test - Manual check on E2E Cosmos Test logs --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- rust/main/utils/run-locally/src/cosmos/mod.rs | 93 +++++++++++-------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/rust/main/utils/run-locally/src/cosmos/mod.rs b/rust/main/utils/run-locally/src/cosmos/mod.rs index 2b0ab06b7..d78685333 100644 --- a/rust/main/utils/run-locally/src/cosmos/mod.rs +++ b/rust/main/utils/run-locally/src/cosmos/mod.rs @@ -463,6 +463,12 @@ fn run_locally() { .unwrap() ); + // count all the dispatched messages + let mut dispatched_messages = 0; + + // dispatch the first batch of messages (before agents start) + dispatched_messages += dispatch(&osmosisd, linker, &nodes); + let config_dir = tempdir().unwrap(); // export agent config @@ -525,9 +531,51 @@ fn run_locally() { let starting_relayer_balance: f64 = agent_balance_sum(hpl_rly_metrics_port).unwrap(); - // dispatch messages - let mut dispatched_messages = 0; + // dispatch the second batch of messages (after agents start) + dispatched_messages += dispatch(&osmosisd, linker, &nodes); + + let _stack = CosmosHyperlaneStack { + validators: hpl_val.into_iter().map(|v| v.join()).collect(), + relayer: hpl_rly.join(), + scraper: hpl_scr.join(), + postgres, + }; + + // Mostly copy-pasta from `rust/main/utils/run-locally/src/main.rs` + // TODO: refactor to share code + let loop_start = Instant::now(); + let mut failure_occurred = false; + loop { + // look for the end condition. + if termination_invariants_met( + hpl_rly_metrics_port, + hpl_scr_metrics_port, + dispatched_messages, + starting_relayer_balance, + ) + .unwrap_or(false) + { + // end condition reached successfully + break; + } else if (Instant::now() - loop_start).as_secs() > TIMEOUT_SECS { + // we ran out of time + log!("timeout reached before message submission was confirmed"); + failure_occurred = true; + break; + } + + sleep(Duration::from_secs(5)); + } + if failure_occurred { + panic!("E2E tests failed"); + } else { + log!("E2E tests passed"); + } +} + +fn dispatch(osmosisd: &Path, linker: &str, nodes: &[CosmosNetwork]) -> u32 { + let mut dispatched_messages = 0; for node in nodes.iter() { let targets = nodes .iter() @@ -545,7 +593,7 @@ fn run_locally() { for target in targets { dispatched_messages += 1; let cli = OsmosisCLI::new( - osmosisd.clone(), + osmosisd.to_path_buf(), node.launch_resp.home_path.to_str().unwrap(), ); @@ -574,44 +622,7 @@ fn run_locally() { } } - let _stack = CosmosHyperlaneStack { - validators: hpl_val.into_iter().map(|v| v.join()).collect(), - relayer: hpl_rly.join(), - scraper: hpl_scr.join(), - postgres, - }; - - // Mostly copy-pasta from `rust/main/utils/run-locally/src/main.rs` - // TODO: refactor to share code - let loop_start = Instant::now(); - let mut failure_occurred = false; - loop { - // look for the end condition. - if termination_invariants_met( - hpl_rly_metrics_port, - hpl_scr_metrics_port, - dispatched_messages, - starting_relayer_balance, - ) - .unwrap_or(false) - { - // end condition reached successfully - break; - } else if (Instant::now() - loop_start).as_secs() > TIMEOUT_SECS { - // we ran out of time - log!("timeout reached before message submission was confirmed"); - failure_occurred = true; - break; - } - - sleep(Duration::from_secs(5)); - } - - if failure_occurred { - panic!("E2E tests failed"); - } else { - log!("E2E tests passed"); - } + dispatched_messages } fn termination_invariants_met( From 3c819c777e3ac5938e990b8a296e42f5a7a0d5a3 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 3 Oct 2024 13:48:06 +0100 Subject: [PATCH 095/224] revert: "feat: Generate cosmos account addresses for Injective" (#4615) Reverts hyperlane-xyz/hyperlane-monorepo#4576 context: https://discord.com/channels/935678348330434570/1291354470730436680/1291357041624875010 > The problem is that Injective supports both "normal cosmos" signing with the bitcoin style address, and also ethereum style addresses. They disambiguate depending on the type of the pubkey that's signed in the tx > The relayer signs things using a bitcoin style address on Injective bc this was easier than making code changes to have it do ethereum-style (which isn't supported easily out of the box with the cosmos libs we use) > So we want the relayer account balance metric to look at the bitcoin-style address relating to our relayer key, not the Ethereum-style one at least this is the theory behind what happened --- rust/main/Cargo.lock | 101 ++++++++---------- rust/main/Cargo.toml | 7 +- rust/main/chains/hyperlane-cosmos/Cargo.toml | 1 - .../main/chains/hyperlane-cosmos/src/error.rs | 11 +- .../hyperlane-cosmos/src/libs/account.rs | 33 ------ .../src/libs/account/tests.rs | 70 ------------ .../hyperlane-cosmos/src/libs/address.rs | 6 +- .../src/providers/cosmos/provider.rs | 66 +----------- rust/main/utils/crypto/Cargo.toml | 14 --- rust/main/utils/crypto/src/key.rs | 51 --------- rust/main/utils/crypto/src/lib.rs | 4 - 11 files changed, 56 insertions(+), 308 deletions(-) delete mode 100644 rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs delete mode 100644 rust/main/utils/crypto/Cargo.toml delete mode 100644 rust/main/utils/crypto/src/key.rs delete mode 100644 rust/main/utils/crypto/src/lib.rs diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index b47cce795..f58a90d40 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -515,7 +515,7 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http 0.2.12", + "http 0.2.11", "http-body", "hyper", "itoa", @@ -545,7 +545,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.12", + "http 0.2.11", "http-body", "mime", "rustversion", @@ -1256,7 +1256,7 @@ dependencies = [ "coins-core 0.8.7", "digest 0.10.7", "hmac 0.12.1", - "k256 0.13.4", + "k256 0.13.3", "serde", "sha2 0.10.8", "thiserror", @@ -1564,7 +1564,7 @@ dependencies = [ "ecdsa 0.16.9", "eyre", "getrandom 0.2.15", - "k256 0.13.4", + "k256 0.13.3", "rand_core 0.6.4", "serde", "serde_json", @@ -1589,7 +1589,7 @@ checksum = "0f862b355f7e47711e0acfe6af92cb3fd8fd5936b66a9eaa338b51edabd1e77d" dependencies = [ "digest 0.10.7", "ed25519-zebra 3.1.0", - "k256 0.13.4", + "k256 0.13.3", "rand_core 0.6.4", "thiserror", ] @@ -1608,7 +1608,7 @@ dependencies = [ "digest 0.10.7", "ecdsa 0.16.9", "ed25519-zebra 4.0.3", - "k256 0.13.4", + "k256 0.13.3", "num-traits", "p256", "rand_core 0.6.4", @@ -1798,16 +1798,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto" -version = "0.1.0" -dependencies = [ - "elliptic-curve 0.13.8", - "hex 0.4.3", - "k256 0.13.4", - "thiserror", -] - [[package]] name = "crypto-bigint" version = "0.4.9" @@ -2515,7 +2505,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve 0.13.8", "rfc6979 0.4.0", - "signature 2.0.0", + "signature 2.2.0", "spki 0.7.3", ] @@ -2545,7 +2535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8 0.10.2", - "signature 2.0.0", + "signature 2.2.0", ] [[package]] @@ -3088,7 +3078,7 @@ dependencies = [ "getrandom 0.2.15", "hashers", "hex 0.4.3", - "http 0.2.12", + "http 0.2.11", "once_cell", "parking_lot 0.11.2", "pin-project", @@ -3494,7 +3484,7 @@ dependencies = [ "ecdsa 0.16.9", "ed25519-dalek 2.1.1", "fuel-types", - "k256 0.13.4", + "k256 0.13.3", "lazy_static", "p256", "rand 0.8.5", @@ -3989,7 +3979,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.12", + "http 0.2.11", "indexmap 2.5.0", "slab", "tokio", @@ -4084,7 +4074,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http 0.2.12", + "http 0.2.11", "httpdate", "mime", "sha1", @@ -4096,7 +4086,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http 0.2.12", + "http 0.2.11", ] [[package]] @@ -4240,9 +4230,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.12" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -4267,7 +4257,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.12", + "http 0.2.11", "pin-project-lite", ] @@ -4310,7 +4300,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.12", + "http 0.2.11", "http-body", "httparse", "httpdate", @@ -4332,7 +4322,7 @@ dependencies = [ "bytes", "futures", "headers", - "http 0.2.12", + "http 0.2.11", "hyper", "hyper-rustls 0.22.1", "rustls-native-certs 0.5.0", @@ -4367,7 +4357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.12", + "http 0.2.11", "hyper", "log", "rustls 0.21.12", @@ -4512,11 +4502,10 @@ dependencies = [ "bech32 0.9.1", "cosmrs", "cosmwasm-std 2.1.3", - "crypto", "derive-new", "futures", "hex 0.4.3", - "http 0.2.12", + "http 0.2.11", "hyper", "hyper-tls", "hyperlane-core", @@ -5102,16 +5091,16 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.4" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", "ecdsa 0.16.9", "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.8", - "signature 2.0.0", + "signature 2.2.0", ] [[package]] @@ -5491,7 +5480,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 0.2.12", + "http 0.2.11", "httparse", "log", "memchr", @@ -7038,7 +7027,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.12", + "http 0.2.11", "http-body", "hyper", "hyper-rustls 0.24.2", @@ -7239,7 +7228,7 @@ dependencies = [ "hyperlane-cosmos", "hyperlane-cosmwasm-interface", "jobserver", - "k256 0.13.4", + "k256 0.13.3", "macro_rules_attribute", "maplit", "nix 0.26.4", @@ -7269,7 +7258,7 @@ dependencies = [ "bytes", "crc32fast", "futures", - "http 0.2.12", + "http 0.2.11", "hyper", "hyper-tls", "lazy_static", @@ -7341,7 +7330,7 @@ dependencies = [ "futures", "hex 0.4.3", "hmac 0.11.0", - "http 0.2.12", + "http 0.2.11", "hyper", "log", "md-5 0.9.1", @@ -8291,9 +8280,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", @@ -9402,7 +9391,7 @@ dependencies = [ "base64 0.13.1", "bytes", "chrono", - "http 0.2.12", + "http 0.2.11", "percent-encoding", "serde", "serde_json", @@ -9441,7 +9430,7 @@ dependencies = [ "ed25519-consensus", "flex-error", "futures", - "k256 0.13.4", + "k256 0.13.3", "num-traits", "once_cell", "prost 0.11.9", @@ -9452,7 +9441,7 @@ dependencies = [ "serde_json", "serde_repr", "sha2 0.10.8", - "signature 2.0.0", + "signature 2.2.0", "subtle", "subtle-encoding", "tendermint-proto 0.32.2 (git+https://github.com/hyperlane-xyz/tendermint-rs.git?branch=trevor/0.32.2-fork)", @@ -9518,7 +9507,7 @@ dependencies = [ "flex-error", "futures", "getrandom 0.2.15", - "http 0.2.12", + "http 0.2.11", "hyper", "hyper-proxy", "hyper-rustls 0.22.1", @@ -9574,18 +9563,18 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2 1.0.86", "quote 1.0.37", @@ -9902,7 +9891,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.12", + "http 0.2.11", "http-body", "hyper", "hyper-timeout", @@ -9932,7 +9921,7 @@ dependencies = [ "base64 0.21.7", "bytes", "h2", - "http 0.2.12", + "http 0.2.11", "http-body", "hyper", "hyper-timeout", @@ -10114,7 +10103,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "bytes", - "http 0.2.12", + "http 0.2.11", "httparse", "log", "rand 0.8.5", @@ -10386,7 +10375,7 @@ dependencies = [ "hyperlane-cosmos", "hyperlane-ethereum", "hyperlane-test", - "k256 0.13.4", + "k256 0.13.3", "prometheus", "reqwest", "serde", @@ -10469,7 +10458,7 @@ dependencies = [ "futures-channel", "futures-util", "headers", - "http 0.2.12", + "http 0.2.11", "hyper", "log", "mime", @@ -10959,7 +10948,7 @@ checksum = "acaf2e321fc6f853572b372962fa253cba1b62a0025116bb463ce3c00b4394dc" dependencies = [ "cfg-if", "futures", - "http 0.2.12", + "http 0.2.11", "humantime-serde", "hyper", "hyper-rustls 0.24.2", @@ -11005,7 +10994,7 @@ dependencies = [ "async-trait", "base64 0.13.1", "futures", - "http 0.2.12", + "http 0.2.11", "hyper", "hyper-rustls 0.24.2", "itertools 0.10.5", diff --git a/rust/main/Cargo.toml b/rust/main/Cargo.toml index 3e2dec820..06619dcd4 100644 --- a/rust/main/Cargo.toml +++ b/rust/main/Cargo.toml @@ -13,7 +13,6 @@ members = [ "hyperlane-test", "utils/abigen", "utils/backtrace-oneline", - "utils/crypto", "utils/hex", "utils/run-locally", ] @@ -69,10 +68,10 @@ futures-util = "0.3" generic-array = { version = "0.14", features = ["serde", "more_lengths"] } # Required for WASM support https://docs.rs/getrandom/latest/getrandom/#webassembly-support bech32 = "0.9.1" -elliptic-curve = "0.13.8" +elliptic-curve = "0.12.3" getrandom = { version = "0.2", features = ["js"] } hex = "0.4.3" -http = "0.2.12" +http = "*" hyper = "0.14" hyper-tls = "0.5.0" hyperlane-cosmwasm-interface = "=0.0.6-rc6" @@ -81,7 +80,7 @@ injective-std = "=0.1.5" itertools = "*" jobserver = "=0.1.26" jsonrpc-core = "18.0" -k256 = { version = "0.13.4", features = ["arithmetic", "std", "ecdsa"] } +k256 = { version = "0.13.1", features = ["std", "ecdsa"] } log = "0.4" macro_rules_attribute = "0.2" maplit = "1.0" diff --git a/rust/main/chains/hyperlane-cosmos/Cargo.toml b/rust/main/chains/hyperlane-cosmos/Cargo.toml index ce936ec1f..e8b1af668 100644 --- a/rust/main/chains/hyperlane-cosmos/Cargo.toml +++ b/rust/main/chains/hyperlane-cosmos/Cargo.toml @@ -14,7 +14,6 @@ base64 = { workspace = true } bech32 = { workspace = true } cosmrs = { workspace = true, features = ["cosmwasm", "tokio", "grpc", "rpc"] } cosmwasm-std = { workspace = true } -crypto = { path = "../../utils/crypto" } derive-new = { workspace = true } futures = { workspace = true } hex = { workspace = true } diff --git a/rust/main/chains/hyperlane-cosmos/src/error.rs b/rust/main/chains/hyperlane-cosmos/src/error.rs index 8ceacd601..abe61fd92 100644 --- a/rust/main/chains/hyperlane-cosmos/src/error.rs +++ b/rust/main/chains/hyperlane-cosmos/src/error.rs @@ -1,9 +1,6 @@ -use std::fmt::Debug; - use cosmrs::proto::prost; - -use crypto::PublicKeyError; use hyperlane_core::ChainCommunicationError; +use std::fmt::Debug; /// Errors from the crates specific to the hyperlane-cosmos /// implementation. @@ -63,9 +60,3 @@ impl From for ChainCommunicationError { ChainCommunicationError::from_other(value) } } - -impl From for HyperlaneCosmosError { - fn from(value: PublicKeyError) -> Self { - HyperlaneCosmosError::PublicKeyError(value.to_string()) - } -} diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs index 7f471b211..bac0fe4bc 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs @@ -1,9 +1,7 @@ use cosmrs::{crypto::PublicKey, AccountId}; -use hyperlane_cosmwasm_interface::types::keccak256_hash; use tendermint::account::Id as TendermintAccountId; use tendermint::public_key::PublicKey as TendermintPublicKey; -use crypto::decompress_public_key; use hyperlane_core::Error::Overflow; use hyperlane_core::{ChainCommunicationError, ChainResult, H256}; @@ -18,18 +16,7 @@ impl<'a> CosmosAccountId<'a> { Self { account_id } } - /// Calculate AccountId from public key depending on provided prefix pub fn account_id_from_pubkey(pub_key: PublicKey, prefix: &str) -> ChainResult { - match prefix { - "neutron" | "osmo" => Self::bitcoin_style(pub_key, prefix), - "inj" => Self::ethereum_style(pub_key, prefix), - _ => Err(HyperlaneCosmosError::CosmosError(cosmrs::Error::Crypto))?, - } - } - - /// Returns a Bitcoin style address: RIPEMD160(SHA256(pubkey)) - /// Source: `` - fn bitcoin_style(pub_key: PublicKey, prefix: &str) -> ChainResult { // Get the inner type let tendermint_pub_key = TendermintPublicKey::from(pub_key); // Get the RIPEMD160(SHA256(pub_key)) @@ -40,23 +27,6 @@ impl<'a> CosmosAccountId<'a> { Ok(account_id) } - - /// Returns an Ethereum style address: KECCAK256(pubkey)[20] - /// Parameter `pub_key` is a compressed public key. - fn ethereum_style(pub_key: PublicKey, prefix: &str) -> ChainResult { - let decompressed_public_key = decompress_public_key(&pub_key.to_bytes()) - .map_err(Into::::into)?; - - let hash = keccak256_hash(&decompressed_public_key[1..]); - - let mut bytes = [0u8; 20]; - bytes.copy_from_slice(&hash.as_slice()[12..]); - - let account_id = - AccountId::new(prefix, bytes.as_slice()).map_err(Into::::into)?; - - Ok(account_id) - } } impl TryFrom<&CosmosAccountId<'_>> for H256 { @@ -85,6 +55,3 @@ impl TryFrom> for H256 { (&account_id).try_into() } } - -#[cfg(test)] -mod tests; diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs deleted file mode 100644 index d00c0019c..000000000 --- a/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs +++ /dev/null @@ -1,70 +0,0 @@ -use cosmrs::crypto::PublicKey; -use cosmwasm_std::HexBinary; - -use crypto::decompress_public_key; - -use crate::libs::account::CosmosAccountId; - -const COMPRESSED_PUBLIC_KEY: &str = - "02962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f4"; -const INJECTIVE_ADDRESS: &str = "inj1m6ada382hfuxvuke4h9p4uswhn2qcca7mlg0dr"; -const NEUTRON_ADDRESS: &str = "neutron1mydju5alsmhnfsawy0j4lyns70l7qukgdgy45w"; - -#[test] -fn test_account_id() { - // given - let pub_key = compressed_public_key(); - - // when - let neutron_account_id = CosmosAccountId::account_id_from_pubkey(pub_key, "neutron").unwrap(); - let injective_account_id = CosmosAccountId::account_id_from_pubkey(pub_key, "inj").unwrap(); - - // then - assert_eq!(neutron_account_id.as_ref(), NEUTRON_ADDRESS); - assert_eq!(injective_account_id.as_ref(), INJECTIVE_ADDRESS); -} - -#[test] -fn test_bitcoin_style() { - // given - let compressed = compressed_public_key(); - let decompressed = decompressed_public_key(); - - // when - let from_compressed = CosmosAccountId::bitcoin_style(compressed, "neutron").unwrap(); - let from_decompressed = CosmosAccountId::bitcoin_style(decompressed, "neutron").unwrap(); - - // then - assert_eq!(from_compressed.as_ref(), NEUTRON_ADDRESS); - assert_eq!(from_decompressed.as_ref(), NEUTRON_ADDRESS); -} - -#[test] -fn test_ethereum_style() { - // given - let compressed = compressed_public_key(); - let decompressed = decompressed_public_key(); - - // when - let from_compressed = CosmosAccountId::ethereum_style(compressed, "inj").unwrap(); - let from_decompressed = CosmosAccountId::ethereum_style(decompressed, "inj").unwrap(); - - // then - assert_eq!(from_compressed.as_ref(), INJECTIVE_ADDRESS); - assert_eq!(from_decompressed.as_ref(), INJECTIVE_ADDRESS); -} - -fn compressed_public_key() -> PublicKey { - let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); - let tendermint = tendermint::PublicKey::from_raw_secp256k1(&hex).unwrap(); - let pub_key = PublicKey::from(tendermint); - pub_key -} - -fn decompressed_public_key() -> PublicKey { - let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); - let decompressed = decompress_public_key(&hex).unwrap(); - let tendermint = tendermint::PublicKey::from_raw_secp256k1(&decompressed).unwrap(); - let pub_key = PublicKey::from(tendermint); - pub_key -} diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs index 78cb393de..41a5ab6ab 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs @@ -20,7 +20,8 @@ pub struct CosmosAddress { } impl CosmosAddress { - /// Calculates an account address depending on prefix + /// Returns a Bitcoin style address: RIPEMD160(SHA256(pubkey)) + /// Source: `` pub fn from_pubkey(pubkey: PublicKey, prefix: &str) -> ChainResult { let account_id = CosmosAccountId::account_id_from_pubkey(pubkey, prefix)?; Self::from_account_id(account_id) @@ -34,7 +35,8 @@ impl CosmosAddress { Self::from_pubkey(pubkey, prefix) } - /// Returns an account address calculated from Bech32 encoding + /// Returns a Bitcoin style address calculated from Bech32 encoding + /// Source: `` pub fn from_account_id(account_id: AccountId) -> ChainResult { // Hex digest let digest = H256::try_from(&CosmosAccountId::new(&account_id))?; diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index 000495a75..62931e69e 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -1,10 +1,8 @@ -use std::str::FromStr; - use async_trait::async_trait; use cosmrs::cosmwasm::MsgExecuteContract; use cosmrs::crypto::PublicKey; -use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo, SignerPublicKey}; -use cosmrs::{proto, AccountId, Any, Coin, Tx}; +use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo}; +use cosmrs::{AccountId, Any, Coin, Tx}; use itertools::Itertools; use once_cell::sync::Lazy; use tendermint::hash::Algorithm; @@ -13,7 +11,6 @@ use tendermint_rpc::{client::CompatMode, Client, HttpClient}; use time::OffsetDateTime; use tracing::{error, warn}; -use crypto::decompress_public_key; use hyperlane_core::{ BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, TxnInfo, TxnReceiptInfo, H256, U256, @@ -28,9 +25,6 @@ use crate::{ConnectionConf, CosmosAmount, HyperlaneCosmosError, Signer}; /// Exponent value for atto units (10^-18). const ATTO_EXPONENT: u32 = 18; -/// Injective public key type URL for protobuf Any -const INJECTIVE_PUBLIC_KEY_TYPE_URL: &str = "/injective.crypto.v1beta1.ethsecp256k1.PubKey"; - /// Abstraction over a connection to a Cosmos chain #[derive(Debug, Clone)] pub struct CosmosProvider { @@ -99,8 +93,7 @@ impl CosmosProvider { HyperlaneCosmosError::PublicKeyError("no public key for default signer".to_owned()) })?; - let key = self.normalize_public_key(signer_public_key)?; - let public_key = PublicKey::try_from(key)?; + let public_key = PublicKey::try_from(signer_public_key)?; let account_id = CosmosAccountId::account_id_from_pubkey( public_key, @@ -110,59 +103,6 @@ impl CosmosProvider { Ok((account_id, signer_info.sequence)) } - fn normalize_public_key( - &self, - signer_public_key: SignerPublicKey, - ) -> ChainResult { - let public_key = match signer_public_key { - SignerPublicKey::Single(pk) => SignerPublicKey::from(pk), - SignerPublicKey::LegacyAminoMultisig(pk) => SignerPublicKey::from(pk), - SignerPublicKey::Any(pk) => { - if pk.type_url != PublicKey::ED25519_TYPE_URL - && pk.type_url != PublicKey::SECP256K1_TYPE_URL - && pk.type_url != INJECTIVE_PUBLIC_KEY_TYPE_URL - { - let msg = format!( - "can only normalize public keys with a known TYPE_URL: {}, {}, {}", - PublicKey::ED25519_TYPE_URL, - PublicKey::SECP256K1_TYPE_URL, - INJECTIVE_PUBLIC_KEY_TYPE_URL - ); - warn!(pk.type_url, msg); - Err(HyperlaneCosmosError::PublicKeyError(msg.to_owned()))? - } - - let pub_key = if pk.type_url == INJECTIVE_PUBLIC_KEY_TYPE_URL { - let any = Any { - type_url: PublicKey::SECP256K1_TYPE_URL.to_owned(), - value: pk.value, - }; - - let proto = proto::cosmos::crypto::secp256k1::PubKey::from_any(&any) - .map_err(Into::::into)?; - - let decompressed = decompress_public_key(&proto.key) - .map_err(|e| HyperlaneCosmosError::PublicKeyError(e.to_string()))?; - - let tendermint = tendermint::PublicKey::from_raw_secp256k1(&decompressed) - .ok_or_else(|| { - HyperlaneCosmosError::PublicKeyError( - "cannot create tendermint public key".to_owned(), - ) - })?; - - PublicKey::from(tendermint) - } else { - PublicKey::try_from(pk)? - }; - - SignerPublicKey::Single(pub_key) - } - }; - - Ok(public_key) - } - /// Calculates the sender and the nonce for the transaction. /// We use `payer` of the fees as the sender of the transaction, and we search for `payer` /// signature information to find the nonce. diff --git a/rust/main/utils/crypto/Cargo.toml b/rust/main/utils/crypto/Cargo.toml deleted file mode 100644 index de5b64535..000000000 --- a/rust/main/utils/crypto/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "crypto" -documentation.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -publish.workspace = true -version.workspace = true - -[dependencies] -elliptic-curve = { workspace = true, features = ["sec1"] } -hex = { workspace = true } -k256 = { workspace = true } -thiserror = { workspace = true } diff --git a/rust/main/utils/crypto/src/key.rs b/rust/main/utils/crypto/src/key.rs deleted file mode 100644 index 601431f28..000000000 --- a/rust/main/utils/crypto/src/key.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::fmt::{Display, Formatter}; - -use elliptic_curve::sec1::ToEncodedPoint; - -#[derive(Debug, thiserror::Error)] -pub enum PublicKeyError { - Decode(String), -} - -impl Display for PublicKeyError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -/// Decompresses public key of secp256k1 if it was compressed -/// -/// Public key can be expressed in compressed or decompressed forms. -/// Compressed form contains one byte as prefix and x component of the public key. -/// Decompressed form contains one byte as prefix, x and y components of the public key. -pub fn decompress_public_key(public_key: &[u8]) -> Result, PublicKeyError> { - let elliptic: elliptic_curve::PublicKey = - elliptic_curve::PublicKey::from_sec1_bytes(public_key) - .map_err(|e| PublicKeyError::Decode(e.to_string()))?; - - // if public key was compressed, encoding into the point will decompress it. - let point = elliptic.to_encoded_point(false); - let decompressed = point.to_bytes().to_vec(); - Ok(decompressed) -} - -#[cfg(test)] -mod tests { - use crate::key::decompress_public_key; - - #[test] - fn test_decompress_public_key() { - // given - let compressed = "02962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f4"; - let hex = hex::decode(compressed).unwrap(); - - // when - let decompressed = hex::encode(decompress_public_key(&hex).unwrap()); - - // then - assert_eq!( - "04962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f40cb1152fb9e61ec7493a0d9a35d2e8a57198e109613854abdd3be5603d504008", - decompressed - ); - } -} diff --git a/rust/main/utils/crypto/src/lib.rs b/rust/main/utils/crypto/src/lib.rs deleted file mode 100644 index edd7a4f4d..000000000 --- a/rust/main/utils/crypto/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub use key::decompress_public_key; -pub use key::PublicKeyError; - -mod key; From 4f92871c2b7fe1c7b5e3e7917eacdb0787a26740 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:12:17 +0100 Subject: [PATCH 096/224] feat: include `id` field in `list_operations` endpoint (#4610) ### Description The `id` field was missing if the serialized `PendingOperation` was a `PendingMessage`, which made it hard to look up the message in relayer logs or the explorer. This PR takes advantage of `id()` being a required method on `PendingOperation` to derive and display the ID as part of endpoint logic. ### Testing Unit Tests --- rust/main/agents/relayer/src/msg/op_queue.rs | 4 ++ .../relayer/src/server/list_messages.rs | 69 +++++++++++++++---- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/rust/main/agents/relayer/src/msg/op_queue.rs b/rust/main/agents/relayer/src/msg/op_queue.rs index 30f78edda..78a94de70 100644 --- a/rust/main/agents/relayer/src/msg/op_queue.rs +++ b/rust/main/agents/relayer/src/msg/op_queue.rs @@ -145,6 +145,10 @@ pub mod test { destination_domain, } } + + pub fn with_id(self, id: H256) -> Self { + Self { id, ..self } + } } impl TryBatchAs for MockPendingOperation {} diff --git a/rust/main/agents/relayer/src/server/list_messages.rs b/rust/main/agents/relayer/src/server/list_messages.rs index 9c851a623..8eea8446b 100644 --- a/rust/main/agents/relayer/src/server/list_messages.rs +++ b/rust/main/agents/relayer/src/server/list_messages.rs @@ -3,8 +3,8 @@ use axum::{ routing, Router, }; use derive_new::new; -use hyperlane_core::QueueOperation; -use serde::Deserialize; +use hyperlane_core::{QueueOperation, H256}; +use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; @@ -39,12 +39,27 @@ async fn list_operations( format_queue(op_queue.clone()).await } +#[derive(Debug, Serialize)] +struct OperationWithId<'a> { + id: H256, + operation: &'a QueueOperation, +} + +impl<'a> OperationWithId<'a> { + fn new(operation: &'a QueueOperation) -> Self { + Self { + id: operation.id(), + operation, + } + } +} + pub async fn format_queue(queue: OperationPriorityQueue) -> String { let res: Result, _> = queue .lock() .await .iter() - .map(|reverse| serde_json::to_value(&reverse.0)) + .map(|reverse| serde_json::to_value(OperationWithId::new(&reverse.0))) .collect(); match res.and_then(|v| serde_json::to_string_pretty(&v)) { Ok(s) => s, @@ -76,7 +91,7 @@ mod tests { use super::*; use axum::http::StatusCode; use hyperlane_core::KnownHyperlaneDomain; - use std::{cmp::Reverse, net::SocketAddr, sync::Arc}; + use std::{cmp::Reverse, net::SocketAddr, str::FromStr, sync::Arc}; use tokio::sync::{self, Mutex}; const DUMMY_DOMAIN: KnownHyperlaneDomain = KnownHyperlaneDomain::Arbitrum; @@ -108,15 +123,43 @@ mod tests { #[tokio::test] async fn test_message_id_retry() { let (addr, op_queue) = setup_test_server(); - let dummy_operation_1 = - Box::new(MockPendingOperation::new(1, DUMMY_DOMAIN.into())) as QueueOperation; - let dummy_operation_2 = - Box::new(MockPendingOperation::new(2, DUMMY_DOMAIN.into())) as QueueOperation; - let v = vec![ - serde_json::to_value(&dummy_operation_1).unwrap(), - serde_json::to_value(&dummy_operation_2).unwrap(), - ]; - let expected_response = serde_json::to_string_pretty(&v).unwrap(); + let id_1 = "0x1acbee9798118b11ebef0d94b0a2936eafd58e3bfab91b05da875825c4a1c39b"; + let id_2 = "0x51e7be221ce90a49dee46ca0d0270c48d338a7b9d85c2a89d83fac0816571914"; + let dummy_operation_1 = Box::new( + MockPendingOperation::new(1, DUMMY_DOMAIN.into()) + .with_id(H256::from_str(id_1).unwrap()), + ) as QueueOperation; + let dummy_operation_2 = Box::new( + MockPendingOperation::new(2, DUMMY_DOMAIN.into()) + .with_id(H256::from_str(id_2).unwrap()), + ) as QueueOperation; + + // The reason there already is an id inside `operation` here is because it's a field on `MockPendingOperation` - that field is + // missing on `PendingMessage` because it's derived, hence the need to hence the need to have it explicitly serialized alongside the operation. + let expected_response = r#"[ + { + "id": "0x1acbee9798118b11ebef0d94b0a2936eafd58e3bfab91b05da875825c4a1c39b", + "operation": { + "destination_domain": { + "Known": "Arbitrum" + }, + "id": "0x1acbee9798118b11ebef0d94b0a2936eafd58e3bfab91b05da875825c4a1c39b", + "seconds_to_next_attempt": 1, + "type": "MockPendingOperation" + } + }, + { + "id": "0x51e7be221ce90a49dee46ca0d0270c48d338a7b9d85c2a89d83fac0816571914", + "operation": { + "destination_domain": { + "Known": "Arbitrum" + }, + "id": "0x51e7be221ce90a49dee46ca0d0270c48d338a7b9d85c2a89d83fac0816571914", + "seconds_to_next_attempt": 2, + "type": "MockPendingOperation" + } + } +]"#; op_queue.lock().await.push(Reverse(dummy_operation_1)); op_queue.lock().await.push(Reverse(dummy_operation_2)); From e2b5a4c785862e3953da31cf0e580d9dc6e43297 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:26:38 +0100 Subject: [PATCH 097/224] feat: HyperlaneDb trait (#4609) ### Description Defines a `HyperlaneDb` trait for use in the validator submitter, so a mock can be passed in to simulate indexed data from reorged state. Although the `HyperlaneDb` trait can't be `Clone` to be object safe, as long as we use `Arc`s everywhere, all will be ok. Eventually the aim is to replace all direct usage of `HyperlaneRocksDb` with `Arc`. --- .../relayer/src/merkle_tree/processor.rs | 2 +- .../agents/relayer/src/msg/metadata/base.rs | 2 +- .../agents/relayer/src/msg/pending_message.rs | 5 +- rust/main/agents/relayer/src/msg/processor.rs | 168 ++++++++- rust/main/agents/validator/src/submit.rs | 11 +- rust/main/agents/validator/src/validator.rs | 4 +- rust/main/config/testnet_config.json | 188 ++++++++++ rust/main/hyperlane-base/src/db/error.rs | 34 ++ rust/main/hyperlane-base/src/db/mod.rs | 160 +++++++++ .../src/db/rocks/hyperlane_db.rs | 331 ++++++++++++------ rust/main/hyperlane-base/src/db/rocks/mod.rs | 39 +-- .../hyperlane-base/src/db/rocks/typed_db.rs | 2 +- .../src/db/{rocks => }/storage_types.rs | 9 +- 13 files changed, 795 insertions(+), 160 deletions(-) create mode 100644 rust/main/hyperlane-base/src/db/error.rs rename rust/main/hyperlane-base/src/db/{rocks => }/storage_types.rs (90%) diff --git a/rust/main/agents/relayer/src/merkle_tree/processor.rs b/rust/main/agents/relayer/src/merkle_tree/processor.rs index 251e8e7c6..9ddcc2ee0 100644 --- a/rust/main/agents/relayer/src/merkle_tree/processor.rs +++ b/rust/main/agents/relayer/src/merkle_tree/processor.rs @@ -7,7 +7,7 @@ use std::{ use async_trait::async_trait; use derive_new::new; use eyre::Result; -use hyperlane_base::db::HyperlaneRocksDB; +use hyperlane_base::db::{HyperlaneDb, HyperlaneRocksDB}; use hyperlane_core::{HyperlaneDomain, MerkleTreeInsertion}; use prometheus::IntGauge; use tokio::sync::RwLock; diff --git a/rust/main/agents/relayer/src/msg/metadata/base.rs b/rust/main/agents/relayer/src/msg/metadata/base.rs index e4b7ebb19..e847e39c6 100644 --- a/rust/main/agents/relayer/src/msg/metadata/base.rs +++ b/rust/main/agents/relayer/src/msg/metadata/base.rs @@ -22,7 +22,7 @@ use crate::{ use async_trait::async_trait; use derive_new::new; use eyre::{Context, Result}; -use hyperlane_base::db::HyperlaneRocksDB; +use hyperlane_base::db::{HyperlaneDb, HyperlaneRocksDB}; use hyperlane_base::{ settings::{ChainConf, CheckpointSyncerConf}, CheckpointSyncer, CoreMetrics, MultisigCheckpointSyncer, diff --git a/rust/main/agents/relayer/src/msg/pending_message.rs b/rust/main/agents/relayer/src/msg/pending_message.rs index 7abfd07cd..350e9f5b5 100644 --- a/rust/main/agents/relayer/src/msg/pending_message.rs +++ b/rust/main/agents/relayer/src/msg/pending_message.rs @@ -9,7 +9,10 @@ use std::{ use async_trait::async_trait; use derive_new::new; use eyre::Result; -use hyperlane_base::{db::HyperlaneRocksDB, CoreMetrics}; +use hyperlane_base::{ + db::{HyperlaneDb, HyperlaneRocksDB}, + CoreMetrics, +}; use hyperlane_core::{ gas_used_by_operation, BatchItem, ChainCommunicationError, ChainResult, ConfirmReason, HyperlaneChain, HyperlaneDomain, HyperlaneMessage, Mailbox, MessageSubmissionData, diff --git a/rust/main/agents/relayer/src/msg/processor.rs b/rust/main/agents/relayer/src/msg/processor.rs index 8d0422879..a2f70f8c9 100644 --- a/rust/main/agents/relayer/src/msg/processor.rs +++ b/rust/main/agents/relayer/src/msg/processor.rs @@ -11,7 +11,7 @@ use derive_new::new; use ethers::utils::hex; use eyre::Result; use hyperlane_base::{ - db::{HyperlaneRocksDB, ProcessMessage}, + db::{HyperlaneDb, HyperlaneRocksDB}, CoreMetrics, }; use hyperlane_core::{HyperlaneDomain, HyperlaneMessage, QueueOperation}; @@ -52,7 +52,7 @@ struct ForwardBackwardIterator { impl ForwardBackwardIterator { #[instrument(skip(db), ret)] - fn new(db: Arc) -> Self { + fn new(db: Arc) -> Self { let high_nonce = db.retrieve_highest_seen_message_nonce().ok().flatten(); let domain = db.domain().name().to_owned(); let high_nonce_iter = DirectionalNonceIterator::new( @@ -125,7 +125,7 @@ enum NonceDirection { struct DirectionalNonceIterator { nonce: Option, direction: NonceDirection, - db: Arc, + db: Arc, domain_name: String, } @@ -196,7 +196,10 @@ impl DirectionalNonceIterator { let Some(nonce) = self.nonce else { return Ok(false); }; - let processed = self.db.retrieve_processed_by_nonce(nonce)?.unwrap_or(false); + let processed = self + .db + .retrieve_processed_by_nonce(&nonce)? + .unwrap_or(false); if processed { trace!( nonce, @@ -326,7 +329,7 @@ impl MessageProcessor { send_channels, destination_ctxs, metric_app_contexts, - nonce_iterator: ForwardBackwardIterator::new(Arc::new(db) as Arc), + nonce_iterator: ForwardBackwardIterator::new(Arc::new(db) as Arc), } } @@ -394,9 +397,16 @@ mod test { use super::*; use hyperlane_base::{ - db::{test_utils, DbResult, HyperlaneRocksDB}, + db::{ + test_utils, DbResult, HyperlaneRocksDB, InterchainGasExpenditureData, + InterchainGasPaymentData, + }, settings::{ChainConf, ChainConnectionConf, Settings}, }; + use hyperlane_core::{ + GasPaymentKey, InterchainGasPayment, InterchainGasPaymentMeta, MerkleTreeInsertion, + PendingOperationStatus, H256, + }; use hyperlane_test::mocks::{MockMailboxContract, MockValidatorAnnounceContract}; use prometheus::{IntCounter, Registry}; use tokio::{ @@ -591,11 +601,153 @@ mod test { fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result; } - impl ProcessMessage for Db { + impl HyperlaneDb for Db { + /// Retrieve the nonce of the highest processed message we're aware of fn retrieve_highest_seen_message_nonce(&self) -> DbResult>; + + /// Retrieve a message by its nonce fn retrieve_message_by_nonce(&self, nonce: u32) -> DbResult>; - fn retrieve_processed_by_nonce(&self, nonce: u32) -> DbResult>; + + /// Retrieve whether a message has been processed + fn retrieve_processed_by_nonce(&self, nonce: &u32) -> DbResult>; + + /// Get the origin domain of the database fn domain(&self) -> &HyperlaneDomain; + + fn store_message_id_by_nonce(&self, nonce: &u32, id: &H256) -> DbResult<()>; + + fn retrieve_message_id_by_nonce(&self, nonce: &u32) -> DbResult>; + + fn store_message_by_id(&self, id: &H256, message: &HyperlaneMessage) -> DbResult<()>; + + fn retrieve_message_by_id(&self, id: &H256) -> DbResult>; + + fn store_dispatched_block_number_by_nonce( + &self, + nonce: &u32, + block_number: &u64, + ) -> DbResult<()>; + + fn retrieve_dispatched_block_number_by_nonce(&self, nonce: &u32) -> DbResult>; + + /// Store whether a message was processed by its nonce + fn store_processed_by_nonce(&self, nonce: &u32, processed: &bool) -> DbResult<()>; + + fn store_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + processed: &bool, + ) -> DbResult<()>; + + fn retrieve_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + ) -> DbResult>; + + fn store_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + data: &InterchainGasExpenditureData, + ) -> DbResult<()>; + + fn retrieve_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + + /// Store the status of an operation by its message id + fn store_status_by_message_id( + &self, + message_id: &H256, + status: &PendingOperationStatus, + ) -> DbResult<()>; + + /// Retrieve the status of an operation by its message id + fn retrieve_status_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + + fn store_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + data: &InterchainGasPaymentData, + ) -> DbResult<()>; + + fn retrieve_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + ) -> DbResult>; + + fn store_gas_payment_by_sequence( + &self, + sequence: &u32, + payment: &InterchainGasPayment, + ) -> DbResult<()>; + + fn retrieve_gas_payment_by_sequence( + &self, + sequence: &u32, + ) -> DbResult>; + + fn store_gas_payment_block_by_sequence( + &self, + sequence: &u32, + block_number: &u64, + ) -> DbResult<()>; + + fn retrieve_gas_payment_block_by_sequence(&self, sequence: &u32) -> DbResult>; + + /// Store the retry count for a pending message by its message id + fn store_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + count: &u32, + ) -> DbResult<()>; + + /// Retrieve the retry count for a pending message by its message id + fn retrieve_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + + fn store_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + insertion: &MerkleTreeInsertion, + ) -> DbResult<()>; + + /// Retrieve the merkle tree insertion event by its leaf index + fn retrieve_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult>; + + fn store_merkle_leaf_index_by_message_id( + &self, + message_id: &H256, + leaf_index: &u32, + ) -> DbResult<()>; + + /// Retrieve the merkle leaf index of a message in the merkle tree + fn retrieve_merkle_leaf_index_by_message_id(&self, message_id: &H256) -> DbResult>; + + fn store_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + block_number: &u64, + ) -> DbResult<()>; + + fn retrieve_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult>; + + fn store_highest_seen_message_nonce_number(&self, nonce: &u32) -> DbResult<()>; + + /// Retrieve the nonce of the highest processed message we're aware of + fn retrieve_highest_seen_message_nonce_number(&self) -> DbResult>; + } } diff --git a/rust/main/agents/validator/src/submit.rs b/rust/main/agents/validator/src/submit.rs index 8f91f284f..8b3ede08e 100644 --- a/rust/main/agents/validator/src/submit.rs +++ b/rust/main/agents/validator/src/submit.rs @@ -3,13 +3,14 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use std::vec; +use hyperlane_base::db::HyperlaneDb; use hyperlane_core::rpc_clients::call_and_retry_indefinitely; use hyperlane_core::{ChainResult, MerkleTreeHook}; use prometheus::IntGauge; use tokio::time::sleep; use tracing::{debug, error, info}; -use hyperlane_base::{db::HyperlaneRocksDB, CheckpointSyncer, CoreMetrics}; +use hyperlane_base::{CheckpointSyncer, CoreMetrics}; use hyperlane_core::{ accumulator::incremental::IncrementalMerkle, Checkpoint, CheckpointWithMessageId, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSignerExt, @@ -23,7 +24,7 @@ pub(crate) struct ValidatorSubmitter { signer: SingletonSignerHandle, merkle_tree_hook: Arc, checkpoint_syncer: Arc, - message_db: HyperlaneRocksDB, + db: Arc, metrics: ValidatorSubmitterMetrics, } @@ -34,7 +35,7 @@ impl ValidatorSubmitter { merkle_tree_hook: Arc, signer: SingletonSignerHandle, checkpoint_syncer: Arc, - message_db: HyperlaneRocksDB, + db: Arc, metrics: ValidatorSubmitterMetrics, ) -> Self { Self { @@ -43,7 +44,7 @@ impl ValidatorSubmitter { merkle_tree_hook, signer, checkpoint_syncer, - message_db, + db, metrics, } } @@ -159,7 +160,7 @@ impl ValidatorSubmitter { // and convert the correctness_checkpoint.index to a count by adding 1. while tree.count() as u32 <= correctness_checkpoint.index { if let Some(insertion) = self - .message_db + .db .retrieve_merkle_tree_insertion_by_leaf_index(&(tree.count() as u32)) .unwrap_or_else(|err| { panic!( diff --git a/rust/main/agents/validator/src/validator.rs b/rust/main/agents/validator/src/validator.rs index a4f9a9e00..3f1f05c3a 100644 --- a/rust/main/agents/validator/src/validator.rs +++ b/rust/main/agents/validator/src/validator.rs @@ -10,7 +10,7 @@ use tokio::{task::JoinHandle, time::sleep}; use tracing::{error, info, info_span, instrument::Instrumented, warn, Instrument}; use hyperlane_base::{ - db::{HyperlaneRocksDB, DB}, + db::{HyperlaneDb, HyperlaneRocksDB, DB}, metrics::AgentMetrics, settings::ChainConf, AgentMetadata, BaseAgent, ChainMetrics, CheckpointSyncer, ContractSyncMetrics, ContractSyncer, @@ -241,7 +241,7 @@ impl Validator { self.merkle_tree_hook.clone(), self.signer.clone(), self.checkpoint_syncer.clone(), - self.db.clone(), + Arc::new(self.db.clone()) as Arc, ValidatorSubmitterMetrics::new(&self.core.metrics, &self.origin_chain), ); diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index 77617bb75..6f10162a2 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -1446,6 +1446,194 @@ "index": { "from": 1921514 } + }, + "test1": { + "blockExplorers": [ + { + "apiKey": "fakekey", + "apiUrl": "https://api.etherscan.io/api", + "family": "etherscan", + "name": "Etherscan", + "url": "https://etherscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 0 + }, + "chainId": 9913371, + "displayName": "Test 1", + "domainId": 9913371, + "isTestnet": true, + "name": "test1", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "http://127.0.0.1:8545" + } + ], + "aggregationHook": "0x7F54A0734c5B443E5B04cc26B54bb8ecE0455785", + "domainRoutingIsm": "0xb0279Db6a2F1E01fbC8483FCCef0Be2bC6299cC3", + "fallbackRoutingHook": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf", + "interchainGasPaymaster": "0x5eb3Bc0a489C5A8288765d2336659EbCA68FCd00", + "interchainSecurityModule": "0xb0279Db6a2F1E01fbC8483FCCef0Be2bC6299cC3", + "mailbox": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E", + "merkleTreeHook": "0x4826533B4897376654Bb4d4AD88B7faFD0C98528", + "protocolFee": "0x1291Be112d480055DaFd8a610b7d1e203891C274", + "proxyAdmin": "0xc5a5C42992dECbae36851359345FE25997F5C42d", + "storageGasOracle": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF", + "testRecipient": "0xCD8a1C3ba11CF5ECfa6267617243239504a98d90", + "validatorAnnounce": "0xb7278A61aa25c888815aFC32Ad3cC52fF24fE575", + "index": { + "from": 30 + } + }, + "test2": { + "blockExplorers": [ + { + "apiKey": "fakekey", + "apiUrl": "https://api.etherscan.io/api", + "family": "etherscan", + "name": "Etherscan", + "url": "https://etherscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 1 + }, + "chainId": 9913372, + "displayName": "Test 2", + "domainId": 9913372, + "isTestnet": true, + "name": "test2", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "http://127.0.0.1:8545" + } + ], + "aggregationHook": "0x5f07F66a6c12BAE727A0e0C84c2f83Ef3c83b44c", + "domainRoutingIsm": "0x3Ca8f9C04c7e3E1624Ac2008F92f6F366A869444", + "fallbackRoutingHook": "0x4C4a2f8c81640e47606d3fd77B353E87Ba015584", + "interchainGasPaymaster": "0xDC11f7E700A4c898AE5CAddB1082cFfa76512aDD", + "interchainSecurityModule": "0x3Ca8f9C04c7e3E1624Ac2008F92f6F366A869444", + "mailbox": "0x7bc06c482DEAd17c0e297aFbC32f6e63d3846650", + "merkleTreeHook": "0x04C89607413713Ec9775E14b954286519d836FEf", + "protocolFee": "0x0355B7B8cb128fA5692729Ab3AAa199C1753f726", + "proxyAdmin": "0x2bdCC0de6bE1f7D2ee689a0342D76F52E8EFABa3", + "storageGasOracle": "0x21dF544947ba3E8b3c32561399E88B52Dc8b2823", + "testRecipient": "0x172076E0166D1F9Cc711C77Adf8488051744980C", + "validatorAnnounce": "0xf4B146FbA71F41E0592668ffbF264F1D186b2Ca8", + "index": { + "from": 57 + } + }, + "test3": { + "blockExplorers": [ + { + "apiKey": "fakekey", + "apiUrl": "https://api.etherscan.io/api", + "family": "etherscan", + "name": "Etherscan", + "url": "https://etherscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 2 + }, + "chainId": 9913373, + "displayName": "Test 3", + "domainId": 9913373, + "isTestnet": true, + "name": "test3", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "http://127.0.0.1:8545" + } + ], + "aggregationHook": "0xd5BA21a5bDE25af311a900191c52ce9Fc8Ab9b8d", + "domainRoutingIsm": "0xa12fFA0B9f159BB4C54bce579611927Addc51610", + "fallbackRoutingHook": "0xf953b3A269d80e3eB0F2947630Da976B896A8C5b", + "interchainGasPaymaster": "0xe8D2A1E88c91DCd5433208d4152Cc4F399a7e91d", + "interchainSecurityModule": "0xa12fFA0B9f159BB4C54bce579611927Addc51610", + "mailbox": "0x2B0d36FACD61B71CC05ab8F3D2355ec3631C0dd5", + "merkleTreeHook": "0xA4899D35897033b927acFCf422bc745916139776", + "protocolFee": "0xCace1b78160AE76398F486c8a18044da0d66d86D", + "proxyAdmin": "0xBEc49fA140aCaA83533fB00A2BB19bDdd0290f25", + "storageGasOracle": "0xAA292E8611aDF267e563f334Ee42320aC96D0463", + "testRecipient": "0xc0F115A19107322cFBf1cDBC7ea011C19EbDB4F8", + "validatorAnnounce": "0xF8e31cb472bc70500f08Cd84917E5A1912Ec8397", + "index": { + "from": 84 + } + }, + "test4": { + "blockExplorers": [ + { + "apiKey": "fakekey", + "apiUrl": "https://api.etherscan.io/api", + "family": "etherscan", + "name": "Etherscan", + "url": "https://etherscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 0 + }, + "chainId": 31337, + "displayName": "Test 4", + "domainId": 31337, + "isTestnet": true, + "name": "test4", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "http://127.0.0.1:8545" + } + ], + "aggregationHook": "0xfD4Ab5938aAcE9B094cc3B298d18be83E170B2fc", + "domainRoutingIsm": "0x532B02BD614Fd18aEE45603d02866cFb77575CB3", + "fallbackRoutingHook": "0x1f10F3Ba7ACB61b2F50B9d6DdCf91a6f787C0E82", + "interchainGasPaymaster": "0x5fc748f1FEb28d7b76fa1c6B07D8ba2d5535177c", + "interchainSecurityModule": "0x532B02BD614Fd18aEE45603d02866cFb77575CB3", + "mailbox": "0x07882Ae1ecB7429a84f1D53048d35c4bB2056877", + "merkleTreeHook": "0xE3011A37A904aB90C8881a99BD1F6E21401f1522", + "protocolFee": "0x8A93d247134d91e0de6f96547cB0204e5BE8e5D8", + "proxyAdmin": "0x34B40BA116d5Dec75548a9e9A8f15411461E8c70", + "storageGasOracle": "0x457cCf29090fe5A24c19c1bc95F492168C0EaFdb", + "testRecipient": "0xd6e1afe5cA8D00A2EFC01B89997abE2De47fdfAf", + "validatorAnnounce": "0xF32D39ff9f6Aa7a7A64d7a4F00a54826Ef791a55", + "index": { + "from": 111 + } } }, "defaultRpcConsensusType": "fallback" diff --git a/rust/main/hyperlane-base/src/db/error.rs b/rust/main/hyperlane-base/src/db/error.rs new file mode 100644 index 000000000..73b5e35bf --- /dev/null +++ b/rust/main/hyperlane-base/src/db/error.rs @@ -0,0 +1,34 @@ +use std::{io, path::PathBuf}; + +use hyperlane_core::{ChainCommunicationError, HyperlaneProtocolError}; + +/// DB Error type +#[derive(thiserror::Error, Debug)] +pub enum DbError { + /// Rocks DB Error + #[error("{0}")] + RockError(#[from] rocksdb::Error), + #[error("Failed to open {path}, canonicalized as {canonicalized}: {source}")] + /// Error opening the database + OpeningError { + /// Rocksdb error during opening + #[source] + source: rocksdb::Error, + /// Raw database path provided + path: PathBuf, + /// Parsed path used + canonicalized: PathBuf, + }, + /// Could not parse the provided database path string + #[error("Invalid database path supplied {1:?}; {0}")] + InvalidDbPath(#[source] io::Error, String), + /// Hyperlane Error + #[error("{0}")] + HyperlaneError(#[from] HyperlaneProtocolError), +} + +impl From for ChainCommunicationError { + fn from(value: DbError) -> Self { + ChainCommunicationError::from_other(value) + } +} diff --git a/rust/main/hyperlane-base/src/db/mod.rs b/rust/main/hyperlane-base/src/db/mod.rs index 55c11ddc9..04a3e59cc 100644 --- a/rust/main/hyperlane-base/src/db/mod.rs +++ b/rust/main/hyperlane-base/src/db/mod.rs @@ -1,2 +1,162 @@ +pub use error::*; +use hyperlane_core::{ + GasPaymentKey, HyperlaneDomain, HyperlaneMessage, InterchainGasPayment, + InterchainGasPaymentMeta, MerkleTreeInsertion, PendingOperationStatus, H256, +}; pub use rocks::*; + +pub use self::storage_types::{InterchainGasExpenditureData, InterchainGasPaymentData}; + +mod error; mod rocks; +pub(crate) mod storage_types; + +#[allow(missing_docs)] +/// Hyperlane database interface +pub trait HyperlaneDb: Send + Sync { + /// Retrieve the nonce of the highest processed message we're aware of + fn retrieve_highest_seen_message_nonce(&self) -> DbResult>; + + /// Retrieve a message by its nonce + fn retrieve_message_by_nonce(&self, nonce: u32) -> DbResult>; + + /// Retrieve whether a message has been processed + fn retrieve_processed_by_nonce(&self, nonce: &u32) -> DbResult>; + + /// Get the origin domain of the database + fn domain(&self) -> &HyperlaneDomain; + + fn store_message_id_by_nonce(&self, nonce: &u32, id: &H256) -> DbResult<()>; + + fn retrieve_message_id_by_nonce(&self, nonce: &u32) -> DbResult>; + + fn store_message_by_id(&self, id: &H256, message: &HyperlaneMessage) -> DbResult<()>; + + fn retrieve_message_by_id(&self, id: &H256) -> DbResult>; + + fn store_dispatched_block_number_by_nonce( + &self, + nonce: &u32, + block_number: &u64, + ) -> DbResult<()>; + + fn retrieve_dispatched_block_number_by_nonce(&self, nonce: &u32) -> DbResult>; + + /// Store whether a message was processed by its nonce + fn store_processed_by_nonce(&self, nonce: &u32, processed: &bool) -> DbResult<()>; + + fn store_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + processed: &bool, + ) -> DbResult<()>; + + fn retrieve_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + ) -> DbResult>; + + fn store_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + data: &InterchainGasExpenditureData, + ) -> DbResult<()>; + + fn retrieve_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + + /// Store the status of an operation by its message id + fn store_status_by_message_id( + &self, + message_id: &H256, + status: &PendingOperationStatus, + ) -> DbResult<()>; + + /// Retrieve the status of an operation by its message id + fn retrieve_status_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + + fn store_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + data: &InterchainGasPaymentData, + ) -> DbResult<()>; + + fn retrieve_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + ) -> DbResult>; + + fn store_gas_payment_by_sequence( + &self, + sequence: &u32, + payment: &InterchainGasPayment, + ) -> DbResult<()>; + + fn retrieve_gas_payment_by_sequence( + &self, + sequence: &u32, + ) -> DbResult>; + + fn store_gas_payment_block_by_sequence( + &self, + sequence: &u32, + block_number: &u64, + ) -> DbResult<()>; + + fn retrieve_gas_payment_block_by_sequence(&self, sequence: &u32) -> DbResult>; + + /// Store the retry count for a pending message by its message id + fn store_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + count: &u32, + ) -> DbResult<()>; + + /// Retrieve the retry count for a pending message by its message id + fn retrieve_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + + fn store_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + insertion: &MerkleTreeInsertion, + ) -> DbResult<()>; + + /// Retrieve the merkle tree insertion event by its leaf index + fn retrieve_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult>; + + fn store_merkle_leaf_index_by_message_id( + &self, + message_id: &H256, + leaf_index: &u32, + ) -> DbResult<()>; + + /// Retrieve the merkle leaf index of a message in the merkle tree + fn retrieve_merkle_leaf_index_by_message_id(&self, message_id: &H256) -> DbResult>; + + fn store_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + block_number: &u64, + ) -> DbResult<()>; + + fn retrieve_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult>; + + fn store_highest_seen_message_nonce_number(&self, nonce: &u32) -> DbResult<()>; + + /// Retrieve the nonce of the highest processed message we're aware of + fn retrieve_highest_seen_message_nonce_number(&self) -> DbResult>; +} diff --git a/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs b/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs index 689878ca3..c99990b43 100644 --- a/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs +++ b/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs @@ -1,18 +1,18 @@ use async_trait::async_trait; use eyre::{bail, Result}; -use paste::paste; use tracing::{debug, instrument, trace}; use hyperlane_core::{ - GasPaymentKey, HyperlaneDomain, HyperlaneLogStore, HyperlaneMessage, + Decode, Encode, GasPaymentKey, HyperlaneDomain, HyperlaneLogStore, HyperlaneMessage, HyperlaneSequenceAwareIndexerStoreReader, HyperlaneWatermarkedLogStore, Indexed, InterchainGasExpenditure, InterchainGasPayment, InterchainGasPaymentMeta, LogMeta, MerkleTreeInsertion, PendingOperationStatus, H256, }; -use super::{ +use super::{DbError, TypedDB, DB}; +use crate::db::{ storage_types::{InterchainGasExpenditureData, InterchainGasPaymentData}, - DbError, TypedDB, DB, + HyperlaneDb, }; // these keys MUST not be given multiple uses in case multiple agents are @@ -120,16 +120,11 @@ impl HyperlaneRocksDB { .retrieve_highest_seen_message_nonce()? .unwrap_or_default(); if nonce >= current_max { - self.store_highest_seen_message_nonce_number(&Default::default(), &nonce)?; + self.store_highest_seen_message_nonce_number(&nonce)?; } Ok(()) } - /// Retrieve the nonce of the highest processed message we're aware of - pub fn retrieve_highest_seen_message_nonce(&self) -> DbResult> { - self.retrieve_highest_seen_message_nonce_number(&Default::default()) - } - /// If the provided gas payment, identified by its metadata, has not been /// processed, processes the gas payment and records it as processed. /// Returns whether the gas payment was processed for the first time. @@ -443,109 +438,241 @@ impl HyperlaneWatermarkedLogStore for HyperlaneRocksDB { } } -/// Database interface required for processing messages -pub trait ProcessMessage: Send + Sync { - /// Retrieve the nonce of the highest processed message we're aware of - fn retrieve_highest_seen_message_nonce(&self) -> DbResult>; +impl HyperlaneDb for HyperlaneRocksDB { + fn retrieve_highest_seen_message_nonce(&self) -> DbResult> { + self.retrieve_highest_seen_message_nonce_number() + } - /// Retrieve a message by its nonce - fn retrieve_message_by_nonce(&self, nonce: u32) -> DbResult>; + fn retrieve_message_by_nonce(&self, nonce: u32) -> DbResult> { + self.retrieve_message_by_nonce(nonce) + } - /// Retrieve whether a message has been processed - fn retrieve_processed_by_nonce(&self, nonce: u32) -> DbResult>; + fn domain(&self) -> &HyperlaneDomain { + self.domain() + } - /// Get the origin domain of the database - fn domain(&self) -> &HyperlaneDomain; -} + fn store_message_id_by_nonce(&self, nonce: &u32, id: &H256) -> DbResult<()> { + self.store_value_by_key(MESSAGE_ID, nonce, id) + } -impl ProcessMessage for HyperlaneRocksDB { - fn retrieve_highest_seen_message_nonce(&self) -> DbResult> { - self.retrieve_highest_seen_message_nonce() + fn retrieve_message_id_by_nonce(&self, nonce: &u32) -> DbResult> { + self.retrieve_value_by_key(MESSAGE_ID, nonce) } - fn retrieve_message_by_nonce(&self, nonce: u32) -> DbResult> { - self.retrieve_message_by_nonce(nonce) + fn store_message_by_id(&self, id: &H256, message: &HyperlaneMessage) -> DbResult<()> { + self.store_value_by_key(MESSAGE, id, message) } - fn retrieve_processed_by_nonce(&self, nonce: u32) -> DbResult> { - self.retrieve_processed_by_nonce(&nonce) + fn retrieve_message_by_id(&self, id: &H256) -> DbResult> { + self.retrieve_value_by_key(MESSAGE, id) } - fn domain(&self) -> &HyperlaneDomain { - self.domain() + fn store_dispatched_block_number_by_nonce( + &self, + nonce: &u32, + block_number: &u64, + ) -> DbResult<()> { + self.store_value_by_key(MESSAGE_DISPATCHED_BLOCK_NUMBER, nonce, block_number) } -} -/// Generate a call to ChainSetup for the given builder -macro_rules! make_store_and_retrieve { - ($vis:vis, $name_suffix:ident, $key_prefix: ident, $key_ty:ty, $val_ty:ty$(,)?) => { - impl HyperlaneRocksDB { - paste! { - /// Stores a key value pair in the DB - $vis fn [] ( - &self, - key: &$key_ty, - val: &$val_ty, - ) -> DbResult<()> { - self.store_keyed_encodable($key_prefix, key, val) - } - - /// Retrieves a key value pair from the DB - $vis fn [] ( - &self, - key: &$key_ty, - ) -> DbResult> { - self.retrieve_keyed_decodable($key_prefix, key) - } - } - } - }; + fn retrieve_dispatched_block_number_by_nonce(&self, nonce: &u32) -> DbResult> { + self.retrieve_value_by_key(MESSAGE_DISPATCHED_BLOCK_NUMBER, nonce) + } + + /// Store whether a message was processed by its nonce + fn store_processed_by_nonce(&self, nonce: &u32, processed: &bool) -> DbResult<()> { + self.store_value_by_key(NONCE_PROCESSED, nonce, processed) + } + + fn retrieve_processed_by_nonce(&self, nonce: &u32) -> DbResult> { + self.retrieve_value_by_key(NONCE_PROCESSED, nonce) + } + + fn store_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + processed: &bool, + ) -> DbResult<()> { + self.store_value_by_key(GAS_PAYMENT_META_PROCESSED, meta, processed) + } + + fn retrieve_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + ) -> DbResult> { + self.retrieve_value_by_key(GAS_PAYMENT_META_PROCESSED, meta) + } + + fn store_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + data: &InterchainGasExpenditureData, + ) -> DbResult<()> { + self.store_value_by_key(GAS_EXPENDITURE_FOR_MESSAGE_ID, message_id, data) + } + + fn retrieve_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + ) -> DbResult> { + self.retrieve_value_by_key(GAS_EXPENDITURE_FOR_MESSAGE_ID, message_id) + } + + /// Store the status of an operation by its message id + fn store_status_by_message_id( + &self, + message_id: &H256, + status: &PendingOperationStatus, + ) -> DbResult<()> { + self.store_value_by_key(STATUS_BY_MESSAGE_ID, message_id, status) + } + + /// Retrieve the status of an operation by its message id + fn retrieve_status_by_message_id( + &self, + message_id: &H256, + ) -> DbResult> { + self.retrieve_value_by_key(STATUS_BY_MESSAGE_ID, message_id) + } + + fn store_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + data: &InterchainGasPaymentData, + ) -> DbResult<()> { + self.store_value_by_key(GAS_PAYMENT_FOR_MESSAGE_ID, key, data) + } + + fn retrieve_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + ) -> DbResult> { + self.retrieve_value_by_key(GAS_PAYMENT_FOR_MESSAGE_ID, key) + } + + fn store_gas_payment_by_sequence( + &self, + sequence: &u32, + payment: &InterchainGasPayment, + ) -> DbResult<()> { + self.store_value_by_key(GAS_PAYMENT_BY_SEQUENCE, sequence, payment) + } + + fn retrieve_gas_payment_by_sequence( + &self, + sequence: &u32, + ) -> DbResult> { + self.retrieve_value_by_key(GAS_PAYMENT_BY_SEQUENCE, sequence) + } + + fn store_gas_payment_block_by_sequence( + &self, + sequence: &u32, + block_number: &u64, + ) -> DbResult<()> { + self.store_value_by_key(GAS_PAYMENT_BLOCK_BY_SEQUENCE, sequence, block_number) + } + + fn retrieve_gas_payment_block_by_sequence(&self, sequence: &u32) -> DbResult> { + self.retrieve_value_by_key(GAS_PAYMENT_BLOCK_BY_SEQUENCE, sequence) + } + + /// Store the retry count for a pending message by its message id + fn store_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + count: &u32, + ) -> DbResult<()> { + self.store_value_by_key( + PENDING_MESSAGE_RETRY_COUNT_FOR_MESSAGE_ID, + message_id, + count, + ) + } + + /// Retrieve the retry count for a pending message by its message id + fn retrieve_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + ) -> DbResult> { + self.retrieve_value_by_key(PENDING_MESSAGE_RETRY_COUNT_FOR_MESSAGE_ID, message_id) + } + + fn store_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + insertion: &MerkleTreeInsertion, + ) -> DbResult<()> { + self.store_value_by_key(MERKLE_TREE_INSERTION, leaf_index, insertion) + } + + /// Retrieve the merkle tree insertion event by its leaf index + fn retrieve_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult> { + self.retrieve_value_by_key(MERKLE_TREE_INSERTION, leaf_index) + } + + fn store_merkle_leaf_index_by_message_id( + &self, + message_id: &H256, + leaf_index: &u32, + ) -> DbResult<()> { + self.store_value_by_key(MERKLE_LEAF_INDEX_BY_MESSAGE_ID, message_id, leaf_index) + } + + /// Retrieve the merkle leaf index of a message in the merkle tree + fn retrieve_merkle_leaf_index_by_message_id(&self, message_id: &H256) -> DbResult> { + self.retrieve_value_by_key(MERKLE_LEAF_INDEX_BY_MESSAGE_ID, message_id) + } + + fn store_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + block_number: &u64, + ) -> DbResult<()> { + self.store_value_by_key( + MERKLE_TREE_INSERTION_BLOCK_NUMBER_BY_LEAF_INDEX, + leaf_index, + block_number, + ) + } + + fn retrieve_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult> { + self.retrieve_value_by_key(MERKLE_TREE_INSERTION_BLOCK_NUMBER_BY_LEAF_INDEX, leaf_index) + } + + fn store_highest_seen_message_nonce_number(&self, nonce: &u32) -> DbResult<()> { + // There's no unit struct Encode/Decode impl, so just use `bool` and always use the `Default::default()` key + self.store_value_by_key(HIGHEST_SEEN_MESSAGE_NONCE, &bool::default(), nonce) + } + + /// Retrieve the nonce of the highest processed message we're aware of + fn retrieve_highest_seen_message_nonce_number(&self) -> DbResult> { + // There's no unit struct Encode/Decode impl, so just use `bool` and always use the `Default::default()` key + self.retrieve_value_by_key(HIGHEST_SEEN_MESSAGE_NONCE, &bool::default()) + } } -make_store_and_retrieve!(pub, message_id_by_nonce, MESSAGE_ID, u32, H256); -make_store_and_retrieve!(pub(self), message_by_id, MESSAGE, H256, HyperlaneMessage); -make_store_and_retrieve!(pub(self), dispatched_block_number_by_nonce, MESSAGE_DISPATCHED_BLOCK_NUMBER, u32, u64); -make_store_and_retrieve!(pub, processed_by_nonce, NONCE_PROCESSED, u32, bool); -make_store_and_retrieve!(pub(self), processed_by_gas_payment_meta, GAS_PAYMENT_META_PROCESSED, InterchainGasPaymentMeta, bool); -make_store_and_retrieve!(pub(self), interchain_gas_expenditure_data_by_message_id, GAS_EXPENDITURE_FOR_MESSAGE_ID, H256, InterchainGasExpenditureData); -make_store_and_retrieve!( - pub, - status_by_message_id, - STATUS_BY_MESSAGE_ID, - H256, - PendingOperationStatus -); -make_store_and_retrieve!(pub(self), interchain_gas_payment_data_by_gas_payment_key, GAS_PAYMENT_FOR_MESSAGE_ID, GasPaymentKey, InterchainGasPaymentData); -make_store_and_retrieve!(pub(self), gas_payment_by_sequence, GAS_PAYMENT_BY_SEQUENCE, u32, InterchainGasPayment); -make_store_and_retrieve!(pub(self), gas_payment_block_by_sequence, GAS_PAYMENT_BLOCK_BY_SEQUENCE, u32, u64); -make_store_and_retrieve!( - pub, - pending_message_retry_count_by_message_id, - PENDING_MESSAGE_RETRY_COUNT_FOR_MESSAGE_ID, - H256, - u32 -); -make_store_and_retrieve!( - pub, - merkle_tree_insertion_by_leaf_index, - MERKLE_TREE_INSERTION, - u32, - MerkleTreeInsertion -); -make_store_and_retrieve!( - pub, - merkle_leaf_index_by_message_id, - MERKLE_LEAF_INDEX_BY_MESSAGE_ID, - H256, - u32 -); -make_store_and_retrieve!( - pub, - merkle_tree_insertion_block_number_by_leaf_index, - MERKLE_TREE_INSERTION_BLOCK_NUMBER_BY_LEAF_INDEX, - u32, - u64 -); -// There's no unit struct Encode/Decode impl, so just use `bool`, have visibility be private (by omitting the first argument), and wrap -// with a function that always uses the `Default::default()` key -make_store_and_retrieve!(, highest_seen_message_nonce_number, HIGHEST_SEEN_MESSAGE_NONCE, bool, u32); +impl HyperlaneRocksDB { + fn store_value_by_key( + &self, + prefix: impl AsRef<[u8]>, + key: &K, + value: &V, + ) -> DbResult<()> { + self.store_encodable(prefix, key.to_vec(), value) + } + + fn retrieve_value_by_key( + &self, + prefix: impl AsRef<[u8]>, + key: &K, + ) -> DbResult> { + self.retrieve_decodable(prefix, key.to_vec()) + } +} diff --git a/rust/main/hyperlane-base/src/db/rocks/mod.rs b/rust/main/hyperlane-base/src/db/rocks/mod.rs index e9a626a15..b92c9bc7e 100644 --- a/rust/main/hyperlane-base/src/db/rocks/mod.rs +++ b/rust/main/hyperlane-base/src/db/rocks/mod.rs @@ -1,7 +1,6 @@ -use std::path::PathBuf; -use std::{io, path::Path, sync::Arc}; +use std::{path::Path, sync::Arc}; -use hyperlane_core::{ChainCommunicationError, HyperlaneProtocolError}; +use super::error::DbError; use rocksdb::{Options, DB as Rocks}; use tracing::info; @@ -16,9 +15,6 @@ mod hyperlane_db; /// Type-specific db operations mod typed_db; -/// Internal-use storage types. -mod storage_types; - /// Database test utilities. #[cfg(any(test, feature = "test-utils"))] pub mod test_utils; @@ -33,37 +29,6 @@ impl From for DB { } } -/// DB Error type -#[derive(thiserror::Error, Debug)] -pub enum DbError { - /// Rocks DB Error - #[error("{0}")] - RockError(#[from] rocksdb::Error), - #[error("Failed to open {path}, canonicalized as {canonicalized}: {source}")] - /// Error opening the database - OpeningError { - /// Rocksdb error during opening - #[source] - source: rocksdb::Error, - /// Raw database path provided - path: PathBuf, - /// Parsed path used - canonicalized: PathBuf, - }, - /// Could not parse the provided database path string - #[error("Invalid database path supplied {1:?}; {0}")] - InvalidDbPath(#[source] io::Error, String), - /// Hyperlane Error - #[error("{0}")] - HyperlaneError(#[from] HyperlaneProtocolError), -} - -impl From for ChainCommunicationError { - fn from(value: DbError) -> Self { - ChainCommunicationError::from_other(value) - } -} - type Result = std::result::Result; impl DB { diff --git a/rust/main/hyperlane-base/src/db/rocks/typed_db.rs b/rust/main/hyperlane-base/src/db/rocks/typed_db.rs index 485731ea3..3008ef838 100644 --- a/rust/main/hyperlane-base/src/db/rocks/typed_db.rs +++ b/rust/main/hyperlane-base/src/db/rocks/typed_db.rs @@ -1,6 +1,6 @@ use hyperlane_core::{Decode, Encode, HyperlaneDomain}; -use crate::db::{DbError, DB}; +use crate::db::{error::DbError, DB}; type Result = std::result::Result; diff --git a/rust/main/hyperlane-base/src/db/rocks/storage_types.rs b/rust/main/hyperlane-base/src/db/storage_types.rs similarity index 90% rename from rust/main/hyperlane-base/src/db/rocks/storage_types.rs rename to rust/main/hyperlane-base/src/db/storage_types.rs index 9c5282c34..bde1eb773 100644 --- a/rust/main/hyperlane-base/src/db/rocks/storage_types.rs +++ b/rust/main/hyperlane-base/src/db/storage_types.rs @@ -8,15 +8,18 @@ use hyperlane_core::{ /// Subset of `InterchainGasPayment` excluding the message id which is stored in /// the key. #[derive(Debug, Copy, Clone)] -pub(super) struct InterchainGasPaymentData { +pub struct InterchainGasPaymentData { + /// The amount of tokens paid for the gas. pub payment: U256, + /// The amount of gas paid for. pub gas_amount: U256, } /// Subset of `InterchainGasExpenditure` excluding the message id which is /// stored in the key. +#[allow(missing_docs)] #[derive(Debug, Copy, Clone)] -pub(super) struct InterchainGasExpenditureData { +pub struct InterchainGasExpenditureData { pub tokens_used: U256, pub gas_used: U256, } @@ -31,6 +34,7 @@ impl Default for InterchainGasPaymentData { } impl InterchainGasPaymentData { + /// Complete the data with the message id and destination. pub fn complete(self, message_id: H256, destination: u32) -> InterchainGasPayment { InterchainGasPayment { message_id, @@ -82,6 +86,7 @@ impl Default for InterchainGasExpenditureData { } impl InterchainGasExpenditureData { + /// Complete the data with the message id. pub fn complete(self, message_id: H256) -> InterchainGasExpenditure { InterchainGasExpenditure { message_id, From c5c217f8ea1a65c81d54b9118618b284bd370acc Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 3 Oct 2024 09:52:57 -0400 Subject: [PATCH 098/224] feat: embed package version in deployed bytecode (#4518) ### Description Embed NPM package version in all deployed contracts bytecode. Follows [similar pattern to published CLI version](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/3010e36ec9ac981fb0e760841c2e9b6a4dde1691/typescript/cli/src/version.ts#L0-L1). Should not be conflated with `Mailbox.VERSION` used for message encoding. ### Drive-by Changes Unfixes solidity NPM package version from typescript packages ### Backward compatibility No, only applies to new deployments or upgrades ### Testing Tested [changeset glob](https://changesets-docs.vercel.app/fixed-packages#using-glob-expressions) ```ts console.log(micromatch(['@hyperlane-xyz/sdk', '@hyperlane-xyz/core', '@hyperlane-xyz/cli'], ['@hyperlane-xyz/!(core)|*'])); ['@hyperlane-xyz/sdk', '@hyperlane-xyz/cli'] ``` Added test that version function is on ABI --- .changeset/config.json | 2 +- .changeset/silent-crabs-visit.md | 5 + solidity/bytecodeversion.sh | 16 + .../contracts/AttributeCheckpointFraud.sol | 4 +- solidity/contracts/CheckpointFraudProofs.sol | 4 +- solidity/contracts/Mailbox.sol | 9 +- solidity/contracts/PackageVersioned.sol | 11 + solidity/contracts/avs/ECDSAStakeRegistry.sol | 5 +- .../contracts/avs/HyperlaneServiceManager.sol | 3 +- solidity/contracts/client/MailboxClient.sol | 3 +- .../contracts/hooks/igp/StorageGasOracle.sol | 3 +- .../hooks/libs/AbstractPostDispatchHook.sol | 6 +- solidity/contracts/isms/NoopIsm.sol | 3 +- solidity/contracts/isms/PausableIsm.sol | 8 +- solidity/contracts/isms/TrustedRelayerIsm.sol | 3 +- .../isms/aggregation/StaticAggregationIsm.sol | 3 +- .../StaticAggregationIsmFactory.sol | 1 + .../hook/AbstractMessageIdAuthorizedIsm.sol | 5 +- .../isms/multisig/AbstractMultisigIsm.sol | 3 +- .../isms/routing/DomainRoutingIsm.sol | 7 +- .../isms/routing/DomainRoutingIsmFactory.sol | 3 +- .../isms/routing/InterchainAccountIsm.sol | 3 +- .../libs/StaticAddressSetFactory.sol | 3 +- .../StaticWeightedValidatorSetFactory.sol | 3 +- solidity/package.json | 12 +- solidity/test/exhaustiveversion.test.ts | 63 ++++ yarn.lock | 277 ++++++++++++++++++ 27 files changed, 443 insertions(+), 25 deletions(-) create mode 100644 .changeset/silent-crabs-visit.md create mode 100755 solidity/bytecodeversion.sh create mode 100644 solidity/contracts/PackageVersioned.sol create mode 100644 solidity/test/exhaustiveversion.test.ts diff --git a/.changeset/config.json b/.changeset/config.json index 03a168c16..84a0cf06c 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -2,7 +2,7 @@ "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", "changelog": "@changesets/cli/changelog", "commit": false, - "fixed": [["@hyperlane-xyz/*"]], + "fixed": [["@hyperlane-xyz/!(core)|*"]], "linked": [], "access": "public", "baseBranch": "main", diff --git a/.changeset/silent-crabs-visit.md b/.changeset/silent-crabs-visit.md new file mode 100644 index 000000000..e6d426ab9 --- /dev/null +++ b/.changeset/silent-crabs-visit.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': minor +--- + +Embed NPM package version in bytecode constant diff --git a/solidity/bytecodeversion.sh b/solidity/bytecodeversion.sh new file mode 100755 index 000000000..2998414f9 --- /dev/null +++ b/solidity/bytecodeversion.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +FILEPATH="contracts/PackageVersioned.sol" +TEMPFILE=$(mktemp) + +# writes all but the last 2 lines to the temp file +head -n $(($(wc -l < $FILEPATH) - 2)) $FILEPATH > $TEMPFILE + +# writes generated last 2 lines to the temp file +cat <> $TEMPFILE + string public constant PACKAGE_VERSION = "$npm_package_version"; +} +EOF + +# overwrite the original file with the temp file +cat $TEMPFILE > $FILEPATH diff --git a/solidity/contracts/AttributeCheckpointFraud.sol b/solidity/contracts/AttributeCheckpointFraud.sol index 357612d04..33c533e37 100644 --- a/solidity/contracts/AttributeCheckpointFraud.sol +++ b/solidity/contracts/AttributeCheckpointFraud.sol @@ -5,6 +5,7 @@ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; import {TREE_DEPTH} from "./libs/Merkle.sol"; import {CheckpointLib, Checkpoint} from "./libs/CheckpointLib.sol"; import {CheckpointFraudProofs} from "./CheckpointFraudProofs.sol"; @@ -26,7 +27,8 @@ struct Attribution { * @title AttributeCheckpointFraud * @dev The AttributeCheckpointFraud contract is used to attribute fraud to a specific ECDSA checkpoint signer. */ -contract AttributeCheckpointFraud is Ownable { + +contract AttributeCheckpointFraud is Ownable, PackageVersioned { using CheckpointLib for Checkpoint; using Address for address; diff --git a/solidity/contracts/CheckpointFraudProofs.sol b/solidity/contracts/CheckpointFraudProofs.sol index 55fa9fc73..adec53002 100644 --- a/solidity/contracts/CheckpointFraudProofs.sol +++ b/solidity/contracts/CheckpointFraudProofs.sol @@ -9,12 +9,14 @@ import {MerkleLib, TREE_DEPTH} from "./libs/Merkle.sol"; import {MerkleTreeHook} from "./hooks/MerkleTreeHook.sol"; import {IMailbox} from "./interfaces/IMailbox.sol"; +import {PackageVersioned} from "./PackageVersioned.sol"; + struct StoredIndex { uint32 index; bool exists; } -contract CheckpointFraudProofs { +contract CheckpointFraudProofs is PackageVersioned { using CheckpointLib for Checkpoint; using Address for address; diff --git a/solidity/contracts/Mailbox.sol b/solidity/contracts/Mailbox.sol index 338bdfc0e..472707684 100644 --- a/solidity/contracts/Mailbox.sol +++ b/solidity/contracts/Mailbox.sol @@ -10,12 +10,19 @@ import {IInterchainSecurityModule, ISpecifiesInterchainSecurityModule} from "./i import {IPostDispatchHook} from "./interfaces/hooks/IPostDispatchHook.sol"; import {IMessageRecipient} from "./interfaces/IMessageRecipient.sol"; import {IMailbox} from "./interfaces/IMailbox.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; // ============ External Imports ============ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -contract Mailbox is IMailbox, Indexed, Versioned, OwnableUpgradeable { +contract Mailbox is + IMailbox, + Indexed, + Versioned, + OwnableUpgradeable, + PackageVersioned +{ // ============ Libraries ============ using Message for bytes; diff --git a/solidity/contracts/PackageVersioned.sol b/solidity/contracts/PackageVersioned.sol new file mode 100644 index 000000000..84e980209 --- /dev/null +++ b/solidity/contracts/PackageVersioned.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.11; + +/** + * @title PackageVersioned + * @notice Package version getter for contracts + **/ +abstract contract PackageVersioned { + // GENERATED CODE - DO NOT EDIT + string public constant PACKAGE_VERSION = "5.3.0"; +} diff --git a/solidity/contracts/avs/ECDSAStakeRegistry.sol b/solidity/contracts/avs/ECDSAStakeRegistry.sol index 6148c3c4e..11d1fa820 100644 --- a/solidity/contracts/avs/ECDSAStakeRegistry.sol +++ b/solidity/contracts/avs/ECDSAStakeRegistry.sol @@ -7,6 +7,8 @@ import {IDelegationManager} from "../interfaces/avs/vendored/IDelegationManager. import {ISignatureUtils} from "../interfaces/avs/vendored/ISignatureUtils.sol"; import {IServiceManager} from "../interfaces/avs/vendored/IServiceManager.sol"; +import {PackageVersioned} from "../PackageVersioned.sol"; + import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {CheckpointsUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/CheckpointsUpgradeable.sol"; import {SignatureCheckerUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol"; @@ -19,7 +21,8 @@ import {IERC1271Upgradeable} from "@openzeppelin/contracts-upgradeable/interface contract ECDSAStakeRegistry is IERC1271Upgradeable, OwnableUpgradeable, - ECDSAStakeRegistryStorage + ECDSAStakeRegistryStorage, + PackageVersioned { using SignatureCheckerUpgradeable for address; using CheckpointsUpgradeable for CheckpointsUpgradeable.History; diff --git a/solidity/contracts/avs/HyperlaneServiceManager.sol b/solidity/contracts/avs/HyperlaneServiceManager.sol index b663695dd..99f27c652 100644 --- a/solidity/contracts/avs/HyperlaneServiceManager.sol +++ b/solidity/contracts/avs/HyperlaneServiceManager.sol @@ -19,8 +19,9 @@ import {IAVSDirectory} from "../interfaces/avs/vendored/IAVSDirectory.sol"; import {IRemoteChallenger} from "../interfaces/avs/IRemoteChallenger.sol"; import {ISlasher} from "../interfaces/avs/vendored/ISlasher.sol"; import {ECDSAServiceManagerBase} from "./ECDSAServiceManagerBase.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; -contract HyperlaneServiceManager is ECDSAServiceManagerBase { +contract HyperlaneServiceManager is ECDSAServiceManagerBase, PackageVersioned { // ============ Libraries ============ using EnumerableMapEnrollment for EnumerableMapEnrollment.AddressToEnrollmentMap; diff --git a/solidity/contracts/client/MailboxClient.sol b/solidity/contracts/client/MailboxClient.sol index 3e0b751e6..41ad7f055 100644 --- a/solidity/contracts/client/MailboxClient.sol +++ b/solidity/contracts/client/MailboxClient.sol @@ -6,12 +6,13 @@ import {IMailbox} from "../interfaces/IMailbox.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {Message} from "../libs/Message.sol"; +import {PackageVersioned} from "../PackageVersioned.sol"; // ============ External Imports ============ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -abstract contract MailboxClient is OwnableUpgradeable { +abstract contract MailboxClient is OwnableUpgradeable, PackageVersioned { using Message for bytes; IMailbox public immutable mailbox; diff --git a/solidity/contracts/hooks/igp/StorageGasOracle.sol b/solidity/contracts/hooks/igp/StorageGasOracle.sol index fb6ca2a83..1c5f9ad15 100644 --- a/solidity/contracts/hooks/igp/StorageGasOracle.sol +++ b/solidity/contracts/hooks/igp/StorageGasOracle.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.0; // ============ Internal Imports ============ import {IGasOracle} from "../../interfaces/IGasOracle.sol"; +import {PackageVersioned} from "../../PackageVersioned.sol"; // ============ External Imports ============ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; @@ -12,7 +13,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; * @dev This contract is intended to be owned by an address that will * update the stored remote gas data. */ -contract StorageGasOracle is IGasOracle, Ownable { +contract StorageGasOracle is IGasOracle, Ownable, PackageVersioned { // ============ Public Storage ============ /// @notice Keyed by remote domain, gas data on that remote domain. diff --git a/solidity/contracts/hooks/libs/AbstractPostDispatchHook.sol b/solidity/contracts/hooks/libs/AbstractPostDispatchHook.sol index 5ad564976..2578af947 100644 --- a/solidity/contracts/hooks/libs/AbstractPostDispatchHook.sol +++ b/solidity/contracts/hooks/libs/AbstractPostDispatchHook.sol @@ -16,12 +16,16 @@ pragma solidity >=0.8.0; // ============ Internal Imports ============ import {StandardHookMetadata} from "./StandardHookMetadata.sol"; import {IPostDispatchHook} from "../../interfaces/hooks/IPostDispatchHook.sol"; +import {PackageVersioned} from "../../PackageVersioned.sol"; /** * @title AbstractPostDispatch * @notice Abstract post dispatch hook supporting the current global hook metadata variant. */ -abstract contract AbstractPostDispatchHook is IPostDispatchHook { +abstract contract AbstractPostDispatchHook is + IPostDispatchHook, + PackageVersioned +{ using StandardHookMetadata for bytes; // ============ External functions ============ diff --git a/solidity/contracts/isms/NoopIsm.sol b/solidity/contracts/isms/NoopIsm.sol index 9e7a7f941..30ac76864 100644 --- a/solidity/contracts/isms/NoopIsm.sol +++ b/solidity/contracts/isms/NoopIsm.sol @@ -2,8 +2,9 @@ pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; -contract NoopIsm is IInterchainSecurityModule { +contract NoopIsm is IInterchainSecurityModule, PackageVersioned { uint8 public constant override moduleType = uint8(Types.NULL); function verify( diff --git a/solidity/contracts/isms/PausableIsm.sol b/solidity/contracts/isms/PausableIsm.sol index cbe696d2e..00868285e 100644 --- a/solidity/contracts/isms/PausableIsm.sol +++ b/solidity/contracts/isms/PausableIsm.sol @@ -7,8 +7,14 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; // ============ Internal Imports ============ import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; -contract PausableIsm is IInterchainSecurityModule, Ownable, Pausable { +contract PausableIsm is + IInterchainSecurityModule, + Ownable, + Pausable, + PackageVersioned +{ uint8 public constant override moduleType = uint8(Types.NULL); constructor(address owner) Ownable() Pausable() { diff --git a/solidity/contracts/isms/TrustedRelayerIsm.sol b/solidity/contracts/isms/TrustedRelayerIsm.sol index 89a8d07d1..aba894a94 100644 --- a/solidity/contracts/isms/TrustedRelayerIsm.sol +++ b/solidity/contracts/isms/TrustedRelayerIsm.sol @@ -5,8 +5,9 @@ pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {Message} from "../libs/Message.sol"; import {Mailbox} from "../Mailbox.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; -contract TrustedRelayerIsm is IInterchainSecurityModule { +contract TrustedRelayerIsm is IInterchainSecurityModule, PackageVersioned { using Message for bytes; uint8 public immutable moduleType = uint8(Types.NULL); diff --git a/solidity/contracts/isms/aggregation/StaticAggregationIsm.sol b/solidity/contracts/isms/aggregation/StaticAggregationIsm.sol index 8e8bbb56e..7a64369af 100644 --- a/solidity/contracts/isms/aggregation/StaticAggregationIsm.sol +++ b/solidity/contracts/isms/aggregation/StaticAggregationIsm.sol @@ -5,13 +5,14 @@ pragma solidity >=0.8.0; import {AbstractAggregationIsm} from "./AbstractAggregationIsm.sol"; import {AggregationIsmMetadata} from "../../isms/libs/AggregationIsmMetadata.sol"; import {MetaProxy} from "../../libs/MetaProxy.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; /** * @title StaticAggregationIsm * @notice Manages per-domain m-of-n ISM sets that are used to verify * interchain messages. */ -contract StaticAggregationIsm is AbstractAggregationIsm { +contract StaticAggregationIsm is AbstractAggregationIsm, PackageVersioned { // ============ Public Functions ============ /** diff --git a/solidity/contracts/isms/aggregation/StaticAggregationIsmFactory.sol b/solidity/contracts/isms/aggregation/StaticAggregationIsmFactory.sol index da4209499..8fa18fa65 100644 --- a/solidity/contracts/isms/aggregation/StaticAggregationIsmFactory.sol +++ b/solidity/contracts/isms/aggregation/StaticAggregationIsmFactory.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; + // ============ Internal Imports ============ import {StaticAggregationIsm} from "./StaticAggregationIsm.sol"; import {StaticThresholdAddressSetFactory} from "../../libs/StaticAddressSetFactory.sol"; diff --git a/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol b/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol index a8b8baee6..43d851345 100644 --- a/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol +++ b/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol @@ -18,9 +18,9 @@ pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol"; import {LibBit} from "../../libs/LibBit.sol"; import {Message} from "../../libs/Message.sol"; +import {PackageVersioned} from "contracts/PackageVersioned.sol"; // ============ External Imports ============ - import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; @@ -31,7 +31,8 @@ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Ini */ abstract contract AbstractMessageIdAuthorizedIsm is IInterchainSecurityModule, - Initializable + Initializable, + PackageVersioned { using Address for address payable; using LibBit for uint256; diff --git a/solidity/contracts/isms/multisig/AbstractMultisigIsm.sol b/solidity/contracts/isms/multisig/AbstractMultisigIsm.sol index 0d56319b9..3b59d130c 100644 --- a/solidity/contracts/isms/multisig/AbstractMultisigIsm.sol +++ b/solidity/contracts/isms/multisig/AbstractMultisigIsm.sol @@ -21,6 +21,7 @@ import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityMod import {IMultisigIsm} from "../../interfaces/isms/IMultisigIsm.sol"; import {Message} from "../../libs/Message.sol"; import {MerkleLib} from "../../libs/Merkle.sol"; +import {PackageVersioned} from "../../PackageVersioned.sol"; /** * @title AbstractMultisig @@ -29,7 +30,7 @@ import {MerkleLib} from "../../libs/Merkle.sol"; * for concrete implementations of `digest` and `signatureAt`. * @dev See ./StaticMultisigIsm.sol for concrete implementations. */ -abstract contract AbstractMultisig { +abstract contract AbstractMultisig is PackageVersioned { /** * @notice Returns the digest to be used for signature verification. * @param _metadata ABI encoded module metadata diff --git a/solidity/contracts/isms/routing/DomainRoutingIsm.sol b/solidity/contracts/isms/routing/DomainRoutingIsm.sol index 3b4d753ae..4203d6348 100644 --- a/solidity/contracts/isms/routing/DomainRoutingIsm.sol +++ b/solidity/contracts/isms/routing/DomainRoutingIsm.sol @@ -12,11 +12,16 @@ import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityMod import {Message} from "../../libs/Message.sol"; import {TypeCasts} from "../../libs/TypeCasts.sol"; import {EnumerableMapExtended} from "../../libs/EnumerableMapExtended.sol"; +import {PackageVersioned} from "../../PackageVersioned.sol"; /** * @title DomainRoutingIsm */ -contract DomainRoutingIsm is AbstractRoutingIsm, OwnableUpgradeable { +contract DomainRoutingIsm is + AbstractRoutingIsm, + OwnableUpgradeable, + PackageVersioned +{ using EnumerableMapExtended for EnumerableMapExtended.UintToBytes32Map; using Message for bytes; using TypeCasts for bytes32; diff --git a/solidity/contracts/isms/routing/DomainRoutingIsmFactory.sol b/solidity/contracts/isms/routing/DomainRoutingIsmFactory.sol index fc8b20383..8015fd8e2 100644 --- a/solidity/contracts/isms/routing/DomainRoutingIsmFactory.sol +++ b/solidity/contracts/isms/routing/DomainRoutingIsmFactory.sol @@ -6,8 +6,9 @@ import {DomainRoutingIsm} from "./DomainRoutingIsm.sol"; import {DefaultFallbackRoutingIsm} from "./DefaultFallbackRoutingIsm.sol"; import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol"; import {MinimalProxy} from "../../libs/MinimalProxy.sol"; +import {PackageVersioned} from "../../PackageVersioned.sol"; -abstract contract AbstractDomainRoutingIsmFactory { +abstract contract AbstractDomainRoutingIsmFactory is PackageVersioned { /** * @notice Emitted when a routing module is deployed * @param module The deployed ISM diff --git a/solidity/contracts/isms/routing/InterchainAccountIsm.sol b/solidity/contracts/isms/routing/InterchainAccountIsm.sol index e509e603d..9adecfe88 100644 --- a/solidity/contracts/isms/routing/InterchainAccountIsm.sol +++ b/solidity/contracts/isms/routing/InterchainAccountIsm.sol @@ -6,11 +6,12 @@ import {IMailbox} from "../../interfaces/IMailbox.sol"; import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol"; import {Message} from "../../libs/Message.sol"; import {InterchainAccountMessage} from "../../middleware/libs/InterchainAccountMessage.sol"; +import {PackageVersioned} from "../../PackageVersioned.sol"; /** * @title InterchainAccountIsm */ -contract InterchainAccountIsm is AbstractRoutingIsm { +contract InterchainAccountIsm is AbstractRoutingIsm, PackageVersioned { IMailbox private immutable mailbox; // ============ Constructor ============ diff --git a/solidity/contracts/libs/StaticAddressSetFactory.sol b/solidity/contracts/libs/StaticAddressSetFactory.sol index 82df1e168..38da45b8b 100644 --- a/solidity/contracts/libs/StaticAddressSetFactory.sol +++ b/solidity/contracts/libs/StaticAddressSetFactory.sol @@ -6,8 +6,9 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; // ============ Internal Imports ============ import {MetaProxy} from "./MetaProxy.sol"; +import {PackageVersioned} from "../PackageVersioned.sol"; -abstract contract StaticThresholdAddressSetFactory { +abstract contract StaticThresholdAddressSetFactory is PackageVersioned { // ============ Immutables ============ address public immutable implementation; diff --git a/solidity/contracts/libs/StaticWeightedValidatorSetFactory.sol b/solidity/contracts/libs/StaticWeightedValidatorSetFactory.sol index 9e9516dac..6cd849420 100644 --- a/solidity/contracts/libs/StaticWeightedValidatorSetFactory.sol +++ b/solidity/contracts/libs/StaticWeightedValidatorSetFactory.sol @@ -8,8 +8,9 @@ import {IStaticWeightedMultisigIsm} from "../interfaces/isms/IWeightedMultisigIs // ============ Internal Imports ============ import {MetaProxy} from "./MetaProxy.sol"; +import {PackageVersioned} from "../PackageVersioned.sol"; -abstract contract StaticWeightedValidatorSetFactory { +abstract contract StaticWeightedValidatorSetFactory is PackageVersioned { // ============ Immutables ============ address public immutable implementation; diff --git a/solidity/package.json b/solidity/package.json index e5fe859f0..e38ec2435 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -33,6 +33,7 @@ "solidity-coverage": "^0.8.3", "ts-generator": "^0.1.1", "ts-node": "^10.8.0", + "tsx": "^4.19.1", "typechain": "patch:typechain@npm%3A8.3.2#~/.yarn/patches/typechain-npm-8.3.2-b02e27439e.patch", "typescript": "5.3.3" }, @@ -63,7 +64,7 @@ ], "license": "Apache-2.0", "scripts": { - "build": "yarn hardhat-esm compile && tsc && ./exportBuildArtifact.sh", + "build": "yarn version:bytecode && yarn hardhat-esm compile && tsc && ./exportBuildArtifact.sh", "lint": "solhint contracts/**/*.sol", "clean": "yarn hardhat-esm clean && rm -rf ./dist ./cache ./types ./coverage ./out ./forge-cache ./fixtures", "coverage": "yarn fixtures && ./coverage.sh", @@ -71,14 +72,17 @@ "fixtures": "mkdir -p ./fixtures/aggregation ./fixtures/multisig", "hardhat-esm": "NODE_OPTIONS='--experimental-loader ts-node/esm/transpile-only --no-warnings=ExperimentalWarning' hardhat --config hardhat.config.cts", "prettier": "prettier --write ./contracts ./test", - "test": "yarn hardhat-esm test && yarn test:forge", + "test": "yarn version:exhaustive && yarn hardhat-esm test && yarn test:forge", "test:hardhat": "yarn hardhat-esm test", "test:forge": "yarn fixtures && forge test -vvv", - "test:ci": "yarn test:hardhat && yarn test:forge --no-match-test testFork", + "test:ci": "yarn version:changed && yarn test:hardhat && yarn test:forge --no-match-test testFork", "gas": "forge snapshot", "gas-ci": "yarn gas --check --tolerance 2 || (echo 'Manually update gas snapshot' && exit 1)", "slither": "slither .", - "storage": "./storage.sh" + "storage": "./storage.sh", + "version:bytecode": "./bytecodeversion.sh", + "version:changed": "yarn version:bytecode && git diff --exit-code", + "version:exhaustive": "yarn tsx ./test/exhaustiveversion.test.ts" }, "peerDependencies": { "@ethersproject/abi": "*", diff --git a/solidity/test/exhaustiveversion.test.ts b/solidity/test/exhaustiveversion.test.ts new file mode 100644 index 000000000..e43909927 --- /dev/null +++ b/solidity/test/exhaustiveversion.test.ts @@ -0,0 +1,63 @@ +import { CompilerOutputContract } from 'hardhat/types'; +import { readFile, readdir } from 'node:fs/promises'; +import { basename, join } from 'node:path'; + +const EXCLUDE_PATTERNS: RegExp[] = [ + /\.dbg/g, + /interfaces\//g, + /libs\//g, + /Abstract/g, + /Test/g, + /Mock/g, + /Versioned/g, + // also abstract + /ECDSAServiceManagerBase/g, + /ECDSAStakeRegistryStorage/g, +]; +const REQUIRED_METHOD = 'PACKAGE_VERSION'; + +// https://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search +const walk = async (dirPath) => + Promise.all( + await readdir(dirPath, { withFileTypes: true }).then((entries) => + entries.map((entry) => { + const childPath = join(dirPath, entry.name); + return entry.isDirectory() ? walk(childPath) : childPath; + }), + ), + ); + +const artifacts = (await walk('artifacts/contracts')).flat( + Number.POSITIVE_INFINITY, +); + +const filtered = artifacts.filter((path: string) => + EXCLUDE_PATTERNS.every((excluded) => path.match(excluded) === null), +); + +const results = await Promise.all( + filtered.map(async (path) => { + const content = await readFile(path, 'utf-8'); + const compilerOutput: CompilerOutputContract = JSON.parse(content); + return [ + path, + compilerOutput.abi && + compilerOutput.abi.some((elem) => elem.name === REQUIRED_METHOD), + ]; + }), +); + +const missing = results.filter(([, included]) => !included); + +if (missing.length > 0) { + console.error( + `Missing ${REQUIRED_METHOD} method in the following contracts:`, + ); + const contracts = missing.map(([path]) => + basename(path).replace('.json', ''), + ); + console.error(contracts.map((contract) => ` - ${contract}`).join('\n')); + process.exit(1); +} + +console.log('All contracts have the required method'); diff --git a/yarn.lock b/yarn.lock index b99daa980..1990c5588 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5780,6 +5780,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/aix-ppc64@npm:0.23.1" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/android-arm64@npm:0.17.19" @@ -5808,6 +5815,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/android-arm64@npm:0.23.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/android-arm@npm:0.17.19" @@ -5836,6 +5850,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/android-arm@npm:0.23.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/android-x64@npm:0.17.19" @@ -5864,6 +5885,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/android-x64@npm:0.23.1" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/darwin-arm64@npm:0.17.19" @@ -5892,6 +5920,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/darwin-arm64@npm:0.23.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/darwin-x64@npm:0.17.19" @@ -5920,6 +5955,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/darwin-x64@npm:0.23.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/freebsd-arm64@npm:0.17.19" @@ -5948,6 +5990,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/freebsd-arm64@npm:0.23.1" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/freebsd-x64@npm:0.17.19" @@ -5976,6 +6025,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/freebsd-x64@npm:0.23.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-arm64@npm:0.17.19" @@ -6004,6 +6060,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-arm64@npm:0.23.1" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-arm@npm:0.17.19" @@ -6032,6 +6095,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-arm@npm:0.23.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-ia32@npm:0.17.19" @@ -6060,6 +6130,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-ia32@npm:0.23.1" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-loong64@npm:0.17.19" @@ -6088,6 +6165,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-loong64@npm:0.23.1" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-mips64el@npm:0.17.19" @@ -6116,6 +6200,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-mips64el@npm:0.23.1" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-ppc64@npm:0.17.19" @@ -6144,6 +6235,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-ppc64@npm:0.23.1" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-riscv64@npm:0.17.19" @@ -6172,6 +6270,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-riscv64@npm:0.23.1" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-s390x@npm:0.17.19" @@ -6200,6 +6305,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-s390x@npm:0.23.1" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-x64@npm:0.17.19" @@ -6228,6 +6340,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/linux-x64@npm:0.23.1" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/netbsd-x64@npm:0.17.19" @@ -6256,6 +6375,20 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/netbsd-x64@npm:0.23.1" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/openbsd-arm64@npm:0.23.1" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/openbsd-x64@npm:0.17.19" @@ -6284,6 +6417,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/openbsd-x64@npm:0.23.1" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/sunos-x64@npm:0.17.19" @@ -6312,6 +6452,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/sunos-x64@npm:0.23.1" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/win32-arm64@npm:0.17.19" @@ -6340,6 +6487,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/win32-arm64@npm:0.23.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/win32-ia32@npm:0.17.19" @@ -6368,6 +6522,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/win32-ia32@npm:0.23.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/win32-x64@npm:0.17.19" @@ -6396,6 +6557,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.23.1": + version: 0.23.1 + resolution: "@esbuild/win32-x64@npm:0.23.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -7654,6 +7822,7 @@ __metadata: solidity-coverage: "npm:^0.8.3" ts-generator: "npm:^0.1.1" ts-node: "npm:^10.8.0" + tsx: "npm:^4.19.1" typechain: "patch:typechain@npm%3A8.3.2#~/.yarn/patches/typechain-npm-8.3.2-b02e27439e.patch" typescript: "npm:5.3.3" peerDependencies: @@ -18279,6 +18448,89 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:~0.23.0": + version: 0.23.1 + resolution: "esbuild@npm:0.23.1" + dependencies: + "@esbuild/aix-ppc64": "npm:0.23.1" + "@esbuild/android-arm": "npm:0.23.1" + "@esbuild/android-arm64": "npm:0.23.1" + "@esbuild/android-x64": "npm:0.23.1" + "@esbuild/darwin-arm64": "npm:0.23.1" + "@esbuild/darwin-x64": "npm:0.23.1" + "@esbuild/freebsd-arm64": "npm:0.23.1" + "@esbuild/freebsd-x64": "npm:0.23.1" + "@esbuild/linux-arm": "npm:0.23.1" + "@esbuild/linux-arm64": "npm:0.23.1" + "@esbuild/linux-ia32": "npm:0.23.1" + "@esbuild/linux-loong64": "npm:0.23.1" + "@esbuild/linux-mips64el": "npm:0.23.1" + "@esbuild/linux-ppc64": "npm:0.23.1" + "@esbuild/linux-riscv64": "npm:0.23.1" + "@esbuild/linux-s390x": "npm:0.23.1" + "@esbuild/linux-x64": "npm:0.23.1" + "@esbuild/netbsd-x64": "npm:0.23.1" + "@esbuild/openbsd-arm64": "npm:0.23.1" + "@esbuild/openbsd-x64": "npm:0.23.1" + "@esbuild/sunos-x64": "npm:0.23.1" + "@esbuild/win32-arm64": "npm:0.23.1" + "@esbuild/win32-ia32": "npm:0.23.1" + "@esbuild/win32-x64": "npm:0.23.1" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: f55fbd0bfb0f86ce67a6d2c6f6780729d536c330999ecb9f5a38d578fb9fda820acbbc67d6d1d377eed8fed50fc38f14ff9cb014f86dafab94269a7fb2177018 + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -20100,6 +20352,15 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.7.5": + version: 4.8.1 + resolution: "get-tsconfig@npm:4.8.1" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 3fb5a8ad57b9633eaea085d81661e9e5c9f78b35d8f8689eaf8b8b45a2a3ebf3b3422266d4d7df765e308cc1e6231648d114803ab3d018332e29916f2c1de036 + languageName: node + linkType: hard + "getpass@npm:^0.1.1": version: 0.1.7 resolution: "getpass@npm:0.1.7" @@ -29828,6 +30089,22 @@ __metadata: languageName: node linkType: hard +"tsx@npm:^4.19.1": + version: 4.19.1 + resolution: "tsx@npm:4.19.1" + dependencies: + esbuild: "npm:~0.23.0" + fsevents: "npm:~2.3.3" + get-tsconfig: "npm:^4.7.5" + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: 1f5f0b7c4107fc18f523e94c79204b043641aa328f721324795cc961826879035652a1f19fe29ba420465d9f4bacb0f47e08f0bd4b934684ab45727eca110311 + languageName: node + linkType: hard + "tsx@npm:^4.7.1": version: 4.7.1 resolution: "tsx@npm:4.7.1" From 7c5766e51d82c9985afa9286b1d5068b35292967 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 3 Oct 2024 15:14:24 -0400 Subject: [PATCH 099/224] feat: small QoL improvement for adding changesets (#4619) ### Description `changeset add` will auto commit --- .changeset/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/config.json b/.changeset/config.json index 84a0cf06c..d72044ed2 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,7 +1,7 @@ { "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", "changelog": "@changesets/cli/changelog", - "commit": false, + "commit": true, "fixed": [["@hyperlane-xyz/!(core)|*"]], "linked": [], "access": "public", From ca86da471830647c76e45cd22241c3022e51d48f Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Fri, 4 Oct 2024 01:16:08 +0100 Subject: [PATCH 100/224] fix: write merkle & IGP hook addresses if created by core deploy (#4607) ### Description original: there was a series of related problems that people are encountering with cli deploys where the merkleTreeHook is deployed but its address is not included in the artifacts. this PR was intended to bring parity with how infra does it, we can also update for now to only add the merkleTreeHook to the output to unblock the base problem people are having update: restricted to just `merkleTreeHook` and `interchainGasPaymaster` to provide MVP fix ![image](https://github.com/user-attachments/assets/9f38c3a8-5240-4cbe-a224-161a7a4da8af) ### Related issues https://github.com/hyperlane-xyz/hyperlane-registry/pull/240#discussion_r1784297872 https://github.com/hyperlane-xyz/hyperlane-registry/pull/236#issuecomment-2383922133 https://github.com/hyperlane-xyz/hyperlane-registry/pull/237#discussion_r1782564051 ### Backward compatibility yes ### Testing manual --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .../src/core/EvmCoreModule.hardhat-test.ts | 8 +++++--- typescript/sdk/src/core/EvmCoreModule.ts | 20 ++++++++++++++++++- typescript/sdk/src/core/schemas.ts | 2 ++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts b/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts index 408ea4e2b..13f81f92e 100644 --- a/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts +++ b/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts @@ -105,10 +105,12 @@ describe('EvmCoreModule', async () => { }); it('should deploy ISM factories', () => { - // Each ISM factory - const deployedContracts = evmCoreModule.serialize(); + // Each ISM factory is a contract that is deployed by the core module + // Ignore IGP because it's not part of the default config + const { interchainGasPaymaster: _, ...coreContracts } = + evmCoreModule.serialize(); - objMap(deployedContracts as any, (_, address) => { + objMap(coreContracts as any, (_, address) => { expect(address).to.exist; expect(address).to.not.equal(constants.AddressZero); }); diff --git a/typescript/sdk/src/core/EvmCoreModule.ts b/typescript/sdk/src/core/EvmCoreModule.ts index 1ab4ef649..f8f726c52 100644 --- a/typescript/sdk/src/core/EvmCoreModule.ts +++ b/typescript/sdk/src/core/EvmCoreModule.ts @@ -11,7 +11,10 @@ import { attachContractsMap, serializeContractsMap, } from '../contracts/contracts.js'; -import { HyperlaneAddresses } from '../contracts/types.js'; +import { + HyperlaneAddresses, + HyperlaneContractsMap, +} from '../contracts/types.js'; import { DeployedCoreAddresses } from '../core/schemas.js'; import { CoreConfig } from '../core/types.js'; import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js'; @@ -20,6 +23,7 @@ import { proxyFactoryFactories, } from '../deploy/contracts.js'; import { ContractVerifier } from '../deploy/verify/ContractVerifier.js'; +import { HookFactories } from '../hook/contracts.js'; import { EvmIsmModule } from '../ism/EvmIsmModule.js'; import { DerivedIsmConfig } from '../ism/EvmIsmReader.js'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js'; @@ -35,6 +39,7 @@ import { import { EvmCoreReader } from './EvmCoreReader.js'; import { EvmIcaModule } from './EvmIcaModule.js'; import { HyperlaneCoreDeployer } from './HyperlaneCoreDeployer.js'; +import { CoreFactories } from './contracts.js'; import { CoreConfigSchema } from './schemas.js'; export class EvmCoreModule extends HyperlaneModule< @@ -315,9 +320,20 @@ export class EvmCoreModule extends HyperlaneModule< ) ).address; + // Obtain addresses of every contract created by the deployer + // and extract only the merkleTreeHook and interchainGasPaymaster + const serializedContracts = serializeContractsMap( + coreDeployer.deployedContracts as HyperlaneContractsMap< + CoreFactories & HookFactories + >, + ); + const { merkleTreeHook, interchainGasPaymaster } = + serializedContracts[chainName]; + // Set Core & extra addresses return { ...ismFactoryFactories, + proxyAdmin, mailbox: mailbox.address, interchainAccountRouter, @@ -325,6 +341,8 @@ export class EvmCoreModule extends HyperlaneModule< validatorAnnounce, timelockController, testRecipient, + merkleTreeHook, + interchainGasPaymaster, }; } diff --git a/typescript/sdk/src/core/schemas.ts b/typescript/sdk/src/core/schemas.ts index 79b08bf24..569bb2ee0 100644 --- a/typescript/sdk/src/core/schemas.ts +++ b/typescript/sdk/src/core/schemas.ts @@ -19,6 +19,8 @@ export const DeployedCoreAddressesSchema = ProxyFactoryFactoriesSchema.extend({ timelockController: z.string().optional(), interchainAccountRouter: z.string(), interchainAccountIsm: z.string(), + merkleTreeHook: z.string().optional(), + interchainGasPaymaster: z.string().optional(), }); export type DeployedCoreAddresses = z.infer; From 27a0552938bafd7081a844da805aee839e040b82 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Fri, 4 Oct 2024 11:16:30 +0100 Subject: [PATCH 101/224] chore: disable tangle for now (#4625) ### Description Seems like they have issues with the chain / RPC ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/infra/config/environments/mainnet3/agent.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 20bae5623..04d2e99fa 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -107,7 +107,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< shibarium: true, solanamainnet: true, taiko: true, - tangle: true, + tangle: false, viction: true, worldchain: true, xai: true, @@ -171,7 +171,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< shibarium: true, solanamainnet: true, taiko: true, - tangle: true, + tangle: false, viction: true, worldchain: true, xai: true, @@ -241,7 +241,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< // Cannot scrape non-EVM chains solanamainnet: false, taiko: true, - tangle: true, + tangle: false, // Has RPC non-compliance that breaks scraping. viction: false, worldchain: true, From 6b5746726700ee44bacb9d083d11953c2e836265 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:55:14 +0100 Subject: [PATCH 102/224] fix: monorepo docker build (#4626) ### Description fix: monorepo docker build, which seems to have been broken from https://github.com/hyperlane-xyz/hyperlane-monorepo/commit/c5c217f8ea1a65c81d54b9118618b284bd370acc#diff-ec261746751beaecd8c9dfe0ad06d2be8e74889eafbe5f7fcbb025726fb2cd90R67 ### Drive-by changes na ### Related issues na ### Backward compatibility y ### Testing trying --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- solidity/bytecodeversion.sh | 2 +- solidity/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solidity/bytecodeversion.sh b/solidity/bytecodeversion.sh index 2998414f9..b30ae6979 100755 --- a/solidity/bytecodeversion.sh +++ b/solidity/bytecodeversion.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh FILEPATH="contracts/PackageVersioned.sol" TEMPFILE=$(mktemp) diff --git a/solidity/package.json b/solidity/package.json index e38ec2435..2adae6c6d 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -80,7 +80,7 @@ "gas-ci": "yarn gas --check --tolerance 2 || (echo 'Manually update gas snapshot' && exit 1)", "slither": "slither .", "storage": "./storage.sh", - "version:bytecode": "./bytecodeversion.sh", + "version:bytecode": "sh ./bytecodeversion.sh", "version:changed": "yarn version:bytecode && git diff --exit-code", "version:exhaustive": "yarn tsx ./test/exhaustiveversion.test.ts" }, From dc9adf3b55eb8f727fd689e40f8a8921e64e6fb8 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:43:14 -0400 Subject: [PATCH 103/224] feat: Add pzEth Config Generator (#4624) ### Description Adds pzEth Config Generator files to deploy to ethereum and zircuit - new lockbox and xerc20 addresses - supplied via this message: https://t.me/c/2192542084/925 - Reusing ezEth validators config for both chains - Reusing Safe addresses. - confirmed via this message: https://t.me/c/2192542084/948 ### Drive-by changes Rename to differentiate between ezEth and pzEth ### Related issues #4623 ### Backward compatibility Yes ### Testing Manual --- ...rpConifg.ts => getRenzoEZETHWarpConfig.ts} | 4 +- .../configGetters/getRenzoPZETHWarpConfig.ts | 104 ++++++++++++++++++ typescript/infra/config/warp.ts | 2 +- ...generate-renzo-ezeth-warp-route-config.ts} | 4 +- .../generate-renzo-pzeth-warp-route-config.ts | 23 ++++ 5 files changed, 132 insertions(+), 5 deletions(-) rename typescript/infra/config/environments/mainnet3/warp/configGetters/{getRenzoEZETHWarpConifg.ts => getRenzoEZETHWarpConfig.ts} (98%) create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts rename typescript/infra/scripts/{generate-renzo-warp-route-config.ts => generate-renzo-ezeth-warp-route-config.ts} (85%) create mode 100644 typescript/infra/scripts/generate-renzo-pzeth-warp-route-config.ts diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts similarity index 98% rename from typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts rename to typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts index 2203a8c42..fdb00d30a 100644 --- a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts @@ -28,7 +28,7 @@ const chainsToDeploy = [ 'zircuit', ]; -const ezEthValidators = { +export const ezEthValidators = { arbitrum: { threshold: 1, validators: [ @@ -101,7 +101,7 @@ const ezEthValidators = { }, }; -const ezEthSafes: Record = { +export const ezEthSafes: Record = { arbitrum: '0x0e60fd361fF5b90088e1782e6b21A7D177d462C5', optimism: '0x8410927C286A38883BC23721e640F31D3E3E79F8', base: '0x8410927C286A38883BC23721e640F31D3E3E79F8', diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts new file mode 100644 index 000000000..b9e9b42bb --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts @@ -0,0 +1,104 @@ +import { + ChainMap, + IsmType, + TokenRouterConfig, + TokenType, + buildAggregationIsmConfigs, +} from '@hyperlane-xyz/sdk'; +import { symmetricDifference } from '@hyperlane-xyz/utils'; + +import { getRegistry as getMainnet3Registry } from '../../chains.js'; + +import { ezEthSafes, ezEthValidators } from './getRenzoEZETHWarpConfig.js'; + +const lockbox = '0xbC5511354C4A9a50DE928F56DB01DD327c4e56d5'; +const xERC20 = '0x9cb41CD74D01ae4b4f640EC40f7A60cA1bCF83E7'; +const lockboxChain = 'ethereum'; +// over the default 100k to account for xerc20 gas + ISM overhead over the default ISM https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/49f41d9759fd515bfd89e6e22e799c41b27b4119/typescript/sdk/src/router/GasRouterDeployer.ts#L14 +const warpRouteOverheadGas = 200_000; + +const chainsToDeploy = ['ethereum', 'zircuit']; + +const pzEthValidators = { + ethereum: ezEthValidators.ethereum, + zircuit: ezEthValidators.zircuit, +}; + +const pzEthSafes: Record = { + ethereum: ezEthSafes.ethereum, + zircuit: ezEthSafes.zircuit, +}; + +export const getRenzoPZETHWarpConfig = async (): Promise< + ChainMap +> => { + const registry = await getMainnet3Registry(); + + const validatorDiff = symmetricDifference( + new Set(chainsToDeploy), + new Set(Object.keys(pzEthValidators)), + ); + const safeDiff = symmetricDifference( + new Set(chainsToDeploy), + new Set(Object.keys(pzEthSafes)), + ); + if (validatorDiff.size > 0) { + throw new Error( + `chainsToDeploy !== validatorConfig, diff is ${Array.from( + validatorDiff, + ).join(', ')}`, + ); + } + if (safeDiff.size > 0) { + throw new Error( + `chainsToDeploy !== safeDiff, diff is ${Array.from(safeDiff).join(', ')}`, + ); + } + + const tokenConfig = Object.fromEntries( + await Promise.all( + chainsToDeploy.map( + async (chain): Promise<[string, TokenRouterConfig]> => { + const ret: [string, TokenRouterConfig] = [ + chain, + { + isNft: false, + type: + chain === lockboxChain + ? TokenType.XERC20Lockbox + : TokenType.XERC20, + token: chain === lockboxChain ? lockbox : xERC20, + owner: pzEthSafes[chain], + gas: warpRouteOverheadGas, + mailbox: (await registry.getChainAddresses(chain))!.mailbox, + interchainSecurityModule: { + type: IsmType.AGGREGATION, + threshold: 2, + modules: [ + { + type: IsmType.ROUTING, + owner: pzEthSafes[chain], + domains: buildAggregationIsmConfigs( + chain, + chainsToDeploy, + pzEthValidators, + ), + }, + { + type: IsmType.FALLBACK_ROUTING, + domains: {}, + owner: pzEthSafes[chain], + }, + ], + }, + }, + ]; + + return ret; + }, + ), + ), + ); + + return tokenConfig; +}; diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index b96c74c4f..994c9fa9c 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -20,7 +20,7 @@ import { getEthereumVictionUSDCWarpConfig } from './environments/mainnet3/warp/c import { getEthereumVictionUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionUSDTWarpConfig.js'; import { getInevmInjectiveINJWarpConfig } from './environments/mainnet3/warp/configGetters/getInevmInjectiveINJWarpConfig.js'; import { getMantapacificNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getMantapacificNeutronTiaWarpConfig.js'; -import { getRenzoEZETHWarpConfig } from './environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.js'; +import { getRenzoEZETHWarpConfig } from './environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.js'; import { WarpRouteIds } from './environments/mainnet3/warp/warpIds.js'; type WarpConfigGetterWithConfig = ( diff --git a/typescript/infra/scripts/generate-renzo-warp-route-config.ts b/typescript/infra/scripts/generate-renzo-ezeth-warp-route-config.ts similarity index 85% rename from typescript/infra/scripts/generate-renzo-warp-route-config.ts rename to typescript/infra/scripts/generate-renzo-ezeth-warp-route-config.ts index 5cb917d1b..c8175b0e4 100644 --- a/typescript/infra/scripts/generate-renzo-warp-route-config.ts +++ b/typescript/infra/scripts/generate-renzo-ezeth-warp-route-config.ts @@ -3,7 +3,7 @@ import { stringify as yamlStringify } from 'yaml'; import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk'; -import { getRenzoEZETHWarpConfig } from '../config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.js'; +import { getRenzoEZETHWarpConfig } from '../config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.js'; async function main() { const tokenConfig = await getRenzoEZETHWarpConfig(); @@ -15,7 +15,7 @@ async function main() { } writeFileSync( - 'renzo-warp-route-config.yaml', + 'renzo-ezeth-warp-route-config.yaml', yamlStringify(parsed.data, null, 2), ); } diff --git a/typescript/infra/scripts/generate-renzo-pzeth-warp-route-config.ts b/typescript/infra/scripts/generate-renzo-pzeth-warp-route-config.ts new file mode 100644 index 000000000..b65cca5f0 --- /dev/null +++ b/typescript/infra/scripts/generate-renzo-pzeth-warp-route-config.ts @@ -0,0 +1,23 @@ +import { writeFileSync } from 'fs'; +import { stringify as yamlStringify } from 'yaml'; + +import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk'; + +import { getRenzoPZETHWarpConfig } from '../config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.js'; + +async function main() { + const tokenConfig = await getRenzoPZETHWarpConfig(); + const parsed = WarpRouteDeployConfigSchema.safeParse(tokenConfig); + + if (!parsed.success) { + console.dir(parsed.error.format(), { depth: null }); + return; + } + + writeFileSync( + 'renzo-pzeth-warp-route-config.yaml', + yamlStringify(parsed.data, null, 2), + ); +} + +main().catch(console.error).then(console.log); From 8809f372717bd11a446a78bd77797147a6baa4f1 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:13:50 +0100 Subject: [PATCH 104/224] feat: checkpoint syncer fraud flag (#4587) Upon detection of a merkle root mismatch between the local merkle tree (built from indexed events) and the onchain one, reorg diagnostic data is posted to checkpoint storage. This PR focuses on the submitter logic and leaves two things for a follow up PR: - adding logic to not spin up the validator if a fraud flag has been posted - integration testing with S3 and GCP I assume rolling out to validators will happen after the follow up PR, but running with logic from this PR will already mean the reorg diagnostic flag is posted to S3 (though not tested). --- rust/main/Cargo.lock | 2 + rust/main/Cargo.toml | 1 + rust/main/agents/relayer/Cargo.toml | 1 + rust/main/agents/relayer/src/msg/processor.rs | 15 +- rust/main/agents/validator/Cargo.toml | 3 + rust/main/agents/validator/src/submit.rs | 346 +++++++++++++++++- .../main/chains/hyperlane-ethereum/Cargo.toml | 4 + .../src/signer/singleton.rs | 8 + .../src/traits/checkpoint_syncer.rs | 8 +- .../hyperlane-base/src/types/gcs_storage.rs | 15 +- .../hyperlane-base/src/types/local_storage.rs | 23 +- .../hyperlane-base/src/types/s3_storage.rs | 21 +- rust/main/hyperlane-core/src/test_utils.rs | 14 +- rust/main/hyperlane-core/src/types/mod.rs | 2 + rust/main/hyperlane-core/src/types/reorg.rs | 20 + 15 files changed, 461 insertions(+), 22 deletions(-) create mode 100644 rust/main/hyperlane-core/src/types/reorg.rs diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index f58a90d40..68f4a2732 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -10362,6 +10362,7 @@ version = "0.1.0" dependencies = [ "async-trait", "axum", + "chrono", "config", "console-subscriber", "derive-new", @@ -10376,6 +10377,7 @@ dependencies = [ "hyperlane-ethereum", "hyperlane-test", "k256 0.13.3", + "mockall", "prometheus", "reqwest", "serde", diff --git a/rust/main/Cargo.toml b/rust/main/Cargo.toml index 06619dcd4..aab9a72b9 100644 --- a/rust/main/Cargo.toml +++ b/rust/main/Cargo.toml @@ -40,6 +40,7 @@ borsh = "0.9" bs58 = "0.5.0" bytes = "1" clap = "4" +chrono = "*" color-eyre = "0.6" config = "0.13.3" console-subscriber = "0.2.0" diff --git a/rust/main/agents/relayer/Cargo.toml b/rust/main/agents/relayer/Cargo.toml index 3a7f5c6bb..5a891d912 100644 --- a/rust/main/agents/relayer/Cargo.toml +++ b/rust/main/agents/relayer/Cargo.toml @@ -58,6 +58,7 @@ mockall.workspace = true tokio-test.workspace = true hyperlane-test = { path = "../../hyperlane-test" } hyperlane-base = { path = "../../hyperlane-base", features = ["test-utils"] } +hyperlane-core = { path = "../../hyperlane-core", features = ["agent", "async", "test-utils"] } [features] default = ["color-eyre", "oneline-errors"] diff --git a/rust/main/agents/relayer/src/msg/processor.rs b/rust/main/agents/relayer/src/msg/processor.rs index a2f70f8c9..43bd93c67 100644 --- a/rust/main/agents/relayer/src/msg/processor.rs +++ b/rust/main/agents/relayer/src/msg/processor.rs @@ -404,8 +404,8 @@ mod test { settings::{ChainConf, ChainConnectionConf, Settings}, }; use hyperlane_core::{ - GasPaymentKey, InterchainGasPayment, InterchainGasPaymentMeta, MerkleTreeInsertion, - PendingOperationStatus, H256, + test_utils::dummy_domain, GasPaymentKey, InterchainGasPayment, InterchainGasPaymentMeta, + MerkleTreeInsertion, PendingOperationStatus, H256, }; use hyperlane_test::mocks::{MockMailboxContract, MockValidatorAnnounceContract}; use prometheus::{IntCounter, Registry}; @@ -537,17 +537,6 @@ mod test { } } - fn dummy_domain(domain_id: u32, name: &str) -> HyperlaneDomain { - let test_domain = HyperlaneDomain::new_test_domain(name); - HyperlaneDomain::Unknown { - domain_id, - domain_name: name.to_owned(), - domain_type: test_domain.domain_type(), - domain_protocol: test_domain.domain_protocol(), - domain_technical_stack: test_domain.domain_technical_stack(), - } - } - /// Only adds database entries to the pending message prefix if the message's /// retry count is greater than zero fn persist_retried_messages( diff --git a/rust/main/agents/validator/Cargo.toml b/rust/main/agents/validator/Cargo.toml index 7b3f1049c..7228ad69c 100644 --- a/rust/main/agents/validator/Cargo.toml +++ b/rust/main/agents/validator/Cargo.toml @@ -11,6 +11,7 @@ version.workspace = true [dependencies] async-trait.workspace = true axum.workspace = true +chrono.workspace = true config.workspace = true console-subscriber.workspace = true derive_more.workspace = true @@ -36,10 +37,12 @@ hyperlane-ethereum = { path = "../../chains/hyperlane-ethereum" } hyperlane-cosmos = { path = "../../chains/hyperlane-cosmos" } [dev-dependencies] +mockall.workspace = true tokio-test.workspace = true reqwest.workspace = true hyperlane-test = { path = "../../hyperlane-test" } k256.workspace = true +hyperlane-ethereum = { path = "../../chains/hyperlane-ethereum", features = ["test-utils"] } [features] default = ["color-eyre", "oneline-errors"] diff --git a/rust/main/agents/validator/src/submit.rs b/rust/main/agents/validator/src/submit.rs index 8b3ede08e..94d596467 100644 --- a/rust/main/agents/validator/src/submit.rs +++ b/rust/main/agents/validator/src/submit.rs @@ -3,18 +3,18 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use std::vec; -use hyperlane_base::db::HyperlaneDb; -use hyperlane_core::rpc_clients::call_and_retry_indefinitely; -use hyperlane_core::{ChainResult, MerkleTreeHook}; use prometheus::IntGauge; use tokio::time::sleep; use tracing::{debug, error, info}; +use hyperlane_base::db::HyperlaneDb; use hyperlane_base::{CheckpointSyncer, CoreMetrics}; +use hyperlane_core::rpc_clients::call_and_retry_indefinitely; use hyperlane_core::{ accumulator::incremental::IncrementalMerkle, Checkpoint, CheckpointWithMessageId, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSignerExt, }; +use hyperlane_core::{ChainResult, MerkleTreeHook, ReorgEvent}; use hyperlane_ethereum::SingletonSignerHandle; #[derive(Clone)] @@ -206,12 +206,32 @@ impl ValidatorSubmitter { // If the tree's checkpoint doesn't match the correctness checkpoint, something went wrong // and we bail loudly. if checkpoint != *correctness_checkpoint { + let reorg_event = ReorgEvent::new( + tree.root(), + correctness_checkpoint.root, + checkpoint.index, + chrono::Utc::now().timestamp() as u64, + self.reorg_period.map(|x| x.get()).unwrap_or(0), + ); error!( ?checkpoint, ?correctness_checkpoint, + ?reorg_event, "Incorrect tree root, something went wrong" ); - panic!("Incorrect tree root, something went wrong"); + + let mut panic_message = "Incorrect tree root, something went wrong.".to_owned(); + if let Err(e) = self + .checkpoint_syncer + .write_reorg_status(&reorg_event) + .await + { + panic_message.push_str(&format!( + " Reorg troubleshooting details couldn't be written to checkpoint storage: {}", + e + )); + } + panic!("{panic_message}"); } if !checkpoint_queue.is_empty() { @@ -313,3 +333,321 @@ impl ValidatorSubmitterMetrics { } } } + +#[cfg(test)] +mod test { + use super::*; + use async_trait::async_trait; + use eyre::Result; + use hyperlane_base::{ + db::{DbResult, HyperlaneDb, InterchainGasExpenditureData, InterchainGasPaymentData}, + AgentMetadata, + }; + use hyperlane_core::{ + test_utils::dummy_domain, GasPaymentKey, HyperlaneChain, HyperlaneContract, + HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, InterchainGasPayment, + InterchainGasPaymentMeta, MerkleTreeHook, MerkleTreeInsertion, PendingOperationStatus, + ReorgEvent, SignedAnnouncement, SignedCheckpointWithMessageId, H160, H256, + }; + use prometheus::Registry; + use std::{fmt::Debug, sync::Arc, time::Duration}; + use tokio::sync::mpsc; + + mockall::mock! { + pub Db { + fn provider(&self) -> Box; + } + + impl Debug for Db { + fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result; + } + + impl HyperlaneDb for Db { + fn retrieve_highest_seen_message_nonce(&self) -> DbResult>; + fn retrieve_message_by_nonce(&self, nonce: u32) -> DbResult>; + fn retrieve_processed_by_nonce(&self, nonce: &u32) -> DbResult>; + fn domain(&self) -> &HyperlaneDomain; + fn store_message_id_by_nonce(&self, nonce: &u32, id: &H256) -> DbResult<()>; + fn retrieve_message_id_by_nonce(&self, nonce: &u32) -> DbResult>; + fn store_message_by_id(&self, id: &H256, message: &HyperlaneMessage) -> DbResult<()>; + fn retrieve_message_by_id(&self, id: &H256) -> DbResult>; + fn store_dispatched_block_number_by_nonce( + &self, + nonce: &u32, + block_number: &u64, + ) -> DbResult<()>; + fn retrieve_dispatched_block_number_by_nonce(&self, nonce: &u32) -> DbResult>; + fn store_processed_by_nonce(&self, nonce: &u32, processed: &bool) -> DbResult<()>; + fn store_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + processed: &bool, + ) -> DbResult<()>; + fn retrieve_processed_by_gas_payment_meta( + &self, + meta: &InterchainGasPaymentMeta, + ) -> DbResult>; + fn store_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + data: &InterchainGasExpenditureData, + ) -> DbResult<()>; + fn retrieve_interchain_gas_expenditure_data_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + fn store_status_by_message_id( + &self, + message_id: &H256, + status: &PendingOperationStatus, + ) -> DbResult<()>; + fn retrieve_status_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + fn store_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + data: &InterchainGasPaymentData, + ) -> DbResult<()>; + fn retrieve_interchain_gas_payment_data_by_gas_payment_key( + &self, + key: &GasPaymentKey, + ) -> DbResult>; + fn store_gas_payment_by_sequence( + &self, + sequence: &u32, + payment: &InterchainGasPayment, + ) -> DbResult<()>; + fn retrieve_gas_payment_by_sequence( + &self, + sequence: &u32, + ) -> DbResult>; + fn store_gas_payment_block_by_sequence( + &self, + sequence: &u32, + block_number: &u64, + ) -> DbResult<()>; + fn retrieve_gas_payment_block_by_sequence(&self, sequence: &u32) -> DbResult>; + fn store_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + count: &u32, + ) -> DbResult<()>; + fn retrieve_pending_message_retry_count_by_message_id( + &self, + message_id: &H256, + ) -> DbResult>; + fn store_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + insertion: &MerkleTreeInsertion, + ) -> DbResult<()>; + fn retrieve_merkle_tree_insertion_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult>; + fn store_merkle_leaf_index_by_message_id( + &self, + message_id: &H256, + leaf_index: &u32, + ) -> DbResult<()>; + fn retrieve_merkle_leaf_index_by_message_id(&self, message_id: &H256) -> DbResult>; + fn store_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + block_number: &u64, + ) -> DbResult<()>; + fn retrieve_merkle_tree_insertion_block_number_by_leaf_index( + &self, + leaf_index: &u32, + ) -> DbResult>; + fn store_highest_seen_message_nonce_number(&self, nonce: &u32) -> DbResult<()>; + fn retrieve_highest_seen_message_nonce_number(&self) -> DbResult>; + + } + } + + mockall::mock! { + pub MerkleTreeHook {} + + impl Debug for MerkleTreeHook { + fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result; + } + + impl HyperlaneChain for MerkleTreeHook { + fn domain(&self) -> &HyperlaneDomain; + fn provider(&self) -> Box; + } + + impl HyperlaneContract for MerkleTreeHook { + fn address(&self) -> H256; + } + + #[async_trait] + impl MerkleTreeHook for MerkleTreeHook { + async fn tree(&self, lag: Option) -> ChainResult; + async fn count(&self, lag: Option) -> ChainResult; + async fn latest_checkpoint(&self, lag: Option) -> ChainResult; + } + } + + mockall::mock! { + pub CheckpointSyncer {} + + impl Debug for CheckpointSyncer { + fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result; + } + + #[async_trait] + impl CheckpointSyncer for CheckpointSyncer { + async fn latest_index(&self) -> Result>; + async fn write_latest_index(&self, index: u32) -> Result<()>; + async fn update_latest_index(&self, index: u32) -> Result<()>; + async fn fetch_checkpoint(&self, index: u32) -> Result>; + async fn write_checkpoint( + &self, + signed_checkpoint: &SignedCheckpointWithMessageId, + ) -> Result<()>; + async fn write_metadata(&self, metadata: &AgentMetadata) -> Result<()>; + async fn write_announcement(&self, signed_announcement: &SignedAnnouncement) -> Result<()>; + fn announcement_location(&self) -> String; + async fn write_reorg_status(&self, reorg_event: &ReorgEvent) -> Result<()>; + async fn reorg_status(&self) -> Result>; + } + } + + fn dummy_metrics() -> ValidatorSubmitterMetrics { + let origin_domain = dummy_domain(0, "dummy_origin_domain"); + let core_metrics = CoreMetrics::new("dummy_relayer", 37582, Registry::new()).unwrap(); + ValidatorSubmitterMetrics::new(&core_metrics, &origin_domain) + } + + fn dummy_singleton_handle() -> SingletonSignerHandle { + SingletonSignerHandle::new(H160::from_low_u64_be(0), mpsc::unbounded_channel().0) + } + + fn reorg_event_is_correct( + reorg_event: &ReorgEvent, + expected_local_merkle_tree: &IncrementalMerkle, + mock_onchain_merkle_tree: &IncrementalMerkle, + unix_timestamp: u64, + expected_reorg_period: u64, + ) { + assert_eq!( + reorg_event.canonical_merkle_root, + mock_onchain_merkle_tree.root() + ); + assert_eq!( + reorg_event.local_merkle_root, + expected_local_merkle_tree.root() + ); + assert_eq!( + reorg_event.checkpoint_index, + expected_local_merkle_tree.index() + ); + // timestamp diff should be less than 1 second + let timestamp_diff = reorg_event.unix_timestamp as i64 - unix_timestamp as i64; + assert!(timestamp_diff.abs() < 1); + + assert_eq!(reorg_event.reorg_period, expected_reorg_period); + } + + #[tokio::test] + #[should_panic(expected = "Incorrect tree root, something went wrong.")] + async fn reorg_is_detected_and_persisted_to_checkpoint_storage() { + let unix_timestamp = chrono::Utc::now().timestamp() as u64; + let expected_reorg_period = 12; + + let pre_reorg_merke_insertions = vec![ + MerkleTreeInsertion::new(0, H256::random()), + MerkleTreeInsertion::new(1, H256::random()), + MerkleTreeInsertion::new(2, H256::random()), + ]; + let mut expected_local_merkle_tree = IncrementalMerkle::default(); + for insertion in pre_reorg_merke_insertions.iter() { + expected_local_merkle_tree.ingest(insertion.message_id()); + } + + // the last leaf is different post-reorg + let post_reorg_merkle_insertions = vec![ + pre_reorg_merke_insertions[0].clone(), + pre_reorg_merke_insertions[1].clone(), + MerkleTreeInsertion::new(2, H256::random()), + ]; + let mut mock_onchain_merkle_tree = IncrementalMerkle::default(); + for insertion in post_reorg_merkle_insertions.iter() { + mock_onchain_merkle_tree.ingest(insertion.message_id()); + } + + // assert the reorg resulted in different merkle tree roots + assert_ne!( + mock_onchain_merkle_tree.root(), + expected_local_merkle_tree.root() + ); + + // the db returns the pre-reorg merkle tree insertions + let mut db = MockDb::new(); + db.expect_retrieve_merkle_tree_insertion_by_leaf_index() + .returning(move |sequence| { + Ok(Some(pre_reorg_merke_insertions[*sequence as usize].clone())) + }); + + // boilerplate mocks + let mut mock_merkle_tree_hook = MockMerkleTreeHook::new(); + mock_merkle_tree_hook + .expect_address() + .returning(|| H256::from_low_u64_be(0)); + let dummy_domain = dummy_domain(0, "dummy_domain"); + mock_merkle_tree_hook + .expect_domain() + .return_const(dummy_domain.clone()); + + // expect the checkpoint syncer to post the reorg event to the checkpoint storage + // and not submit any checkpoints (this is checked implicitly, by not setting any `expect`s) + let mut mock_checkpoint_syncer = MockCheckpointSyncer::new(); + let mock_onchain_merkle_tree_clone = mock_onchain_merkle_tree.clone(); + mock_checkpoint_syncer + .expect_write_reorg_status() + .once() + .returning(move |reorg_event| { + // unit test correctness criteria + reorg_event_is_correct( + reorg_event, + &expected_local_merkle_tree, + &mock_onchain_merkle_tree_clone, + unix_timestamp, + expected_reorg_period, + ); + Ok(()) + }); + + // instantiate the validator submitter + let validator_submitter = ValidatorSubmitter::new( + Duration::from_secs(1), + expected_reorg_period, + Arc::new(mock_merkle_tree_hook), + dummy_singleton_handle(), + Arc::new(mock_checkpoint_syncer), + Arc::new(db), + dummy_metrics(), + ); + + // mock the correctness checkpoint response + let mock_onchain_checkpoint = Checkpoint { + root: mock_onchain_merkle_tree.root(), + index: mock_onchain_merkle_tree.index(), + merkle_tree_hook_address: H256::from_low_u64_be(0), + mailbox_domain: dummy_domain.id(), + }; + + // Start the submitter with an empty merkle tree, so it gets rebuilt from the db. + // A panic is expected here, as the merkle root inconsistency is a critical error that may indicate fraud. + validator_submitter + .submit_checkpoints_until_correctness_checkpoint( + &mut IncrementalMerkle::default(), + &mock_onchain_checkpoint, + ) + .await; + } +} diff --git a/rust/main/chains/hyperlane-ethereum/Cargo.toml b/rust/main/chains/hyperlane-ethereum/Cargo.toml index c096965c9..07e624e1e 100644 --- a/rust/main/chains/hyperlane-ethereum/Cargo.toml +++ b/rust/main/chains/hyperlane-ethereum/Cargo.toml @@ -36,3 +36,7 @@ ethers-prometheus = { path = "../../ethers-prometheus", features = ["serde"] } [build-dependencies] abigen = { path = "../../utils/abigen", features = ["ethers"] } hyperlane-core = { path = "../../hyperlane-core", features = ["test-utils"] } + +[features] +default = [] +test-utils = [] \ No newline at end of file diff --git a/rust/main/chains/hyperlane-ethereum/src/signer/singleton.rs b/rust/main/chains/hyperlane-ethereum/src/signer/singleton.rs index 790c8e73a..7925d1ec9 100644 --- a/rust/main/chains/hyperlane-ethereum/src/signer/singleton.rs +++ b/rust/main/chains/hyperlane-ethereum/src/signer/singleton.rs @@ -38,6 +38,14 @@ pub struct SingletonSignerHandle { tx: mpsc::UnboundedSender, } +#[cfg(feature = "test-utils")] +impl SingletonSignerHandle { + /// Create a new handle for testing purposes + pub fn new(address: H160, tx: mpsc::UnboundedSender) -> Self { + Self { address, tx } + } +} + impl fmt::Debug for SingletonSignerHandle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("SingletonSignerHandle") diff --git a/rust/main/hyperlane-base/src/traits/checkpoint_syncer.rs b/rust/main/hyperlane-base/src/traits/checkpoint_syncer.rs index 44828bcbe..0dc6a1e6b 100644 --- a/rust/main/hyperlane-base/src/traits/checkpoint_syncer.rs +++ b/rust/main/hyperlane-base/src/traits/checkpoint_syncer.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use eyre::Result; use crate::AgentMetadata; -use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId}; +use hyperlane_core::{ReorgEvent, SignedAnnouncement, SignedCheckpointWithMessageId}; /// A generic trait to read/write Checkpoints offchain #[async_trait] @@ -34,4 +34,10 @@ pub trait CheckpointSyncer: Debug + Send + Sync { async fn write_announcement(&self, signed_announcement: &SignedAnnouncement) -> Result<()>; /// Return the announcement storage location for this syncer fn announcement_location(&self) -> String; + /// If a bigger than expected reorg was detected on the validated chain, this flag can be set to inform + /// the validator agent to stop publishing checkpoints. Once any remediation is done, this flag can be reset + /// to resume operation. + async fn write_reorg_status(&self, reorg_event: &ReorgEvent) -> Result<()>; + /// Read the reorg status of the chain being validated + async fn reorg_status(&self) -> Result>; } diff --git a/rust/main/hyperlane-base/src/types/gcs_storage.rs b/rust/main/hyperlane-base/src/types/gcs_storage.rs index e54f65349..ba40ec2ca 100644 --- a/rust/main/hyperlane-base/src/types/gcs_storage.rs +++ b/rust/main/hyperlane-base/src/types/gcs_storage.rs @@ -2,7 +2,7 @@ use crate::{AgentMetadata, CheckpointSyncer}; use async_trait::async_trait; use derive_new::new; use eyre::{bail, Result}; -use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId}; +use hyperlane_core::{ReorgEvent, SignedAnnouncement, SignedCheckpointWithMessageId}; use std::fmt; use ya_gcp::{ storage::{ @@ -15,6 +15,7 @@ use ya_gcp::{ const LATEST_INDEX_KEY: &str = "gcsLatestIndexKey"; const METADATA_KEY: &str = "gcsMetadataKey"; const ANNOUNCEMENT_KEY: &str = "gcsAnnouncementKey"; +const REORG_FLAG_KEY: &str = "gcsReorgFlagKey"; /// Path to GCS users_secret file pub const GCS_USER_SECRET: &str = "GCS_USER_SECRET"; /// Path to GCS Service account key @@ -217,6 +218,18 @@ impl CheckpointSyncer for GcsStorageClient { fn announcement_location(&self) -> String { format!("gs://{}/{}", &self.bucket, ANNOUNCEMENT_KEY) } + + async fn write_reorg_status(&self, reorged_event: &ReorgEvent) -> Result<()> { + let serialized_metadata = serde_json::to_string_pretty(reorged_event)?; + self.inner + .insert_object(&self.bucket, REORG_FLAG_KEY, serialized_metadata) + .await?; + Ok(()) + } + + async fn reorg_status(&self) -> Result> { + Ok(None) + } } #[tokio::test] diff --git a/rust/main/hyperlane-base/src/types/local_storage.rs b/rust/main/hyperlane-base/src/types/local_storage.rs index 71047f246..bb1ebf123 100644 --- a/rust/main/hyperlane-base/src/types/local_storage.rs +++ b/rust/main/hyperlane-base/src/types/local_storage.rs @@ -4,7 +4,7 @@ use crate::traits::CheckpointSyncer; use crate::AgentMetadata; use async_trait::async_trait; use eyre::{Context, Result}; -use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId}; +use hyperlane_core::{ReorgEvent, SignedAnnouncement, SignedCheckpointWithMessageId}; use prometheus::IntGauge; #[derive(Debug, Clone)] @@ -41,6 +41,10 @@ impl LocalStorage { self.path.join("announcement.json") } + fn reorg_flag_path(&self) -> PathBuf { + self.path.join("reorg_flag.json") + } + fn metadata_file_path(&self) -> PathBuf { self.path.join("metadata_latest.json") } @@ -116,4 +120,21 @@ impl CheckpointSyncer for LocalStorage { fn announcement_location(&self) -> String { format!("file://{}", self.path.to_str().unwrap()) } + + async fn write_reorg_status(&self, reorged_event: &ReorgEvent) -> Result<()> { + let serialized_reorg = serde_json::to_string_pretty(reorged_event)?; + let path = self.reorg_flag_path(); + tokio::fs::write(&path, &serialized_reorg) + .await + .with_context(|| format!("Writing reorg status to {path:?}"))?; + Ok(()) + } + + async fn reorg_status(&self) -> Result> { + let Ok(data) = tokio::fs::read(self.reorg_flag_path()).await else { + return Ok(None); + }; + let reorg = serde_json::from_slice(&data)?; + Ok(Some(reorg)) + } } diff --git a/rust/main/hyperlane-base/src/types/s3_storage.rs b/rust/main/hyperlane-base/src/types/s3_storage.rs index 4d03ff040..ea04a1c4f 100644 --- a/rust/main/hyperlane-base/src/types/s3_storage.rs +++ b/rust/main/hyperlane-base/src/types/s3_storage.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use derive_new::new; use eyre::{bail, Result}; use futures_util::TryStreamExt; -use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId}; +use hyperlane_core::{ReorgEvent, SignedAnnouncement, SignedCheckpointWithMessageId}; use prometheus::IntGauge; use rusoto_core::{ credential::{Anonymous, AwsCredentials, StaticProvider}, @@ -145,6 +145,10 @@ impl S3Storage { fn announcement_key() -> String { "announcement.json".to_owned() } + + fn reorg_flag_key() -> String { + "reorg_flag.json".to_owned() + } } #[async_trait] @@ -216,4 +220,19 @@ impl CheckpointSyncer for S3Storage { } } } + + async fn write_reorg_status(&self, reorged_event: &ReorgEvent) -> Result<()> { + let serialized_reorg = serde_json::to_string(reorged_event)?; + self.write_to_bucket(S3Storage::reorg_flag_key(), &serialized_reorg) + .await?; + Ok(()) + } + + async fn reorg_status(&self) -> Result> { + self.anonymously_read_from_bucket(S3Storage::reorg_flag_key()) + .await? + .map(|data| serde_json::from_slice(&data)) + .transpose() + .map_err(Into::into) + } } diff --git a/rust/main/hyperlane-core/src/test_utils.rs b/rust/main/hyperlane-core/src/test_utils.rs index c24d70419..242570680 100644 --- a/rust/main/hyperlane-core/src/test_utils.rs +++ b/rust/main/hyperlane-core/src/test_utils.rs @@ -3,7 +3,7 @@ use std::io::Read; use std::path::PathBuf; use crate::accumulator::merkle::Proof; -use crate::H256; +use crate::{HyperlaneDomain, H256}; /// Struct representing a single merkle test case #[derive(serde::Deserialize, serde::Serialize)] @@ -38,3 +38,15 @@ pub fn find_vector(final_component: &str) -> PathBuf { git_dir.join("vectors").join(final_component) } + +/// Create a dummy domain for testing purposes +pub fn dummy_domain(domain_id: u32, name: &str) -> HyperlaneDomain { + let test_domain = HyperlaneDomain::new_test_domain(name); + HyperlaneDomain::Unknown { + domain_id, + domain_name: name.to_owned(), + domain_type: test_domain.domain_type(), + domain_protocol: test_domain.domain_protocol(), + domain_technical_stack: test_domain.domain_technical_stack(), + } +} diff --git a/rust/main/hyperlane-core/src/types/mod.rs b/rust/main/hyperlane-core/src/types/mod.rs index 8987d9a86..f9d78b05a 100644 --- a/rust/main/hyperlane-core/src/types/mod.rs +++ b/rust/main/hyperlane-core/src/types/mod.rs @@ -13,6 +13,7 @@ pub use indexing::*; pub use log_metadata::*; pub use merkle_tree::*; pub use message::*; +pub use reorg::*; pub use transaction::*; use crate::{Decode, Encode, HyperlaneProtocolError}; @@ -24,6 +25,7 @@ mod indexing; mod log_metadata; mod merkle_tree; mod message; +mod reorg; mod serialize; mod transaction; diff --git a/rust/main/hyperlane-core/src/types/reorg.rs b/rust/main/hyperlane-core/src/types/reorg.rs new file mode 100644 index 000000000..00a8dedc1 --- /dev/null +++ b/rust/main/hyperlane-core/src/types/reorg.rs @@ -0,0 +1,20 @@ +use derive_new::new; +use serde::{Deserialize, Serialize}; + +use crate::H256; + +/// Details about a detected chain reorg, from an agent's perspective +#[derive(Debug, Clone, Serialize, Deserialize, new)] +pub struct ReorgEvent { + /// the merkle root built from this agent's indexed events + pub local_merkle_root: H256, + /// the onchain merkle root + pub canonical_merkle_root: H256, + /// the index of the checkpoint when the reorg was detected + /// (due to a mismatch between local and canonical merkle roots) + pub checkpoint_index: u32, + /// the timestamp when the reorg was detected, in seconds since the Unix epoch + pub unix_timestamp: u64, + /// the reorg period configured for the agent, in blocks + pub reorg_period: u64, +} From 7dccf80b57faf49b0a7031f5b3516cb962bb7a80 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:56:33 +0100 Subject: [PATCH 105/224] feat: do not start up validator if fraud was reported (#4627) ### Description Builds on top of https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4587 Adds a check in the `CheckpointSubmitter` builder which emits a panic if a reorg flag was posted, since this potentially signals fraud ### Drive-by changes `CheckpointSubmitter::build` was made private, so any use of it is now replaced by the `build_and_submit` flow ### Related issues ### Backward compatibility Yes ### Testing Unit Tests - which is enough as long as `CheckpointSubmitter::build` is kept private --- .../agents/relayer/src/msg/metadata/base.rs | 2 +- rust/main/agents/validator/src/validator.rs | 6 +- .../src/settings/checkpoint_syncer.rs | 107 +++++++++++++++++- 3 files changed, 112 insertions(+), 3 deletions(-) diff --git a/rust/main/agents/relayer/src/msg/metadata/base.rs b/rust/main/agents/relayer/src/msg/metadata/base.rs index e847e39c6..be10af611 100644 --- a/rust/main/agents/relayer/src/msg/metadata/base.rs +++ b/rust/main/agents/relayer/src/msg/metadata/base.rs @@ -400,7 +400,7 @@ impl BaseMetadataBuilder { continue; } - match config.build(None).await { + match config.build_and_validate(None).await { Ok(checkpoint_syncer) => { // found the syncer for this validator checkpoint_syncers.insert(validator.into(), checkpoint_syncer.into()); diff --git a/rust/main/agents/validator/src/validator.rs b/rust/main/agents/validator/src/validator.rs index 3f1f05c3a..31fe809b4 100644 --- a/rust/main/agents/validator/src/validator.rs +++ b/rust/main/agents/validator/src/validator.rs @@ -77,7 +77,11 @@ impl BaseAgent for Validator { let (signer_instance, signer) = SingletonSigner::new(settings.validator.build().await?); let core = settings.build_hyperlane_core(metrics.clone()); - let checkpoint_syncer = settings.checkpoint_syncer.build(None).await?.into(); + let checkpoint_syncer = settings + .checkpoint_syncer + .build_and_validate(None) + .await? + .into(); let mailbox = settings .build_mailbox(&settings.origin_chain, &metrics) diff --git a/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs b/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs index 81cf74985..38274dafa 100644 --- a/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs +++ b/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs @@ -7,6 +7,7 @@ use eyre::{eyre, Context, Report, Result}; use prometheus::IntGauge; use rusoto_core::Region; use std::{env, path::PathBuf}; +use tracing::error; use ya_gcp::{AuthFlow, ServiceAccountAuth}; /// Checkpoint Syncer types @@ -101,7 +102,37 @@ impl FromStr for CheckpointSyncerConf { impl CheckpointSyncerConf { /// Turn conf info a Checkpoint Syncer - pub async fn build( + /// + /// # Panics + /// + /// Panics if a reorg event has been posted to the checkpoint store, + /// to prevent any operation processing until the reorg is resolved. + pub async fn build_and_validate( + &self, + latest_index_gauge: Option, + ) -> Result, Report> { + let syncer: Box = self.build(latest_index_gauge).await?; + + match syncer.reorg_status().await { + Ok(Some(reorg_event)) => { + panic!( + "A reorg event has been detected: {:#?}. Please resolve the reorg to continue.", + reorg_event + ); + } + Err(err) => { + error!( + ?err, + "Failed to read reorg status. Assuming no reorg occurred." + ); + } + _ => {} + } + Ok(syncer) + } + + // keep this private to force all initializations to perform the reorg check via `build_and_validate` + async fn build( &self, latest_index_gauge: Option, ) -> Result, Report> { @@ -143,3 +174,77 @@ impl CheckpointSyncerConf { }) } } + +#[cfg(test)] +mod test { + use std::panic::AssertUnwindSafe; + + use futures_util::FutureExt; + use hyperlane_core::{ReorgEvent, H256}; + + #[tokio::test] + async fn test_build_and_validate() { + use super::*; + + // initialize a local checkpoint store + let temp_checkpoint_dir = tempfile::tempdir().unwrap(); + let checkpoint_path = format!("file://{}", temp_checkpoint_dir.path().to_str().unwrap()); + let checkpoint_syncer_conf = CheckpointSyncerConf::from_str(&checkpoint_path).unwrap(); + + // create a checkpoint syncer and write a reorg event + // then `drop` it, to simulate a restart + { + let checkpoint_syncer = checkpoint_syncer_conf + .build_and_validate(None) + .await + .unwrap(); + + let dummy_local_merkle_root = H256::from_str( + "0x8da44bc8198e9874db215ec2000037c58e16918c94743d70c838ecb10e243c64", + ) + .unwrap(); + let dummy_canonical_merkle_root = H256::from_str( + "0xb437b888332ef12f7260c7f679aad3c96b91ab81c2dc7242f8b290f0b6bba92b", + ) + .unwrap(); + let dummy_checkpoint_index = 56; + let unix_timestamp = 1620000000; + let reorg_period = 5; + let dummy_reorg_event = ReorgEvent { + local_merkle_root: dummy_local_merkle_root, + canonical_merkle_root: dummy_canonical_merkle_root, + checkpoint_index: dummy_checkpoint_index, + unix_timestamp, + reorg_period, + }; + checkpoint_syncer + .write_reorg_status(&dummy_reorg_event) + .await + .unwrap(); + } + + // Initialize a new checkpoint syncer and expect it to panic due to the reorg event. + // `AssertUnwindSafe` is required for ignoring some type checks so the panic can be caught. + let startup_result = AssertUnwindSafe(checkpoint_syncer_conf.build_and_validate(None)) + .catch_unwind() + .await + .unwrap_err(); + if let Some(err) = startup_result.downcast_ref::() { + assert_eq!( + *err, + r#"A reorg event has been detected: ReorgEvent { + local_merkle_root: 0x8da44bc8198e9874db215ec2000037c58e16918c94743d70c838ecb10e243c64, + canonical_merkle_root: 0xb437b888332ef12f7260c7f679aad3c96b91ab81c2dc7242f8b290f0b6bba92b, + checkpoint_index: 56, + unix_timestamp: 1620000000, + reorg_period: 5, +}. Please resolve the reorg to continue."# + ); + } else { + panic!( + "Caught panic has a different type than the expected one (`String`): {:?}", + startup_result + ); + } + } +} From bb75eba74a2fabf0ff3e54f8c0a89fcde9959ab8 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 7 Oct 2024 16:32:35 -0400 Subject: [PATCH 106/224] fix: recipient rate limited ISM (#4636) ### Description Add recipient restriction to rate limited ISM. This prevents multiple recipients from sharing the same rate limit ISM and denial of service attacks. ### Backward compatibility No ### Testing Unit Tests --- .changeset/breezy-toys-pay.md | 5 ++++ .../isms/warp-route/RateLimitedIsm.sol | 23 +++++++++++++++---- solidity/test/isms/RateLimitedIsm.t.sol | 23 ++++++++++++++++--- 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 .changeset/breezy-toys-pay.md diff --git a/.changeset/breezy-toys-pay.md b/.changeset/breezy-toys-pay.md new file mode 100644 index 000000000..e0cb028f4 --- /dev/null +++ b/.changeset/breezy-toys-pay.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': minor +--- + +fix: constrain rate limited ISM to a single message recipient diff --git a/solidity/contracts/isms/warp-route/RateLimitedIsm.sol b/solidity/contracts/isms/warp-route/RateLimitedIsm.sol index 221b6a5b3..0811cae4a 100644 --- a/solidity/contracts/isms/warp-route/RateLimitedIsm.sol +++ b/solidity/contracts/isms/warp-route/RateLimitedIsm.sol @@ -16,6 +16,8 @@ contract RateLimitedIsm is using Message for bytes; using TokenMessage for bytes; + address public immutable recipient; + mapping(bytes32 messageId => bool validated) public messageValidated; modifier validateMessageOnce(bytes calldata _message) { @@ -25,14 +27,22 @@ contract RateLimitedIsm is _; } + modifier onlyRecipient(bytes calldata _message) { + require(_message.recipientAddress() == recipient, "InvalidRecipient"); + _; + } + constructor( address _mailbox, - uint256 _maxCapacity - ) MailboxClient(_mailbox) RateLimited(_maxCapacity) {} + uint256 _maxCapacity, + address _recipient + ) MailboxClient(_mailbox) RateLimited(_maxCapacity) { + recipient = _recipient; + } /// @inheritdoc IInterchainSecurityModule function moduleType() external pure returns (uint8) { - return uint8(IInterchainSecurityModule.Types.UNUSED); + return uint8(IInterchainSecurityModule.Types.NULL); } /** @@ -42,7 +52,12 @@ contract RateLimitedIsm is function verify( bytes calldata, bytes calldata _message - ) external validateMessageOnce(_message) returns (bool) { + ) + external + onlyRecipient(_message) + validateMessageOnce(_message) + returns (bool) + { require(_isDelivered(_message.id()), "InvalidDeliveredMessage"); uint256 newAmount = _message.body().amount(); diff --git a/solidity/test/isms/RateLimitedIsm.t.sol b/solidity/test/isms/RateLimitedIsm.t.sol index a514d75c9..7c4b76356 100644 --- a/solidity/test/isms/RateLimitedIsm.t.sol +++ b/solidity/test/isms/RateLimitedIsm.t.sol @@ -25,18 +25,20 @@ contract RateLimitedIsmTest is Test { function setUp() external { localMailbox = new TestMailbox(ORIGIN); + testRecipient = new TestRecipient(); rateLimitedIsm = new RateLimitedIsm( address(localMailbox), - MAX_CAPACITY + MAX_CAPACITY, + address(testRecipient) ); - testRecipient = new TestRecipient(); testRecipient.setInterchainSecurityModule(address(rateLimitedIsm)); } function testRateLimitedIsm_revertsIDeliveredFalse( - bytes calldata _message + uint256 _amount ) external { + bytes memory _message = _encodeTestMessage(_amount); vm.prank(address(localMailbox)); vm.expectRevert("InvalidDeliveredMessage"); rateLimitedIsm.verify(bytes(""), _message); @@ -62,6 +64,21 @@ contract RateLimitedIsmTest is Test { rateLimitedIsm.verify(bytes(""), encodedMessage); } + function test_verifyOnlyRecipient(uint128 _amount) external { + bytes memory _message = MessageUtils.formatMessage( + uint8(3), + uint32(1), + ORIGIN, + WARP_ROUTE_ADDR.addressToBytes32(), + ORIGIN, + ~address(testRecipient).addressToBytes32(), // bad recipient + TokenMessage.format(bytes32(""), _amount, bytes("")) + ); + + vm.expectRevert("InvalidRecipient"); + rateLimitedIsm.verify(bytes(""), _message); + } + function _encodeTestMessage( uint256 _amount ) internal view returns (bytes memory) { From 4415ac224a559af2d2b8a00154adbdd25c79bc38 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:53:28 -0400 Subject: [PATCH 107/224] feat: add Safe Transaction Builder to Warp Apply (#4621) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Adds feature to create a Safe Transaction Builder "receipt" that can be uploaded to the Safe UI. This relies on a a gnosisSafeTxBuilder strategy: ``` basesepolia: submitter: chain: 'basesepolia' type: gnosisSafeTxBuilder version: '1.0' meta: {} safeAddress: '0x7232Ad76d905ae9D8D00379359DDa744a7A21C46' ``` To generate this, to be uploaded to the UI: ``` { "version": "1.0", "chainId": "10200", "meta": {}, "transactions": [ { "to": "0xB86F6AF56C411688b3dAB479f646E990287094a0", "value": "0", "data": "0xe9198bf9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000014a3400000000000000000000000000000000000000000000000000000000002fd16700000000000000000000000000000000000000000000000000000000002fd1cb000000000000000000000000000000000000000000000000000000000000000300000000000000000000000021d4928020f503658603a036dd3ad5570e8495ab000000000000000000000000de612cfd22a35aae677398decd7a13057d6d5a300000000000000000000000008c08821f5f94b519c853486eb131667aa528a460", "operation": 0, "baseGas": "0", "gasPrice": "0", "gasToken": "0x0000000000000000000000000000000000000000", "refundReceiver": "0x0000000000000000000000000000000000000000", "nonce": 9, "safeTxGas": "0" } ] } ``` Screenshot 2024-10-03 at 1 08 31 PM ### Drive-by changes - Refactor warp apply to use `submitWarpApplyTransactions()` to submit and write the receipt file, de-duplicating code. ### Related issues - Fixes #4620 ### Backward compatibility Yes ### Testing Manual - [ ] Enrollment on 1 chain basesepolia - [ ] adding 2 anvil chains - [ ] Enrollment to 2 chains: basesepolia chiado - [ ] Adding 2 anvil chains --- .changeset/loud-glasses-beg.md | 7 + .../gnosis-chain-tx-builder-strategy.yaml | 6 + typescript/cli/src/commands/warp.ts | 23 +++- typescript/cli/src/deploy/warp.ts | 127 ++++++++++-------- typescript/cli/src/submit/submit.ts | 5 + typescript/cli/src/utils/files.ts | 7 + typescript/sdk/src/consts/concurrency.ts | 2 +- typescript/sdk/src/index.ts | 1 + typescript/sdk/src/providers/ProviderType.ts | 22 +++ .../sdk/src/providers/providerBuilders.ts | 2 + .../submitter/TxSubmitterInterface.ts | 6 +- .../submitter/TxSubmitterTypes.ts | 1 + .../submitter/builder/TxSubmitterBuilder.ts | 6 +- .../ethersV5/EV5GnosisSafeTxBuilder.ts | 72 ++++++++++ .../ethersV5/EV5GnosisSafeTxSubmitter.ts | 51 ++++--- .../submitter/ethersV5/schemas.ts | 6 + .../transactions/submitter/ethersV5/types.ts | 4 + .../transactions/submitter/schemas.ts | 5 + typescript/sdk/src/token/TokenStandard.ts | 1 + typescript/utils/src/types.ts | 1 + 20 files changed, 276 insertions(+), 79 deletions(-) create mode 100644 .changeset/loud-glasses-beg.md create mode 100644 typescript/cli/examples/submit/strategy/gnosis-chain-tx-builder-strategy.yaml create mode 100644 typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts diff --git a/.changeset/loud-glasses-beg.md b/.changeset/loud-glasses-beg.md new file mode 100644 index 000000000..5e7708fcd --- /dev/null +++ b/.changeset/loud-glasses-beg.md @@ -0,0 +1,7 @@ +--- +'@hyperlane-xyz/utils': minor +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Add Gnosis safe transaction builder to warp apply diff --git a/typescript/cli/examples/submit/strategy/gnosis-chain-tx-builder-strategy.yaml b/typescript/cli/examples/submit/strategy/gnosis-chain-tx-builder-strategy.yaml new file mode 100644 index 000000000..e681027e8 --- /dev/null +++ b/typescript/cli/examples/submit/strategy/gnosis-chain-tx-builder-strategy.yaml @@ -0,0 +1,6 @@ +basesepolia: + submitter: + chain: 'basesepolia' + type: gnosisSafeTxBuilder + version: '1.0' + safeAddress: '0x7232Ad76d905ae9D8D00379359DDa744a7A21C46' diff --git a/typescript/cli/src/commands/warp.ts b/typescript/cli/src/commands/warp.ts index da15e62a2..d3bee1e00 100644 --- a/typescript/cli/src/commands/warp.ts +++ b/typescript/cli/src/commands/warp.ts @@ -28,7 +28,11 @@ import { evaluateIfDryRunFailure } from '../deploy/dry-run.js'; import { runWarpRouteApply, runWarpRouteDeploy } from '../deploy/warp.js'; import { log, logGray, logGreen, logRed, logTable } from '../logger.js'; import { sendTestTransfer } from '../send/transfer.js'; -import { indentYamlOrJson, writeYamlOrJson } from '../utils/files.js'; +import { + indentYamlOrJson, + removeEndingSlash, + writeYamlOrJson, +} from '../utils/files.js'; import { selectRegistryWarpRoute } from '../utils/tokens.js'; import { @@ -68,6 +72,7 @@ export const apply: CommandModuleWithWriteContext<{ symbol?: string; warp: string; strategy?: string; + receiptsDir: string; }> = { command: 'apply', describe: 'Update Warp Route contracts', @@ -82,8 +87,21 @@ export const apply: CommandModuleWithWriteContext<{ demandOption: false, }, strategy: { ...strategyCommandOption, demandOption: false }, + 'receipts-dir': { + type: 'string', + description: 'The directory to output transaction receipts.', + default: './generated/transactions', + coerce: (dir) => removeEndingSlash(dir), + }, }, - handler: async ({ context, config, symbol, warp, strategy: strategyUrl }) => { + handler: async ({ + context, + config, + symbol, + warp, + strategy: strategyUrl, + receiptsDir, + }) => { logGray(`Hyperlane Warp Apply`); logGray('--------------------'); // @TODO consider creating a helper function for these dashes let warpCoreConfig: WarpCoreConfig; @@ -102,6 +120,7 @@ export const apply: CommandModuleWithWriteContext<{ warpDeployConfig, warpCoreConfig, strategyUrl, + receiptsDir, }); process.exit(0); }, diff --git a/typescript/cli/src/deploy/warp.ts b/typescript/cli/src/deploy/warp.ts index b34caa910..1fc13c1ec 100644 --- a/typescript/cli/src/deploy/warp.ts +++ b/typescript/cli/src/deploy/warp.ts @@ -57,6 +57,7 @@ import { objKeys, objMap, promiseObjAll, + retryAsync, } from '@hyperlane-xyz/utils'; import { readWarpRouteDeployConfig } from '../config/warp.js'; @@ -77,6 +78,7 @@ import { isFile, readYamlOrJson, runFileSelectionStep, + writeYamlOrJson, } from '../utils/files.js'; import { @@ -93,6 +95,7 @@ interface DeployParams { interface WarpApplyParams extends DeployParams { warpCoreConfig: WarpCoreConfig; strategyUrl?: string; + receiptsDir: string; } export async function runWarpRouteDeploy({ @@ -434,7 +437,7 @@ function fullyConnectTokens(warpCoreConfig: WarpCoreConfig): void { export async function runWarpRouteApply( params: WarpApplyParams, ): Promise { - const { warpDeployConfig, warpCoreConfig, context, strategyUrl } = params; + const { warpDeployConfig, warpCoreConfig, context } = params; const { registry, multiProvider, chainMetadata, skipConfirmation } = context; WarpRouteDeployConfigSchema.parse(warpDeployConfig); @@ -489,18 +492,7 @@ export async function runWarpRouteApply( return logGreen( `Warp config on ${chain} is the same as target. No updates needed.`, ); - const submitter: TxSubmitterBuilder = - await getWarpApplySubmitter({ - chain, - context, - strategyUrl, - }); - const transactionReceipts = await submitter.submit(...transactions); - - return logGreen( - `✅ Warp config update successfully submitted with ${submitter.txSubmitterType} on ${chain}:\n\n`, - indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 4), - ); + await submitWarpApplyTransactions(chain, params, transactions); } catch (e) { logRed(`Warp config on ${chain} failed to update.`, e); } @@ -542,7 +534,7 @@ export async function runWarpRouteApply( warpCoreConfigByChain, ); - await enrollRemoteRouters(context, mergedRouters, strategyUrl); + await enrollRemoteRouters(params, mergedRouters); const updatedWarpCoreConfig = await getWarpCoreConfig( params, @@ -623,62 +615,53 @@ function mergeAllRouters( * @param multiProvider - A MultiProvider instance to interact with multiple chains. */ async function enrollRemoteRouters( - context: WriteCommandContext, + params: WarpApplyParams, deployedContractsMap: HyperlaneContractsMap, - strategyUrl?: string, ): Promise { - logBlue(`Enrolling deployed routers with each other (if not already)...`); - const { multiProvider } = context; + logBlue(`Enrolling deployed routers with each other...`); + const { multiProvider } = params.context; const deployedRouters: ChainMap
= objMap( deployedContractsMap, (_, contracts) => getRouter(contracts).address, ); const allChains = Object.keys(deployedRouters); - await promiseObjAll( objMap(deployedContractsMap, async (chain, contracts) => { - const router = getRouter(contracts); // Assume deployedContract always has 1 value - - // Mutate the config.remoteRouters by setting it to all other routers to update - const warpRouteReader = new EvmERC20WarpRouteReader(multiProvider, chain); - const mutatedWarpRouteConfig = - await warpRouteReader.deriveWarpRouteConfig(router.address); - const evmERC20WarpModule = new EvmERC20WarpModule(multiProvider, { - config: mutatedWarpRouteConfig, - chain, - addresses: { deployedTokenRoute: router.address }, - }); + await retryAsync(async () => { + const router = getRouter(contracts); // Assume deployedContract always has 1 value - const otherChains = multiProvider - .getRemoteChains(chain) - .filter((c) => allChains.includes(c)); - - mutatedWarpRouteConfig.remoteRouters = otherChains.reduce( - (remoteRouters, chain) => { - remoteRouters[multiProvider.getDomainId(chain)] = - deployedRouters[chain]; - return remoteRouters; - }, - {}, - ); - const mutatedConfigTxs: AnnotatedEV5Transaction[] = - await evmERC20WarpModule.update(mutatedWarpRouteConfig); - - if (mutatedConfigTxs.length == 0) - return logGreen( - `Mutated warp config on ${chain} is the same as target. No updates needed.`, + // Mutate the config.remoteRouters by setting it to all other routers to update + const warpRouteReader = new EvmERC20WarpRouteReader( + multiProvider, + chain, ); - const submitter: TxSubmitterBuilder = - await getWarpApplySubmitter({ + const mutatedWarpRouteConfig = + await warpRouteReader.deriveWarpRouteConfig(router.address); + const evmERC20WarpModule = new EvmERC20WarpModule(multiProvider, { + config: mutatedWarpRouteConfig, chain, - context, - strategyUrl, + addresses: { deployedTokenRoute: router.address }, }); - const transactionReceipts = await submitter.submit(...mutatedConfigTxs); - return logGreen( - `✅ Router enrollment update successfully submitted with ${submitter.txSubmitterType} on ${chain}:\n\n`, - indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 4), - ); + + const otherChains = multiProvider + .getRemoteChains(chain) + .filter((c) => allChains.includes(c)); + + mutatedWarpRouteConfig.remoteRouters = + otherChains.reduce((remoteRouters, chain) => { + remoteRouters[multiProvider.getDomainId(chain)] = + deployedRouters[chain]; + return remoteRouters; + }, {}); + const mutatedConfigTxs: AnnotatedEV5Transaction[] = + await evmERC20WarpModule.update(mutatedWarpRouteConfig); + + if (mutatedConfigTxs.length == 0) + return logGreen( + `Warp config on ${chain} is the same as target. No updates needed.`, + ); + await submitWarpApplyTransactions(chain, params, mutatedConfigTxs); + }); }), ); } @@ -818,6 +801,36 @@ function transformIsmConfigForDisplay(ismConfig: IsmConfig): any[] { } } +/** + * Submits a set of transactions to the specified chain and outputs transaction receipts + */ +async function submitWarpApplyTransactions( + chain: string, + params: WarpApplyParams, + transactions: AnnotatedEV5Transaction[], +) { + const submitter: TxSubmitterBuilder = + await getWarpApplySubmitter({ + chain, + context: params.context, + strategyUrl: params.strategyUrl, + }); + + const transactionReceipts = await submitter.submit(...transactions); + if (transactionReceipts) { + const receiptPath = `${params.receiptsDir}/${chain}-${ + submitter.txSubmitterType + }-${Date.now()}-receipts.json`; + writeYamlOrJson(receiptPath, transactionReceipts); + logGreen(`Transactions receipts successfully written to ${receiptPath}`); + } + + return logGreen( + `✅ Warp route update success with ${submitter.txSubmitterType} on ${chain}:\n\n`, + indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 0), + ); +} + /** * Helper function to get warp apply specific submitter. * diff --git a/typescript/cli/src/submit/submit.ts b/typescript/cli/src/submit/submit.ts index 6c2cca501..29d1f8a05 100644 --- a/typescript/cli/src/submit/submit.ts +++ b/typescript/cli/src/submit/submit.ts @@ -1,4 +1,5 @@ import { + EV5GnosisSafeTxBuilder, EV5GnosisSafeTxSubmitter, EV5ImpersonatedAccountTxSubmitter, EV5InterchainAccountTxTransformer, @@ -47,6 +48,10 @@ async function getSubmitter( return EV5GnosisSafeTxSubmitter.create(multiProvider, { ...submitterMetadata, }); + case TxSubmitterType.GNOSIS_TX_BUILDER: + return EV5GnosisSafeTxBuilder.create(multiProvider, { + ...submitterMetadata, + }); default: throw new Error(`Invalid TxSubmitterType.`); } diff --git a/typescript/cli/src/utils/files.ts b/typescript/cli/src/utils/files.ts index 30360ddd8..9c7cb6216 100644 --- a/typescript/cli/src/utils/files.ts +++ b/typescript/cli/src/utils/files.ts @@ -23,6 +23,13 @@ export type ArtifactsFile = { description: string; }; +export function removeEndingSlash(dirPath: string): string { + if (dirPath.endsWith('/')) { + return dirPath.slice(0, -1); + } + return dirPath; +} + export function resolvePath(filePath: string): string { if (filePath.startsWith('~')) { const homedir = os.homedir(); diff --git a/typescript/sdk/src/consts/concurrency.ts b/typescript/sdk/src/consts/concurrency.ts index 62e6c801c..d9cc8fa7c 100644 --- a/typescript/sdk/src/consts/concurrency.ts +++ b/typescript/sdk/src/consts/concurrency.ts @@ -1 +1 @@ -export const DEFAULT_CONTRACT_READ_CONCURRENCY = 20; +export const DEFAULT_CONTRACT_READ_CONCURRENCY = 1; diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index 3270b4973..4959adacf 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -347,6 +347,7 @@ export { } from './providers/transactions/submitter/builder/types.js'; export { EV5GnosisSafeTxSubmitter } from './providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.js'; +export { EV5GnosisSafeTxBuilder } from './providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.js'; export { EV5ImpersonatedAccountTxSubmitter } from './providers/transactions/submitter/ethersV5/EV5ImpersonatedAccountTxSubmitter.js'; export { EV5JsonRpcTxSubmitter } from './providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.js'; export { EV5TxSubmitterInterface } from './providers/transactions/submitter/ethersV5/EV5TxSubmitterInterface.js'; diff --git a/typescript/sdk/src/providers/ProviderType.ts b/typescript/sdk/src/providers/ProviderType.ts index d7d84f152..7f017ab35 100644 --- a/typescript/sdk/src/providers/ProviderType.ts +++ b/typescript/sdk/src/providers/ProviderType.ts @@ -5,6 +5,7 @@ import type { } from '@cosmjs/cosmwasm-stargate'; import type { EncodeObject as CmTransaction } from '@cosmjs/proto-signing'; import type { DeliverTxResponse, StargateClient } from '@cosmjs/stargate'; +import { SafeTransactionData } from '@safe-global/safe-core-sdk-types'; import type { Connection, Transaction as SolTransaction, @@ -30,6 +31,7 @@ export enum ProviderType { SolanaWeb3 = 'solana-web3', CosmJs = 'cosmjs', CosmJsWasm = 'cosmjs-wasm', + GnosisTxBuilder = 'gnosis-txBuilder', } export const PROTOCOL_TO_DEFAULT_PROVIDER_TYPE: Record< @@ -37,6 +39,7 @@ export const PROTOCOL_TO_DEFAULT_PROVIDER_TYPE: Record< ProviderType > = { [ProtocolType.Ethereum]: ProviderType.EthersV5, + [ProtocolType.GnosisTxBuilder]: ProviderType.EthersV5, [ProtocolType.Sealevel]: ProviderType.SolanaWeb3, [ProtocolType.Cosmos]: ProviderType.CosmJsWasm, }; @@ -50,6 +53,12 @@ type ProtocolTypesMapping = { contract: EthersV5Contract; receipt: EthersV5TransactionReceipt; }; + [ProtocolType.GnosisTxBuilder]: { + transaction: EthersV5Transaction; + provider: EthersV5Provider; + contract: EthersV5Contract; + receipt: GnosisTransactionBuilderReceipt; + }; [ProtocolType.Sealevel]: { transaction: SolanaWeb3Transaction; provider: SolanaWeb3Provider; @@ -258,6 +267,19 @@ export interface CosmJsTransactionReceipt receipt: DeliverTxResponse; } +export interface GnosisTransactionBuilderReceipt + extends TypedTransactionReceiptBase { + type: ProviderType.GnosisTxBuilder; + receipt: GnosisTransactionBuilderPayload; +} + +export interface GnosisTransactionBuilderPayload { + version: string; + chainId: string; + meta: {}; + transactions: SafeTransactionData[]; +} + export interface CosmJsWasmTransactionReceipt extends TypedTransactionReceiptBase { type: ProviderType.CosmJsWasm; diff --git a/typescript/sdk/src/providers/providerBuilders.ts b/typescript/sdk/src/providers/providerBuilders.ts index b3a16762e..2be4100ee 100644 --- a/typescript/sdk/src/providers/providerBuilders.ts +++ b/typescript/sdk/src/providers/providerBuilders.ts @@ -123,6 +123,7 @@ export type ProviderBuilderMap = Record< >; export const defaultProviderBuilderMap: ProviderBuilderMap = { [ProviderType.EthersV5]: defaultEthersV5ProviderBuilder, + [ProviderType.GnosisTxBuilder]: defaultEthersV5ProviderBuilder, [ProviderType.Viem]: defaultViemProviderBuilder, [ProviderType.SolanaWeb3]: defaultSolProviderBuilder, [ProviderType.CosmJs]: defaultCosmJsProviderBuilder, @@ -134,6 +135,7 @@ export const protocolToDefaultProviderBuilder: Record< ProviderBuilderFn > = { [ProtocolType.Ethereum]: defaultEthersV5ProviderBuilder, + [ProtocolType.GnosisTxBuilder]: defaultEthersV5ProviderBuilder, [ProtocolType.Sealevel]: defaultSolProviderBuilder, [ProtocolType.Cosmos]: defaultCosmJsWasmProviderBuilder, }; diff --git a/typescript/sdk/src/providers/transactions/submitter/TxSubmitterInterface.ts b/typescript/sdk/src/providers/transactions/submitter/TxSubmitterInterface.ts index 69f8718e2..eab6fa575 100644 --- a/typescript/sdk/src/providers/transactions/submitter/TxSubmitterInterface.ts +++ b/typescript/sdk/src/providers/transactions/submitter/TxSubmitterInterface.ts @@ -23,5 +23,9 @@ export interface TxSubmitterInterface { */ submit( ...txs: ProtocolTypedTransaction['transaction'][] - ): Promise['receipt'][] | void>; + ): Promise< + | ProtocolTypedReceipt['receipt'] + | ProtocolTypedReceipt['receipt'][] + | void + >; } diff --git a/typescript/sdk/src/providers/transactions/submitter/TxSubmitterTypes.ts b/typescript/sdk/src/providers/transactions/submitter/TxSubmitterTypes.ts index 7b3b47840..60018c83c 100644 --- a/typescript/sdk/src/providers/transactions/submitter/TxSubmitterTypes.ts +++ b/typescript/sdk/src/providers/transactions/submitter/TxSubmitterTypes.ts @@ -2,4 +2,5 @@ export enum TxSubmitterType { JSON_RPC = 'jsonRpc', IMPERSONATED_ACCOUNT = 'impersonatedAccount', GNOSIS_SAFE = 'gnosisSafe', + GNOSIS_TX_BUILDER = 'gnosisSafeTxBuilder', } diff --git a/typescript/sdk/src/providers/transactions/submitter/builder/TxSubmitterBuilder.ts b/typescript/sdk/src/providers/transactions/submitter/builder/TxSubmitterBuilder.ts index 0d77040c6..a113e681d 100644 --- a/typescript/sdk/src/providers/transactions/submitter/builder/TxSubmitterBuilder.ts +++ b/typescript/sdk/src/providers/transactions/submitter/builder/TxSubmitterBuilder.ts @@ -74,7 +74,11 @@ export class TxSubmitterBuilder */ public async submit( ...txs: ProtocolTypedTransaction['transaction'][] - ): Promise['receipt'][] | void> { + ): Promise< + | ProtocolTypedReceipt['receipt'] + | ProtocolTypedReceipt['receipt'][] + | void + > { this.logger.debug( `Submitting ${txs.length} transactions to the ${this.currentSubmitter.txSubmitterType} submitter...`, ); diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts new file mode 100644 index 000000000..e3f90f61c --- /dev/null +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts @@ -0,0 +1,72 @@ +import { SafeTransactionData } from '@safe-global/safe-core-sdk-types'; + +import { assert } from '@hyperlane-xyz/utils'; + +// prettier-ignore +// @ts-ignore +import { getSafe, getSafeService } from '../../../../utils/gnosisSafe.js'; +import { MultiProvider } from '../../../MultiProvider.js'; +import { GnosisTransactionBuilderPayload } from '../../../ProviderType.js'; +import { PopulatedTransaction, PopulatedTransactions } from '../../types.js'; +import { TxSubmitterType } from '../TxSubmitterTypes.js'; + +import { EV5GnosisSafeTxSubmitter } from './EV5GnosisSafeTxSubmitter.js'; +import { EV5GnosisSafeTxBuilderProps } from './types.js'; + +/** + * This class is used to create a Safe Transaction Builder compatible object. + * It is not a true Submitter because it does not submits any transactions. + */ +export class EV5GnosisSafeTxBuilder extends EV5GnosisSafeTxSubmitter { + public readonly txSubmitterType: TxSubmitterType = + TxSubmitterType.GNOSIS_TX_BUILDER; + constructor( + public readonly multiProvider: MultiProvider, + public readonly props: EV5GnosisSafeTxBuilderProps, + safe: any, + safeService: any, + ) { + super(multiProvider, props, safe, safeService); + } + + static async create( + multiProvider: MultiProvider, + props: EV5GnosisSafeTxBuilderProps, + ): Promise { + const { chain, safeAddress } = props; + const { gnosisSafeTransactionServiceUrl } = + multiProvider.getChainMetadata(chain); + assert( + gnosisSafeTransactionServiceUrl, + `Must set gnosisSafeTransactionServiceUrl in the Registry metadata for ${chain}`, + ); + const safe = await getSafe(chain, multiProvider, safeAddress); + const safeService = await getSafeService(chain, multiProvider); + + return new EV5GnosisSafeTxBuilder(multiProvider, props, safe, safeService); + } + + /** + * Creates a Gnosis Safe transaction builder object using the PopulatedTransactions + * + * @param txs - An array of populated transactions + */ + public async submit( + ...txs: PopulatedTransactions + ): Promise { + const transactions: SafeTransactionData[] = await Promise.all( + txs.map( + async (tx: PopulatedTransaction) => + ( + await this.createSafeTransaction(tx) + ).data, + ), + ); + return { + version: this.props.version, + chainId: this.multiProvider.getChainId(this.props.chain).toString(), + meta: {}, + transactions, + }; + } +} diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts index 195b0b454..491594e60 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts @@ -1,3 +1,4 @@ +import { SafeTransaction } from '@safe-global/safe-core-sdk-types'; import { Logger } from 'pino'; import { Address, assert, rootLogger } from '@hyperlane-xyz/utils'; @@ -62,25 +63,43 @@ export class EV5GnosisSafeTxSubmitter implements EV5TxSubmitterInterface { ); } - public async submit(...txs: PopulatedTransactions): Promise { + public async createSafeTransaction({ + to, + data, + value, + chainId, + }: PopulatedTransaction): Promise { const nextNonce: number = await this.safeService.getNextNonce( this.props.safeAddress, ); - const safeTransactionBatch: any[] = txs.map( - ({ to, data, value, chainId }: PopulatedTransaction) => { - const txChain = this.multiProvider.getChainName(chainId); - assert( - txChain === this.props.chain, - `Invalid PopulatedTransaction: Cannot submit ${txChain} tx to ${this.props.chain} submitter.`, - ); - return { to, data, value: value?.toString() ?? '0' }; - }, + const txChain = this.multiProvider.getChainName(chainId); + assert( + txChain === this.props.chain, + `Invalid PopulatedTransaction: Cannot submit ${txChain} tx to ${this.props.chain} submitter.`, ); - const safeTransaction = await this.safe.createTransaction({ - safeTransactionData: safeTransactionBatch, + return this.safe.createTransaction({ + safeTransactionData: [{ to, data, value: value?.toString() ?? '0' }], options: { nonce: nextNonce }, }); - const safeTransactionData: any = safeTransaction.data; + } + + public async submit(...txs: PopulatedTransactions): Promise { + return this.proposeIndividualTransactions(txs); + } + + private async proposeIndividualTransactions(txs: PopulatedTransactions) { + const safeTransactions: SafeTransaction[] = []; + for (const tx of txs) { + const safeTransaction = await this.createSafeTransaction(tx); + await this.proposeSafeTransaction(safeTransaction); + safeTransactions.push(safeTransaction); + } + return safeTransactions; + } + + private async proposeSafeTransaction( + safeTransaction: SafeTransaction, + ): Promise { const safeTxHash: string = await this.safe.getTransactionHash( safeTransaction, ); @@ -94,14 +113,12 @@ export class EV5GnosisSafeTxSubmitter implements EV5TxSubmitterInterface { `Submitting transaction proposal to ${this.props.safeAddress} on ${this.props.chain}: ${safeTxHash}`, ); - const transactionReceipts = await this.safeService.proposeTransaction({ + return this.safeService.proposeTransaction({ safeAddress: this.props.safeAddress, - safeTransactionData, + safeTransactionData: safeTransaction.data, safeTxHash, senderAddress, senderSignature, }); - - return transactionReceipts ?? []; } } diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/schemas.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/schemas.ts index 7b5cb9a6c..931eb11bf 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/schemas.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/schemas.ts @@ -7,6 +7,12 @@ export const EV5GnosisSafeTxSubmitterPropsSchema = z.object({ safeAddress: ZHash, }); +export const EV5GnosisSafeTxBuilderPropsSchema = z.object({ + version: z.string().default('1.0'), + chain: ZChainName, + safeAddress: ZHash, +}); + export const EV5ImpersonatedAccountTxSubmitterPropsSchema = z.object({ userAddress: ZHash, }); diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/types.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/types.ts index 67edd01d4..ee41edfa4 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/types.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/types.ts @@ -1,6 +1,7 @@ import { z } from 'zod'; import { + EV5GnosisSafeTxBuilderPropsSchema, EV5GnosisSafeTxSubmitterPropsSchema, EV5ImpersonatedAccountTxSubmitterPropsSchema, } from './schemas.js'; @@ -8,6 +9,9 @@ import { export type EV5GnosisSafeTxSubmitterProps = z.infer< typeof EV5GnosisSafeTxSubmitterPropsSchema >; +export type EV5GnosisSafeTxBuilderProps = z.infer< + typeof EV5GnosisSafeTxBuilderPropsSchema +>; export type EV5ImpersonatedAccountTxSubmitterProps = z.infer< typeof EV5ImpersonatedAccountTxSubmitterPropsSchema >; diff --git a/typescript/sdk/src/providers/transactions/submitter/schemas.ts b/typescript/sdk/src/providers/transactions/submitter/schemas.ts index 9ec67f19b..89c891c09 100644 --- a/typescript/sdk/src/providers/transactions/submitter/schemas.ts +++ b/typescript/sdk/src/providers/transactions/submitter/schemas.ts @@ -2,6 +2,7 @@ import { z } from 'zod'; import { TxSubmitterType } from './TxSubmitterTypes.js'; import { + EV5GnosisSafeTxBuilderPropsSchema, EV5GnosisSafeTxSubmitterPropsSchema, EV5ImpersonatedAccountTxSubmitterPropsSchema, } from './ethersV5/schemas.js'; @@ -18,4 +19,8 @@ export const SubmitterMetadataSchema = z.discriminatedUnion('type', [ type: z.literal(TxSubmitterType.GNOSIS_SAFE), ...EV5GnosisSafeTxSubmitterPropsSchema.shape, }), + z.object({ + type: z.literal(TxSubmitterType.GNOSIS_TX_BUILDER), + ...EV5GnosisSafeTxBuilderPropsSchema.shape, + }), ]); diff --git a/typescript/sdk/src/token/TokenStandard.ts b/typescript/sdk/src/token/TokenStandard.ts index 002501d32..85ef6e6d5 100644 --- a/typescript/sdk/src/token/TokenStandard.ts +++ b/typescript/sdk/src/token/TokenStandard.ts @@ -159,6 +159,7 @@ export const TOKEN_TYPE_TO_STANDARD: Record = { export const PROTOCOL_TO_NATIVE_STANDARD: Record = { [ProtocolType.Ethereum]: TokenStandard.EvmNative, + [ProtocolType.GnosisTxBuilder]: TokenStandard.EvmNative, [ProtocolType.Cosmos]: TokenStandard.CosmosNative, [ProtocolType.Sealevel]: TokenStandard.SealevelNative, }; diff --git a/typescript/utils/src/types.ts b/typescript/utils/src/types.ts index 3d79f0058..7261e4904 100644 --- a/typescript/utils/src/types.ts +++ b/typescript/utils/src/types.ts @@ -5,6 +5,7 @@ export enum ProtocolType { Ethereum = 'ethereum', Sealevel = 'sealevel', Cosmos = 'cosmos', + GnosisTxBuilder = 'gnosisTxBuilder', } // A type that also allows for literal values of the enum export type ProtocolTypeValue = `${ProtocolType}`; From 5158296489fe70ce36da40e598fa6e504a45d49a Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 7 Oct 2024 18:36:52 -0400 Subject: [PATCH 108/224] fix: hook into version:update for automated release workflow (#4640) ### Description The release job is failing https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/9f19cdf469237773ccd42bcbd6bd3c58c56e644f/.github/workflows/release.yml#L40 https://github.com/hyperlane-xyz/hyperlane-monorepo/actions/runs/11224453679/job/31201246396?pr=4617 ### Testing None --- solidity/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solidity/package.json b/solidity/package.json index 2adae6c6d..3783336c5 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -64,7 +64,7 @@ ], "license": "Apache-2.0", "scripts": { - "build": "yarn version:bytecode && yarn hardhat-esm compile && tsc && ./exportBuildArtifact.sh", + "build": "yarn version:update && yarn hardhat-esm compile && tsc && ./exportBuildArtifact.sh", "lint": "solhint contracts/**/*.sol", "clean": "yarn hardhat-esm clean && rm -rf ./dist ./cache ./types ./coverage ./out ./forge-cache ./fixtures", "coverage": "yarn fixtures && ./coverage.sh", @@ -80,8 +80,8 @@ "gas-ci": "yarn gas --check --tolerance 2 || (echo 'Manually update gas snapshot' && exit 1)", "slither": "slither .", "storage": "./storage.sh", - "version:bytecode": "sh ./bytecodeversion.sh", - "version:changed": "yarn version:bytecode && git diff --exit-code", + "version:update": "sh ./bytecodeversion.sh", + "version:changed": "yarn version:update && git diff --exit-code", "version:exhaustive": "yarn tsx ./test/exhaustiveversion.test.ts" }, "peerDependencies": { From b314d3e4d16118fa27156ee4cb4373faaca5a588 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 23:06:26 +0000 Subject: [PATCH 109/224] Version Packages (#4617) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/core@5.4.0 ### Minor Changes - bb75eba74: fix: constrain rate limited ISM to a single message recipient - c5c217f8e: Embed NPM package version in bytecode constant ### Patch Changes - Updated dependencies [4415ac224] - @hyperlane-xyz/utils@5.4.0 ## @hyperlane-xyz/cli@5.4.0 ### Minor Changes - 4415ac224: Add Gnosis safe transaction builder to warp apply ### Patch Changes - Updated dependencies [4415ac224] - @hyperlane-xyz/utils@5.4.0 - @hyperlane-xyz/sdk@5.4.0 ## @hyperlane-xyz/sdk@5.4.0 ### Minor Changes - 4415ac224: Add Gnosis safe transaction builder to warp apply ### Patch Changes - Updated dependencies [bb75eba74] - Updated dependencies [4415ac224] - Updated dependencies [c5c217f8e] - @hyperlane-xyz/core@5.4.0 - @hyperlane-xyz/utils@5.4.0 ## @hyperlane-xyz/utils@5.4.0 ### Minor Changes - 4415ac224: Add Gnosis safe transaction builder to warp apply ## @hyperlane-xyz/helloworld@5.4.0 ### Patch Changes - Updated dependencies [bb75eba74] - Updated dependencies [4415ac224] - Updated dependencies [c5c217f8e] - @hyperlane-xyz/core@5.4.0 - @hyperlane-xyz/sdk@5.4.0 ## @hyperlane-xyz/widgets@5.4.0 ### Patch Changes - Updated dependencies [4415ac224] - @hyperlane-xyz/sdk@5.4.0 ## @hyperlane-xyz/infra@5.4.0 ### Patch Changes - Updated dependencies [4415ac224] - @hyperlane-xyz/utils@5.4.0 - @hyperlane-xyz/sdk@5.4.0 - @hyperlane-xyz/helloworld@5.4.0 ## @hyperlane-xyz/ccip-server@5.4.0 ## @hyperlane-xyz/github-proxy@5.4.0 --------- Co-authored-by: github-actions[bot] --- .changeset/breezy-toys-pay.md | 5 ----- .changeset/loud-glasses-beg.md | 7 ------ .changeset/silent-crabs-visit.md | 5 ----- solidity/CHANGELOG.md | 12 ++++++++++ solidity/contracts/PackageVersioned.sol | 2 +- solidity/package.json | 4 ++-- typescript/ccip-server/CHANGELOG.md | 2 ++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 12 ++++++++++ typescript/cli/package.json | 6 ++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 2 ++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 10 +++++++++ typescript/helloworld/package.json | 6 ++--- typescript/infra/CHANGELOG.md | 9 ++++++++ typescript/infra/package.json | 8 +++---- typescript/sdk/CHANGELOG.md | 14 ++++++++++++ typescript/sdk/package.json | 6 ++--- typescript/utils/CHANGELOG.md | 6 +++++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 7 ++++++ typescript/widgets/package.json | 4 ++-- yarn.lock | 30 ++++++++++++------------- 24 files changed, 111 insertions(+), 54 deletions(-) delete mode 100644 .changeset/breezy-toys-pay.md delete mode 100644 .changeset/loud-glasses-beg.md delete mode 100644 .changeset/silent-crabs-visit.md diff --git a/.changeset/breezy-toys-pay.md b/.changeset/breezy-toys-pay.md deleted file mode 100644 index e0cb028f4..000000000 --- a/.changeset/breezy-toys-pay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': minor ---- - -fix: constrain rate limited ISM to a single message recipient diff --git a/.changeset/loud-glasses-beg.md b/.changeset/loud-glasses-beg.md deleted file mode 100644 index 5e7708fcd..000000000 --- a/.changeset/loud-glasses-beg.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperlane-xyz/utils': minor -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Add Gnosis safe transaction builder to warp apply diff --git a/.changeset/silent-crabs-visit.md b/.changeset/silent-crabs-visit.md deleted file mode 100644 index e6d426ab9..000000000 --- a/.changeset/silent-crabs-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': minor ---- - -Embed NPM package version in bytecode constant diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index dae564ba4..fd020f14c 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,17 @@ # @hyperlane-xyz/core +## 5.4.0 + +### Minor Changes + +- bb75eba74: fix: constrain rate limited ISM to a single message recipient +- c5c217f8e: Embed NPM package version in bytecode constant + +### Patch Changes + +- Updated dependencies [4415ac224] + - @hyperlane-xyz/utils@5.4.0 + ## 5.3.0 ### Patch Changes diff --git a/solidity/contracts/PackageVersioned.sol b/solidity/contracts/PackageVersioned.sol index 84e980209..39f2a641b 100644 --- a/solidity/contracts/PackageVersioned.sol +++ b/solidity/contracts/PackageVersioned.sol @@ -7,5 +7,5 @@ pragma solidity >=0.6.11; **/ abstract contract PackageVersioned { // GENERATED CODE - DO NOT EDIT - string public constant PACKAGE_VERSION = "5.3.0"; + string public constant PACKAGE_VERSION = "5.4.0"; } diff --git a/solidity/package.json b/solidity/package.json index 3783336c5..f7416d10a 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.3.0", + "version": "5.4.0", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.3.0", + "@hyperlane-xyz/utils": "5.4.0", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index c363576a6..8ae8aab03 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/ccip-server +## 5.4.0 + ## 5.3.0 ## 5.2.1 diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index 911771111..53ce4f0ad 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.3.0", + "version": "5.4.0", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index 8a7fee418..73fb8b050 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,17 @@ # @hyperlane-xyz/cli +## 5.4.0 + +### Minor Changes + +- 4415ac224: Add Gnosis safe transaction builder to warp apply + +### Patch Changes + +- Updated dependencies [4415ac224] + - @hyperlane-xyz/utils@5.4.0 + - @hyperlane-xyz/sdk@5.4.0 + ## 5.3.0 ### Minor Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index c3ba1e78e..d2d617ae3 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.3.0", + "version": "5.4.0", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.3.0", - "@hyperlane-xyz/utils": "5.3.0", + "@hyperlane-xyz/sdk": "5.4.0", + "@hyperlane-xyz/utils": "5.4.0", "@inquirer/prompts": "^3.0.0", "asn1.js": "^5.4.1", "bignumber.js": "^9.1.1", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index 1c1586937..8559a97bf 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.3.0'; +export const VERSION = '5.4.0'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md index 8dc7b9be6..01b25aff9 100644 --- a/typescript/github-proxy/CHANGELOG.md +++ b/typescript/github-proxy/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/github-proxy +## 5.4.0 + ## 5.3.0 ## 5.2.1 diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index c4c002387..03c2af0e9 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.3.0", + "version": "5.4.0", "private": true, "scripts": { "deploy": "wrangler deploy", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index f2d2db3a6..bf074505c 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,15 @@ # @hyperlane-xyz/helloworld +## 5.4.0 + +### Patch Changes + +- Updated dependencies [bb75eba74] +- Updated dependencies [4415ac224] +- Updated dependencies [c5c217f8e] + - @hyperlane-xyz/core@5.4.0 + - @hyperlane-xyz/sdk@5.4.0 + ## 5.3.0 ### Minor Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index 14be666ff..095b84239 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.3.0", + "version": "5.4.0", "dependencies": { - "@hyperlane-xyz/core": "5.3.0", + "@hyperlane-xyz/core": "5.4.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.3.0", + "@hyperlane-xyz/sdk": "5.4.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index b1bdb77d0..d45256a13 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,14 @@ # @hyperlane-xyz/infra +## 5.4.0 + +### Patch Changes + +- Updated dependencies [4415ac224] + - @hyperlane-xyz/utils@5.4.0 + - @hyperlane-xyz/sdk@5.4.0 + - @hyperlane-xyz/helloworld@5.4.0 + ## 5.3.0 ### Patch Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 768f2411a..3a772cc3c 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.3.0", + "version": "5.4.0", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.3.0", + "@hyperlane-xyz/helloworld": "5.4.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.3.0", - "@hyperlane-xyz/utils": "5.3.0", + "@hyperlane-xyz/sdk": "5.4.0", + "@hyperlane-xyz/utils": "5.4.0", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index 486a7ed3f..6c5fd41e8 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,19 @@ # @hyperlane-xyz/sdk +## 5.4.0 + +### Minor Changes + +- 4415ac224: Add Gnosis safe transaction builder to warp apply + +### Patch Changes + +- Updated dependencies [bb75eba74] +- Updated dependencies [4415ac224] +- Updated dependencies [c5c217f8e] + - @hyperlane-xyz/core@5.4.0 + - @hyperlane-xyz/utils@5.4.0 + ## 5.3.0 ### Patch Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 2e19bd9e7..4b07bcb7c 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.3.0", + "version": "5.4.0", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.3.0", - "@hyperlane-xyz/utils": "5.3.0", + "@hyperlane-xyz/core": "5.4.0", + "@hyperlane-xyz/utils": "5.4.0", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index fc4aed2e3..81415beef 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @hyperlane-xyz/utils +## 5.4.0 + +### Minor Changes + +- 4415ac224: Add Gnosis safe transaction builder to warp apply + ## 5.3.0 ### Minor Changes diff --git a/typescript/utils/package.json b/typescript/utils/package.json index 59d4f0958..bb4ba14dd 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.3.0", + "version": "5.4.0", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index 4145ac3ba..0af96516b 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,12 @@ # @hyperlane-xyz/widgets +## 5.4.0 + +### Patch Changes + +- Updated dependencies [4415ac224] + - @hyperlane-xyz/sdk@5.4.0 + ## 5.3.0 ### Minor Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 2cfb3dafe..34732b858 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.3.0", + "version": "5.4.0", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.3.0" + "@hyperlane-xyz/sdk": "5.4.0" }, "devDependencies": { "@storybook/addon-essentials": "^7.6.14", diff --git a/yarn.lock b/yarn.lock index 1990c5588..99a2f1fe7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7759,8 +7759,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.3.0" - "@hyperlane-xyz/utils": "npm:5.3.0" + "@hyperlane-xyz/sdk": "npm:5.4.0" + "@hyperlane-xyz/utils": "npm:5.4.0" "@inquirer/prompts": "npm:^3.0.0" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:^18.14.5" @@ -7790,13 +7790,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.3.0, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.4.0, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.3.0" + "@hyperlane-xyz/utils": "npm:5.4.0" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7847,13 +7847,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.3.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.4.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.3.0" + "@hyperlane-xyz/core": "npm:5.4.0" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.3.0" + "@hyperlane-xyz/sdk": "npm:5.4.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7900,10 +7900,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.3.0" + "@hyperlane-xyz/helloworld": "npm:5.4.0" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.3.0" - "@hyperlane-xyz/utils": "npm:5.3.0" + "@hyperlane-xyz/sdk": "npm:5.4.0" + "@hyperlane-xyz/utils": "npm:5.4.0" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -7969,7 +7969,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.3.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.4.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -7977,8 +7977,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.3.0" - "@hyperlane-xyz/utils": "npm:5.3.0" + "@hyperlane-xyz/core": "npm:5.4.0" + "@hyperlane-xyz/utils": "npm:5.4.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -8019,7 +8019,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.3.0, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.4.0, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -8044,7 +8044,7 @@ __metadata: resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.3.0" + "@hyperlane-xyz/sdk": "npm:5.4.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From e490e774455c3d9ca309d4a794fdc37d830050e8 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Tue, 8 Oct 2024 11:41:15 +0100 Subject: [PATCH 110/224] feat: Generate Cosmos address for Injective (#4618) ### Description Injective uses different logic compared to Neutron and Osmosis to generate account addresses from public key. It is implemented in this PR so that sender address is correctly generated from signer info of transaction. Depending on the type of public key communicated in the transaction, we shall generate either Bitcoin-like or Ethereum-like address for Injective. We can also specify the type of account id for the signer. Bitcoin-like will be chosen by default, so, we don't need to change the configuration of Relayer. ### Drive-by changes Made some errors to be warnings. We'll add metrics to measure how frequent the issues are and decide how to fix them: 1. transaction contains multiple contract execution messages 2. transaction contains fees in unsupported denominations Made Scraper to refrain from recording transaction which it cannot parse properly. ### Backward compatibility Yes ### Testing Added unit tests Manual testing with Injective blockchain --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- rust/main/Cargo.lock | 81 ++++++++------ rust/main/Cargo.toml | 7 +- rust/main/chains/hyperlane-cosmos/Cargo.toml | 1 + .../main/chains/hyperlane-cosmos/src/error.rs | 11 +- .../hyperlane-cosmos/src/libs/account.rs | 40 ++++++- .../src/libs/account/tests.rs | 74 ++++++++++++ .../hyperlane-cosmos/src/libs/address.rs | 41 ++++--- .../chains/hyperlane-cosmos/src/libs/mod.rs | 8 +- .../hyperlane-cosmos/src/mailbox/contract.rs | 3 +- .../src/providers/cosmos/provider.rs | 105 +++++++++++++++--- .../hyperlane-cosmos/src/providers/grpc.rs | 14 ++- .../src/providers/grpc/tests.rs | 3 +- .../src/providers/rpc/provider.rs | 3 +- .../hyperlane-cosmos/src/routing_ism.rs | 3 +- .../chains/hyperlane-cosmos/src/signers.rs | 14 ++- .../hyperlane-base/src/settings/parser/mod.rs | 7 ++ .../hyperlane-base/src/settings/signers.rs | 12 +- .../src/types/account_address_type.rs | 11 ++ rust/main/hyperlane-core/src/types/mod.rs | 6 +- rust/main/utils/crypto/Cargo.toml | 14 +++ rust/main/utils/crypto/src/key.rs | 51 +++++++++ rust/main/utils/crypto/src/lib.rs | 4 + 22 files changed, 416 insertions(+), 97 deletions(-) create mode 100644 rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs create mode 100644 rust/main/hyperlane-core/src/types/account_address_type.rs create mode 100644 rust/main/utils/crypto/Cargo.toml create mode 100644 rust/main/utils/crypto/src/key.rs create mode 100644 rust/main/utils/crypto/src/lib.rs diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index 68f4a2732..9300a0ecb 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -515,7 +515,7 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "itoa", @@ -545,7 +545,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.11", + "http 0.2.12", "http-body", "mime", "rustversion", @@ -1256,7 +1256,7 @@ dependencies = [ "coins-core 0.8.7", "digest 0.10.7", "hmac 0.12.1", - "k256 0.13.3", + "k256 0.13.4", "serde", "sha2 0.10.8", "thiserror", @@ -1564,7 +1564,7 @@ dependencies = [ "ecdsa 0.16.9", "eyre", "getrandom 0.2.15", - "k256 0.13.3", + "k256 0.13.4", "rand_core 0.6.4", "serde", "serde_json", @@ -1589,7 +1589,7 @@ checksum = "0f862b355f7e47711e0acfe6af92cb3fd8fd5936b66a9eaa338b51edabd1e77d" dependencies = [ "digest 0.10.7", "ed25519-zebra 3.1.0", - "k256 0.13.3", + "k256 0.13.4", "rand_core 0.6.4", "thiserror", ] @@ -1608,7 +1608,7 @@ dependencies = [ "digest 0.10.7", "ecdsa 0.16.9", "ed25519-zebra 4.0.3", - "k256 0.13.3", + "k256 0.13.4", "num-traits", "p256", "rand_core 0.6.4", @@ -1798,6 +1798,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto" +version = "0.1.0" +dependencies = [ + "elliptic-curve 0.13.8", + "hex 0.4.3", + "k256 0.13.4", + "thiserror", +] + [[package]] name = "crypto-bigint" version = "0.4.9" @@ -3078,7 +3088,7 @@ dependencies = [ "getrandom 0.2.15", "hashers", "hex 0.4.3", - "http 0.2.11", + "http 0.2.12", "once_cell", "parking_lot 0.11.2", "pin-project", @@ -3484,7 +3494,7 @@ dependencies = [ "ecdsa 0.16.9", "ed25519-dalek 2.1.1", "fuel-types", - "k256 0.13.3", + "k256 0.13.4", "lazy_static", "p256", "rand 0.8.5", @@ -3979,7 +3989,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.11", + "http 0.2.12", "indexmap 2.5.0", "slab", "tokio", @@ -4074,7 +4084,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http 0.2.11", + "http 0.2.12", "httpdate", "mime", "sha1", @@ -4086,7 +4096,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http 0.2.11", + "http 0.2.12", ] [[package]] @@ -4230,9 +4240,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -4257,7 +4267,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.11", + "http 0.2.12", "pin-project-lite", ] @@ -4300,7 +4310,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "httparse", "httpdate", @@ -4322,7 +4332,7 @@ dependencies = [ "bytes", "futures", "headers", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-rustls 0.22.1", "rustls-native-certs 0.5.0", @@ -4357,7 +4367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.11", + "http 0.2.12", "hyper", "log", "rustls 0.21.12", @@ -4502,10 +4512,11 @@ dependencies = [ "bech32 0.9.1", "cosmrs", "cosmwasm-std 2.1.3", + "crypto", "derive-new", "futures", "hex 0.4.3", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-tls", "hyperlane-core", @@ -5091,9 +5102,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa 0.16.9", @@ -5480,7 +5491,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 0.2.11", + "http 0.2.12", "httparse", "log", "memchr", @@ -7027,7 +7038,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "hyper-rustls 0.24.2", @@ -7228,7 +7239,7 @@ dependencies = [ "hyperlane-cosmos", "hyperlane-cosmwasm-interface", "jobserver", - "k256 0.13.3", + "k256 0.13.4", "macro_rules_attribute", "maplit", "nix 0.26.4", @@ -7258,7 +7269,7 @@ dependencies = [ "bytes", "crc32fast", "futures", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-tls", "lazy_static", @@ -7330,7 +7341,7 @@ dependencies = [ "futures", "hex 0.4.3", "hmac 0.11.0", - "http 0.2.11", + "http 0.2.12", "hyper", "log", "md-5 0.9.1", @@ -9391,7 +9402,7 @@ dependencies = [ "base64 0.13.1", "bytes", "chrono", - "http 0.2.11", + "http 0.2.12", "percent-encoding", "serde", "serde_json", @@ -9430,7 +9441,7 @@ dependencies = [ "ed25519-consensus", "flex-error", "futures", - "k256 0.13.3", + "k256 0.13.4", "num-traits", "once_cell", "prost 0.11.9", @@ -9507,7 +9518,7 @@ dependencies = [ "flex-error", "futures", "getrandom 0.2.15", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-proxy", "hyper-rustls 0.22.1", @@ -9891,7 +9902,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "hyper-timeout", @@ -9921,7 +9932,7 @@ dependencies = [ "base64 0.21.7", "bytes", "h2", - "http 0.2.11", + "http 0.2.12", "http-body", "hyper", "hyper-timeout", @@ -10103,7 +10114,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "bytes", - "http 0.2.11", + "http 0.2.12", "httparse", "log", "rand 0.8.5", @@ -10376,7 +10387,7 @@ dependencies = [ "hyperlane-cosmos", "hyperlane-ethereum", "hyperlane-test", - "k256 0.13.3", + "k256 0.13.4", "mockall", "prometheus", "reqwest", @@ -10460,7 +10471,7 @@ dependencies = [ "futures-channel", "futures-util", "headers", - "http 0.2.11", + "http 0.2.12", "hyper", "log", "mime", @@ -10950,7 +10961,7 @@ checksum = "acaf2e321fc6f853572b372962fa253cba1b62a0025116bb463ce3c00b4394dc" dependencies = [ "cfg-if", "futures", - "http 0.2.11", + "http 0.2.12", "humantime-serde", "hyper", "hyper-rustls 0.24.2", @@ -10996,7 +11007,7 @@ dependencies = [ "async-trait", "base64 0.13.1", "futures", - "http 0.2.11", + "http 0.2.12", "hyper", "hyper-rustls 0.24.2", "itertools 0.10.5", diff --git a/rust/main/Cargo.toml b/rust/main/Cargo.toml index aab9a72b9..0f1ec5f74 100644 --- a/rust/main/Cargo.toml +++ b/rust/main/Cargo.toml @@ -13,6 +13,7 @@ members = [ "hyperlane-test", "utils/abigen", "utils/backtrace-oneline", + "utils/crypto", "utils/hex", "utils/run-locally", ] @@ -69,10 +70,10 @@ futures-util = "0.3" generic-array = { version = "0.14", features = ["serde", "more_lengths"] } # Required for WASM support https://docs.rs/getrandom/latest/getrandom/#webassembly-support bech32 = "0.9.1" -elliptic-curve = "0.12.3" +elliptic-curve = "0.13.8" getrandom = { version = "0.2", features = ["js"] } hex = "0.4.3" -http = "*" +http = "0.2.12" hyper = "0.14" hyper-tls = "0.5.0" hyperlane-cosmwasm-interface = "=0.0.6-rc6" @@ -81,7 +82,7 @@ injective-std = "=0.1.5" itertools = "*" jobserver = "=0.1.26" jsonrpc-core = "18.0" -k256 = { version = "0.13.1", features = ["std", "ecdsa"] } +k256 = { version = "0.13.4", features = ["arithmetic", "std", "ecdsa"] } log = "0.4" macro_rules_attribute = "0.2" maplit = "1.0" diff --git a/rust/main/chains/hyperlane-cosmos/Cargo.toml b/rust/main/chains/hyperlane-cosmos/Cargo.toml index e8b1af668..ce936ec1f 100644 --- a/rust/main/chains/hyperlane-cosmos/Cargo.toml +++ b/rust/main/chains/hyperlane-cosmos/Cargo.toml @@ -14,6 +14,7 @@ base64 = { workspace = true } bech32 = { workspace = true } cosmrs = { workspace = true, features = ["cosmwasm", "tokio", "grpc", "rpc"] } cosmwasm-std = { workspace = true } +crypto = { path = "../../utils/crypto" } derive-new = { workspace = true } futures = { workspace = true } hex = { workspace = true } diff --git a/rust/main/chains/hyperlane-cosmos/src/error.rs b/rust/main/chains/hyperlane-cosmos/src/error.rs index abe61fd92..8ceacd601 100644 --- a/rust/main/chains/hyperlane-cosmos/src/error.rs +++ b/rust/main/chains/hyperlane-cosmos/src/error.rs @@ -1,6 +1,9 @@ +use std::fmt::Debug; + use cosmrs::proto::prost; + +use crypto::PublicKeyError; use hyperlane_core::ChainCommunicationError; -use std::fmt::Debug; /// Errors from the crates specific to the hyperlane-cosmos /// implementation. @@ -60,3 +63,9 @@ impl From for ChainCommunicationError { ChainCommunicationError::from_other(value) } } + +impl From for HyperlaneCosmosError { + fn from(value: PublicKeyError) -> Self { + HyperlaneCosmosError::PublicKeyError(value.to_string()) + } +} diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs index bac0fe4bc..092a1f45b 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs @@ -1,9 +1,11 @@ use cosmrs::{crypto::PublicKey, AccountId}; +use hyperlane_cosmwasm_interface::types::keccak256_hash; use tendermint::account::Id as TendermintAccountId; use tendermint::public_key::PublicKey as TendermintPublicKey; +use crypto::decompress_public_key; use hyperlane_core::Error::Overflow; -use hyperlane_core::{ChainCommunicationError, ChainResult, H256}; +use hyperlane_core::{AccountAddressType, ChainCommunicationError, ChainResult, H256}; use crate::HyperlaneCosmosError; @@ -16,7 +18,21 @@ impl<'a> CosmosAccountId<'a> { Self { account_id } } - pub fn account_id_from_pubkey(pub_key: PublicKey, prefix: &str) -> ChainResult { + /// Calculate AccountId from public key depending on provided prefix + pub fn account_id_from_pubkey( + pub_key: PublicKey, + prefix: &str, + account_address_type: &AccountAddressType, + ) -> ChainResult { + match account_address_type { + AccountAddressType::Bitcoin => Self::bitcoin_style(pub_key, prefix), + AccountAddressType::Ethereum => Self::ethereum_style(pub_key, prefix), + } + } + + /// Returns a Bitcoin style address: RIPEMD160(SHA256(pubkey)) + /// Source: `` + fn bitcoin_style(pub_key: PublicKey, prefix: &str) -> ChainResult { // Get the inner type let tendermint_pub_key = TendermintPublicKey::from(pub_key); // Get the RIPEMD160(SHA256(pub_key)) @@ -27,6 +43,23 @@ impl<'a> CosmosAccountId<'a> { Ok(account_id) } + + /// Returns an Ethereum style address: KECCAK256(pubkey)[20] + /// Parameter `pub_key` is a compressed public key. + fn ethereum_style(pub_key: PublicKey, prefix: &str) -> ChainResult { + let decompressed_public_key = decompress_public_key(&pub_key.to_bytes()) + .map_err(Into::::into)?; + + let hash = keccak256_hash(&decompressed_public_key[1..]); + + let mut bytes = [0u8; 20]; + bytes.copy_from_slice(&hash.as_slice()[12..]); + + let account_id = + AccountId::new(prefix, bytes.as_slice()).map_err(Into::::into)?; + + Ok(account_id) + } } impl TryFrom<&CosmosAccountId<'_>> for H256 { @@ -55,3 +88,6 @@ impl TryFrom> for H256 { (&account_id).try_into() } } + +#[cfg(test)] +mod tests; diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs new file mode 100644 index 000000000..0ba8f73d7 --- /dev/null +++ b/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs @@ -0,0 +1,74 @@ +use cosmrs::crypto::PublicKey; +use cosmwasm_std::HexBinary; + +use crypto::decompress_public_key; +use hyperlane_core::AccountAddressType; +use AccountAddressType::{Bitcoin, Ethereum}; + +use crate::CosmosAccountId; + +const COMPRESSED_PUBLIC_KEY: &str = + "02962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f4"; +const INJECTIVE_ADDRESS: &str = "inj1m6ada382hfuxvuke4h9p4uswhn2qcca7mlg0dr"; +const NEUTRON_ADDRESS: &str = "neutron1mydju5alsmhnfsawy0j4lyns70l7qukgdgy45w"; + +#[test] +fn test_account_id() { + // given + let pub_key = compressed_public_key(); + + // when + let neutron_account_id = + CosmosAccountId::account_id_from_pubkey(pub_key, "neutron", &Bitcoin).unwrap(); + let injective_account_id = + CosmosAccountId::account_id_from_pubkey(pub_key, "inj", &Ethereum).unwrap(); + + // then + assert_eq!(neutron_account_id.as_ref(), NEUTRON_ADDRESS); + assert_eq!(injective_account_id.as_ref(), INJECTIVE_ADDRESS); +} + +#[test] +fn test_bitcoin_style() { + // given + let compressed = compressed_public_key(); + let decompressed = decompressed_public_key(); + + // when + let from_compressed = CosmosAccountId::bitcoin_style(compressed, "neutron").unwrap(); + let from_decompressed = CosmosAccountId::bitcoin_style(decompressed, "neutron").unwrap(); + + // then + assert_eq!(from_compressed.as_ref(), NEUTRON_ADDRESS); + assert_eq!(from_decompressed.as_ref(), NEUTRON_ADDRESS); +} + +#[test] +fn test_ethereum_style() { + // given + let compressed = compressed_public_key(); + let decompressed = decompressed_public_key(); + + // when + let from_compressed = CosmosAccountId::ethereum_style(compressed, "inj").unwrap(); + let from_decompressed = CosmosAccountId::ethereum_style(decompressed, "inj").unwrap(); + + // then + assert_eq!(from_compressed.as_ref(), INJECTIVE_ADDRESS); + assert_eq!(from_decompressed.as_ref(), INJECTIVE_ADDRESS); +} + +fn compressed_public_key() -> PublicKey { + let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); + let tendermint = tendermint::PublicKey::from_raw_secp256k1(&hex).unwrap(); + let pub_key = PublicKey::from(tendermint); + pub_key +} + +fn decompressed_public_key() -> PublicKey { + let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); + let decompressed = decompress_public_key(&hex).unwrap(); + let tendermint = tendermint::PublicKey::from_raw_secp256k1(&decompressed).unwrap(); + let pub_key = PublicKey::from(tendermint); + pub_key +} diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs index 41a5ab6ab..4fa08ac9f 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs @@ -5,10 +5,11 @@ use cosmrs::{ AccountId, }; use derive_new::new; -use hyperlane_core::{ChainCommunicationError, ChainResult, Error::Overflow, H256}; +use hyperlane_core::{ + AccountAddressType, ChainCommunicationError, ChainResult, Error::Overflow, H256, +}; -use crate::libs::account::CosmosAccountId; -use crate::HyperlaneCosmosError; +use crate::{CosmosAccountId, HyperlaneCosmosError}; /// Wrapper around the cosmrs AccountId type that abstracts bech32 encoding #[derive(new, Debug, Clone)] @@ -20,23 +21,19 @@ pub struct CosmosAddress { } impl CosmosAddress { - /// Returns a Bitcoin style address: RIPEMD160(SHA256(pubkey)) - /// Source: `` - pub fn from_pubkey(pubkey: PublicKey, prefix: &str) -> ChainResult { - let account_id = CosmosAccountId::account_id_from_pubkey(pubkey, prefix)?; - Self::from_account_id(account_id) - } - /// Creates a wrapper around a cosmrs AccountId from a private key byte array - pub fn from_privkey(priv_key: &[u8], prefix: &str) -> ChainResult { + pub fn from_privkey( + priv_key: &[u8], + prefix: &str, + account_address_type: &AccountAddressType, + ) -> ChainResult { let pubkey = SigningKey::from_slice(priv_key) .map_err(Into::::into)? .public_key(); - Self::from_pubkey(pubkey, prefix) + Self::from_pubkey(pubkey, prefix, account_address_type) } - /// Returns a Bitcoin style address calculated from Bech32 encoding - /// Source: `` + /// Returns an account address calculated from Bech32 encoding pub fn from_account_id(account_id: AccountId) -> ChainResult { // Hex digest let digest = H256::try_from(&CosmosAccountId::new(&account_id))?; @@ -77,6 +74,17 @@ impl CosmosAddress { pub fn digest(&self) -> H256 { self.digest } + + /// Calculates an account address depending on prefix and account address type + fn from_pubkey( + pubkey: PublicKey, + prefix: &str, + account_address_type: &AccountAddressType, + ) -> ChainResult { + let account_id = + CosmosAccountId::account_id_from_pubkey(pubkey, prefix, account_address_type)?; + Self::from_account_id(account_id) + } } impl TryFrom<&CosmosAddress> for H256 { @@ -119,8 +127,9 @@ pub mod test { let hex_key = "0x5486418967eabc770b0fcb995f7ef6d9a72f7fc195531ef76c5109f44f51af26"; let key = hex_or_base58_to_h256(hex_key).unwrap(); let prefix = "neutron"; - let addr = CosmosAddress::from_privkey(key.as_bytes(), prefix) - .expect("Cosmos address creation failed"); + let addr = + CosmosAddress::from_privkey(key.as_bytes(), prefix, &AccountAddressType::Bitcoin) + .expect("Cosmos address creation failed"); assert_eq!( addr.address(), "neutron1kknekjxg0ear00dky5ykzs8wwp2gz62z9s6aaj" diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/mod.rs b/rust/main/chains/hyperlane-cosmos/src/libs/mod.rs index d641b041a..0ee55478e 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/mod.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/mod.rs @@ -1,4 +1,8 @@ +pub(crate) use account::CosmosAccountId; +pub(crate) use address::CosmosAddress; + /// This module contains conversions from Cosmos AccountId to H56 -pub(crate) mod account; +mod account; + /// This module contains all the verification variables the libraries used by the Hyperlane Cosmos chain. -pub mod address; +mod address; diff --git a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs index 9d9f39c54..7c3f1c4ee 100644 --- a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs +++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs @@ -11,7 +11,6 @@ use hyperlane_core::{ TxCostEstimate, TxOutcome, H256, U256, }; -use crate::address::CosmosAddress; use crate::grpc::WasmProvider; use crate::payloads::general; use crate::payloads::mailbox::{ @@ -19,7 +18,7 @@ use crate::payloads::mailbox::{ }; use crate::types::tx_response_to_outcome; use crate::utils::get_block_height_for_lag; -use crate::{payloads, ConnectionConf, CosmosProvider, Signer}; +use crate::{payloads, ConnectionConf, CosmosAddress, CosmosProvider, Signer}; #[derive(Clone, Debug)] /// A reference to a Mailbox contract on some Cosmos chain diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index 62931e69e..6b3e52863 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -1,8 +1,10 @@ +use std::str::FromStr; + use async_trait::async_trait; use cosmrs::cosmwasm::MsgExecuteContract; use cosmrs::crypto::PublicKey; -use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo}; -use cosmrs::{AccountId, Any, Coin, Tx}; +use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo, SignerPublicKey}; +use cosmrs::{proto, AccountId, Any, Coin, Tx}; use itertools::Itertools; use once_cell::sync::Lazy; use tendermint::hash::Algorithm; @@ -11,20 +13,25 @@ use tendermint_rpc::{client::CompatMode, Client, HttpClient}; use time::OffsetDateTime; use tracing::{error, warn}; +use crypto::decompress_public_key; use hyperlane_core::{ - BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, ContractLocator, HyperlaneChain, - HyperlaneDomain, HyperlaneProvider, TxnInfo, TxnReceiptInfo, H256, U256, + AccountAddressType, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, + ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, TxnInfo, TxnReceiptInfo, + H256, U256, }; -use crate::address::CosmosAddress; use crate::grpc::{WasmGrpcProvider, WasmProvider}; -use crate::libs::account::CosmosAccountId; use crate::providers::rpc::CosmosRpcClient; -use crate::{ConnectionConf, CosmosAmount, HyperlaneCosmosError, Signer}; +use crate::{ + ConnectionConf, CosmosAccountId, CosmosAddress, CosmosAmount, HyperlaneCosmosError, Signer, +}; /// Exponent value for atto units (10^-18). const ATTO_EXPONENT: u32 = 18; +/// Injective public key type URL for protobuf Any +const INJECTIVE_PUBLIC_KEY_TYPE_URL: &str = "/injective.crypto.v1beta1.ethsecp256k1.PubKey"; + /// Abstraction over a connection to a Cosmos chain #[derive(Debug, Clone)] pub struct CosmosProvider { @@ -93,16 +100,74 @@ impl CosmosProvider { HyperlaneCosmosError::PublicKeyError("no public key for default signer".to_owned()) })?; - let public_key = PublicKey::try_from(signer_public_key)?; + let (key, account_address_type) = self.normalize_public_key(signer_public_key)?; + let public_key = PublicKey::try_from(key)?; let account_id = CosmosAccountId::account_id_from_pubkey( public_key, &self.connection_conf.get_bech32_prefix(), + &account_address_type, )?; Ok((account_id, signer_info.sequence)) } + fn normalize_public_key( + &self, + signer_public_key: SignerPublicKey, + ) -> ChainResult<(SignerPublicKey, AccountAddressType)> { + let public_key_and_account_address_type = match signer_public_key { + SignerPublicKey::Single(pk) => (SignerPublicKey::from(pk), AccountAddressType::Bitcoin), + SignerPublicKey::LegacyAminoMultisig(pk) => { + (SignerPublicKey::from(pk), AccountAddressType::Bitcoin) + } + SignerPublicKey::Any(pk) => { + if pk.type_url != PublicKey::ED25519_TYPE_URL + && pk.type_url != PublicKey::SECP256K1_TYPE_URL + && pk.type_url != INJECTIVE_PUBLIC_KEY_TYPE_URL + { + let msg = format!( + "can only normalize public keys with a known TYPE_URL: {}, {}, {}", + PublicKey::ED25519_TYPE_URL, + PublicKey::SECP256K1_TYPE_URL, + INJECTIVE_PUBLIC_KEY_TYPE_URL + ); + warn!(pk.type_url, msg); + Err(HyperlaneCosmosError::PublicKeyError(msg.to_owned()))? + } + + let (pub_key, account_address_type) = + if pk.type_url == INJECTIVE_PUBLIC_KEY_TYPE_URL { + let any = Any { + type_url: PublicKey::SECP256K1_TYPE_URL.to_owned(), + value: pk.value, + }; + + let proto = proto::cosmos::crypto::secp256k1::PubKey::from_any(&any) + .map_err(Into::::into)?; + + let decompressed = decompress_public_key(&proto.key) + .map_err(|e| HyperlaneCosmosError::PublicKeyError(e.to_string()))?; + + let tendermint = tendermint::PublicKey::from_raw_secp256k1(&decompressed) + .ok_or_else(|| { + HyperlaneCosmosError::PublicKeyError( + "cannot create tendermint public key".to_owned(), + ) + })?; + + (PublicKey::from(tendermint), AccountAddressType::Ethereum) + } else { + (PublicKey::try_from(pk)?, AccountAddressType::Bitcoin) + }; + + (SignerPublicKey::Single(pub_key), account_address_type) + } + }; + + Ok(public_key_and_account_address_type) + } + /// Calculates the sender and the nonce for the transaction. /// We use `payer` of the fees as the sender of the transaction, and we search for `payer` /// signature information to find the nonce. @@ -146,14 +211,15 @@ impl CosmosProvider { let contract_execution_messages_len = contract_execution_messages.len(); if contract_execution_messages_len > 1 { - error!( - ?tx_hash, - ?contract_execution_messages, - "transaction contains multiple contract execution messages, we are indexing the first entry only"); + let msg = "transaction contains multiple contract execution messages, we are indexing the first entry only"; + warn!(?tx_hash, ?contract_execution_messages, msg); + Err(ChainCommunicationError::CustomError(msg.to_owned()))? } let any = contract_execution_messages.first().ok_or_else(|| { - ChainCommunicationError::from_other_str("could not find contract execution message") + let msg = "could not find contract execution message"; + warn!(?tx_hash, msg); + ChainCommunicationError::from_other_str(msg) })?; let proto = ProtoMsgExecuteContract::from_any(any).map_err(Into::::into)?; @@ -166,7 +232,7 @@ impl CosmosProvider { /// The only denomination we support at the moment is the one we express gas minimum price /// in the configuration of a chain. If fees contain an entry in a different denomination, /// we report it in the logs. - fn report_unsupported_denominations(&self, tx: &Tx, tx_hash: &H256) { + fn report_unsupported_denominations(&self, tx: &Tx, tx_hash: &H256) -> ChainResult<()> { let supported_denomination = self.connection_conf.get_minimum_gas_price().denom; let unsupported_denominations = tx .auth_info @@ -178,12 +244,17 @@ impl CosmosProvider { .fold("".to_string(), |acc, denom| acc + ", " + denom); if !unsupported_denominations.is_empty() { - error!( + let msg = "transaction contains fees in unsupported denominations, manual intervention is required"; + warn!( ?tx_hash, ?supported_denomination, ?unsupported_denominations, - "transaction contains fees in unsupported denominations, manual intervention is required"); + msg, + ); + Err(ChainCommunicationError::CustomError(msg.to_owned()))? } + + Ok(()) } /// Converts fees to a common denomination if necessary. @@ -278,7 +349,7 @@ impl HyperlaneProvider for CosmosProvider { let (sender, nonce) = self.sender_and_nonce(&tx)?; // TODO support multiple denominations for amount - self.report_unsupported_denominations(&tx, hash); + self.report_unsupported_denominations(&tx, hash)?; let gas_limit = U256::from(tx.auth_info.fee.gas_limit); let fee = tx diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs index 4b521658a..c2e05acf4 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/grpc.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + use async_trait::async_trait; use cosmrs::{ proto::{ @@ -25,13 +27,8 @@ use cosmrs::{ Any, Coin, }; use derive_new::new; -use hyperlane_core::{ - rpc_clients::{BlockNumberGetter, FallbackProvider}, - ChainCommunicationError, ChainResult, ContractLocator, FixedPointNumber, HyperlaneDomain, U256, -}; use protobuf::Message as _; use serde::Serialize; -use std::fmt::Debug; use tonic::{ transport::{Channel, Endpoint}, GrpcMethod, IntoRequest, @@ -39,9 +36,14 @@ use tonic::{ use tracing::{debug, instrument}; use url::Url; -use crate::{address::CosmosAddress, CosmosAmount}; +use hyperlane_core::{ + rpc_clients::{BlockNumberGetter, FallbackProvider}, + ChainCommunicationError, ChainResult, ContractLocator, FixedPointNumber, HyperlaneDomain, U256, +}; + use crate::{rpc_clients::CosmosFallbackProvider, HyperlaneCosmosError}; use crate::{signers::Signer, ConnectionConf}; +use crate::{CosmosAddress, CosmosAmount}; /// A multiplier applied to a simulated transaction's gas usage to /// calculate the estimated gas. diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs index 05570f9ce..2f5ca4abf 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs @@ -5,9 +5,8 @@ use url::Url; use hyperlane_core::config::OperationBatchConfig; use hyperlane_core::{ContractLocator, HyperlaneDomain, KnownHyperlaneDomain}; -use crate::address::CosmosAddress; use crate::grpc::{WasmGrpcProvider, WasmProvider}; -use crate::{ConnectionConf, CosmosAmount, NativeToken, RawCosmosAmount}; +use crate::{ConnectionConf, CosmosAddress, CosmosAmount, NativeToken, RawCosmosAmount}; #[ignore] #[tokio::test] diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs index 0184aff96..f9ec3e975 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs @@ -20,9 +20,8 @@ use hyperlane_core::{ ChainCommunicationError, ChainResult, ContractLocator, HyperlaneDomain, LogMeta, H256, U256, }; -use crate::address::CosmosAddress; use crate::rpc::CosmosRpcClient; -use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError}; +use crate::{ConnectionConf, CosmosAddress, CosmosProvider, HyperlaneCosmosError}; #[async_trait] /// Trait for wasm indexer. Use rpc provider diff --git a/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs b/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs index f7d3620eb..c68b2cf59 100644 --- a/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs +++ b/rust/main/chains/hyperlane-cosmos/src/routing_ism.rs @@ -8,13 +8,12 @@ use hyperlane_core::{ }; use crate::{ - address::CosmosAddress, grpc::WasmProvider, payloads::ism_routes::{ IsmRouteRequest, IsmRouteRequestInner, IsmRouteRespnose, QueryRoutingIsmGeneralRequest, }, signers::Signer, - ConnectionConf, CosmosProvider, + ConnectionConf, CosmosAddress, CosmosProvider, }; /// A reference to a RoutingIsm contract on some Cosmos chain diff --git a/rust/main/chains/hyperlane-cosmos/src/signers.rs b/rust/main/chains/hyperlane-cosmos/src/signers.rs index 60870fc92..1cd0dd8ec 100644 --- a/rust/main/chains/hyperlane-cosmos/src/signers.rs +++ b/rust/main/chains/hyperlane-cosmos/src/signers.rs @@ -1,7 +1,7 @@ use cosmrs::crypto::{secp256k1::SigningKey, PublicKey}; -use hyperlane_core::ChainResult; +use hyperlane_core::{AccountAddressType, ChainResult}; -use crate::{address::CosmosAddress, HyperlaneCosmosError}; +use crate::{CosmosAddress, HyperlaneCosmosError}; #[derive(Clone, Debug)] /// Signer for cosmos chain @@ -22,8 +22,14 @@ impl Signer { /// # Arguments /// * `private_key` - private key for signer /// * `prefix` - prefix for signer address - pub fn new(private_key: Vec, prefix: String) -> ChainResult { - let address = CosmosAddress::from_privkey(&private_key, &prefix)?.address(); + /// * `account_address_type` - the type of account address used for signer + pub fn new( + private_key: Vec, + prefix: String, + account_address_type: &AccountAddressType, + ) -> ChainResult { + let address = + CosmosAddress::from_privkey(&private_key, &prefix, account_address_type)?.address(); let signing_key = Self::build_signing_key(&private_key)?; let public_key = signing_key.public_key(); Ok(Self { diff --git a/rust/main/hyperlane-base/src/settings/parser/mod.rs b/rust/main/hyperlane-base/src/settings/parser/mod.rs index f5c1451a0..65a8c845a 100644 --- a/rust/main/hyperlane-base/src/settings/parser/mod.rs +++ b/rust/main/hyperlane-base/src/settings/parser/mod.rs @@ -332,9 +332,16 @@ fn parse_signer(signer: ValueParser) -> ConfigResult { .get_key("prefix") .parse_string() .unwrap_or_default(); + let account_address_type = signer + .chain(&mut err) + .get_opt_key("accountAddressType") + .parse_from_str("Expected Account Address Type") + .end() + .unwrap_or_default(); err.into_result(SignerConf::CosmosKey { key, prefix: prefix.to_string(), + account_address_type, }) }}; } diff --git a/rust/main/hyperlane-base/src/settings/signers.rs b/rust/main/hyperlane-base/src/settings/signers.rs index 042894c6b..459a6337b 100644 --- a/rust/main/hyperlane-base/src/settings/signers.rs +++ b/rust/main/hyperlane-base/src/settings/signers.rs @@ -3,7 +3,7 @@ use ed25519_dalek::SecretKey; use ethers::prelude::{AwsSigner, LocalWallet}; use ethers::utils::hex::ToHex; use eyre::{bail, Context, Report}; -use hyperlane_core::H256; +use hyperlane_core::{AccountAddressType, H256}; use hyperlane_sealevel::Keypair; use rusoto_core::Region; use rusoto_kms::KmsClient; @@ -34,6 +34,8 @@ pub enum SignerConf { key: H256, /// Prefix for cosmos address prefix: String, + /// Account address type for cosmos address + account_address_type: AccountAddressType, }, /// Assume node will sign on RPC calls #[default] @@ -143,10 +145,16 @@ impl ChainSigner for Keypair { #[async_trait] impl BuildableWithSignerConf for hyperlane_cosmos::Signer { async fn build(conf: &SignerConf) -> Result { - if let SignerConf::CosmosKey { key, prefix } = conf { + if let SignerConf::CosmosKey { + key, + prefix, + account_address_type, + } = conf + { Ok(hyperlane_cosmos::Signer::new( key.as_bytes().to_vec(), prefix.clone(), + account_address_type, )?) } else { bail!(format!("{conf:?} key is not supported by cosmos")); diff --git a/rust/main/hyperlane-core/src/types/account_address_type.rs b/rust/main/hyperlane-core/src/types/account_address_type.rs new file mode 100644 index 000000000..2e8079d70 --- /dev/null +++ b/rust/main/hyperlane-core/src/types/account_address_type.rs @@ -0,0 +1,11 @@ +/// Specifies the account address type +#[derive( + Clone, Debug, Default, strum::Display, strum::EnumString, strum::IntoStaticStr, strum::EnumIter, +)] +pub enum AccountAddressType { + /// Bitcoin style address: RIPEMD160(SHA256(pubkey)) + #[default] + Bitcoin, + /// Ethereum style address: KECCAK256(pubkey)[20] + Ethereum, +} diff --git a/rust/main/hyperlane-core/src/types/mod.rs b/rust/main/hyperlane-core/src/types/mod.rs index f9d78b05a..07989e83e 100644 --- a/rust/main/hyperlane-core/src/types/mod.rs +++ b/rust/main/hyperlane-core/src/types/mod.rs @@ -1,11 +1,13 @@ -use serde::{Deserialize, Serialize}; use std::fmt; use std::io::{Read, Write}; use std::ops::Add; +use serde::{Deserialize, Serialize}; + pub use self::primitive_types::*; #[cfg(feature = "ethers")] pub use ::primitive_types as ethers_core_types; +pub use account_address_type::AccountAddressType; pub use announcement::*; pub use chain_data::*; pub use checkpoint::*; @@ -18,6 +20,8 @@ pub use transaction::*; use crate::{Decode, Encode, HyperlaneProtocolError}; +/// This module contains enum for account address type +mod account_address_type; mod announcement; mod chain_data; mod checkpoint; diff --git a/rust/main/utils/crypto/Cargo.toml b/rust/main/utils/crypto/Cargo.toml new file mode 100644 index 000000000..de5b64535 --- /dev/null +++ b/rust/main/utils/crypto/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "crypto" +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +publish.workspace = true +version.workspace = true + +[dependencies] +elliptic-curve = { workspace = true, features = ["sec1"] } +hex = { workspace = true } +k256 = { workspace = true } +thiserror = { workspace = true } diff --git a/rust/main/utils/crypto/src/key.rs b/rust/main/utils/crypto/src/key.rs new file mode 100644 index 000000000..601431f28 --- /dev/null +++ b/rust/main/utils/crypto/src/key.rs @@ -0,0 +1,51 @@ +use std::fmt::{Display, Formatter}; + +use elliptic_curve::sec1::ToEncodedPoint; + +#[derive(Debug, thiserror::Error)] +pub enum PublicKeyError { + Decode(String), +} + +impl Display for PublicKeyError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + +/// Decompresses public key of secp256k1 if it was compressed +/// +/// Public key can be expressed in compressed or decompressed forms. +/// Compressed form contains one byte as prefix and x component of the public key. +/// Decompressed form contains one byte as prefix, x and y components of the public key. +pub fn decompress_public_key(public_key: &[u8]) -> Result, PublicKeyError> { + let elliptic: elliptic_curve::PublicKey = + elliptic_curve::PublicKey::from_sec1_bytes(public_key) + .map_err(|e| PublicKeyError::Decode(e.to_string()))?; + + // if public key was compressed, encoding into the point will decompress it. + let point = elliptic.to_encoded_point(false); + let decompressed = point.to_bytes().to_vec(); + Ok(decompressed) +} + +#[cfg(test)] +mod tests { + use crate::key::decompress_public_key; + + #[test] + fn test_decompress_public_key() { + // given + let compressed = "02962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f4"; + let hex = hex::decode(compressed).unwrap(); + + // when + let decompressed = hex::encode(decompress_public_key(&hex).unwrap()); + + // then + assert_eq!( + "04962d010010b6eec66846322704181570d89e28236796579c535d2e44d20931f40cb1152fb9e61ec7493a0d9a35d2e8a57198e109613854abdd3be5603d504008", + decompressed + ); + } +} diff --git a/rust/main/utils/crypto/src/lib.rs b/rust/main/utils/crypto/src/lib.rs new file mode 100644 index 000000000..edd7a4f4d --- /dev/null +++ b/rust/main/utils/crypto/src/lib.rs @@ -0,0 +1,4 @@ +pub use key::decompress_public_key; +pub use key::PublicKeyError; + +mod key; From 92c86cca66e49a8ad7a8401cfcdb8fead3244593 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Tue, 8 Oct 2024 12:39:44 -0400 Subject: [PATCH 111/224] fix: forward value from ICA router to proxies (#4395) ### Description Value sent to the hyperlane message recipient (InterchainAccountRouter) would not be forwarded to the proxy account for use in calls with value. Only value sent to the proxy account was supported. ### Related Issues - Fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/4 ### Backward compatibility No, ICA routers would need upgrade/redeploy ### Testing Unit Tests --- .changeset/bright-planets-march.md | 5 + .../middleware/InterchainAccountRouter.sol | 2 +- .../middleware/libs/OwnableMulticall.sol | 4 +- .../mock/MockHyperlaneEnvironment.sol | 6 +- solidity/contracts/mock/MockMailbox.sol | 4 +- solidity/test/InterchainAccountRouter.t.sol | 108 ++++++++++++------ 6 files changed, 89 insertions(+), 40 deletions(-) create mode 100644 .changeset/bright-planets-march.md diff --git a/.changeset/bright-planets-march.md b/.changeset/bright-planets-march.md new file mode 100644 index 000000000..6a2d2ab16 --- /dev/null +++ b/.changeset/bright-planets-march.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': patch +--- + +Forward value from ICA router to proxy for multicall diff --git a/solidity/contracts/middleware/InterchainAccountRouter.sol b/solidity/contracts/middleware/InterchainAccountRouter.sol index 0c2277648..3980ac29b 100644 --- a/solidity/contracts/middleware/InterchainAccountRouter.sol +++ b/solidity/contracts/middleware/InterchainAccountRouter.sol @@ -307,7 +307,7 @@ contract InterchainAccountRouter is Router { _sender, _ism.bytes32ToAddress() ); - _interchainAccount.multicall(_calls); + _interchainAccount.multicall{value: msg.value}(_calls); } /** diff --git a/solidity/contracts/middleware/libs/OwnableMulticall.sol b/solidity/contracts/middleware/libs/OwnableMulticall.sol index ad67af036..981d7d35d 100644 --- a/solidity/contracts/middleware/libs/OwnableMulticall.sol +++ b/solidity/contracts/middleware/libs/OwnableMulticall.sol @@ -20,7 +20,9 @@ contract OwnableMulticall { _; } - function multicall(CallLib.Call[] calldata calls) external onlyOwner { + function multicall( + CallLib.Call[] calldata calls + ) external payable onlyOwner { return CallLib.multicall(calls); } diff --git a/solidity/contracts/mock/MockHyperlaneEnvironment.sol b/solidity/contracts/mock/MockHyperlaneEnvironment.sol index 583023cf9..9f28a1c31 100644 --- a/solidity/contracts/mock/MockHyperlaneEnvironment.sol +++ b/solidity/contracts/mock/MockHyperlaneEnvironment.sol @@ -38,8 +38,10 @@ contract MockHyperlaneEnvironment { mailboxes[_destinationDomain] = destinationMailbox; } - function processNextPendingMessage() public { - mailboxes[destinationDomain].processNextInboundMessage(); + function processNextPendingMessage() public payable { + mailboxes[destinationDomain].processNextInboundMessage{ + value: msg.value + }(); } function processNextPendingMessageFromDestination() public { diff --git a/solidity/contracts/mock/MockMailbox.sol b/solidity/contracts/mock/MockMailbox.sol index 68fefc521..ad212dcef 100644 --- a/solidity/contracts/mock/MockMailbox.sol +++ b/solidity/contracts/mock/MockMailbox.sol @@ -72,9 +72,9 @@ contract MockMailbox is Mailbox { inboundUnprocessedNonce++; } - function processNextInboundMessage() public { + function processNextInboundMessage() public payable { bytes memory _message = inboundMessages[inboundProcessedNonce]; - Mailbox(address(this)).process("", _message); + Mailbox(address(this)).process{value: msg.value}("", _message); inboundProcessedNonce++; } } diff --git a/solidity/test/InterchainAccountRouter.t.sol b/solidity/test/InterchainAccountRouter.t.sol index fecfe96a4..d091bfe26 100644 --- a/solidity/test/InterchainAccountRouter.t.sol +++ b/solidity/test/InterchainAccountRouter.t.sol @@ -16,9 +16,11 @@ import {InterchainAccountIsm} from "../contracts/isms/routing/InterchainAccountI contract Callable { mapping(address => bytes32) public data; + mapping(address => uint256) public value; - function set(bytes32 _data) external { + function set(bytes32 _data) external payable { data[msg.sender] = _data; + value[msg.sender] = msg.value; } } @@ -298,13 +300,14 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { } function getCalls( - bytes32 data + bytes32 data, + uint256 value ) private view returns (CallLib.Call[] memory) { vm.assume(data != bytes32(0)); CallLib.Call memory call = CallLib.Call( TypeCasts.addressToBytes32(address(target)), - 0, + value, abi.encodeCall(target.set, (data)) ); CallLib.Call[] memory calls = new CallLib.Call[](1); @@ -312,8 +315,10 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { return calls; } - function assertRemoteCallReceived(bytes32 data) private { + function assertRemoteCallReceived(bytes32 data, uint256 value) private { assertEq(target.data(address(this)), bytes32(0)); + assertEq(target.value(address(this)), 0); + vm.expectEmit(true, true, false, true, address(destinationIcaRouter)); emit InterchainAccountCreated( origin, @@ -321,8 +326,11 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { TypeCasts.bytes32ToAddress(ismOverride), address(ica) ); - environment.processNextPendingMessage(); + vm.deal(address(this), value); + environment.processNextPendingMessage{value: value}(); + assertEq(target.data(address(ica)), data); + assertEq(target.value(address(ica)), value); } function assertIgpPayment( @@ -384,7 +392,10 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { ); } - function testFuzz_singleCallRemoteWithDefault(bytes32 data) public { + function testFuzz_singleCallRemoteWithDefault( + bytes32 data, + uint256 value + ) public { // arrange originIcaRouter.enrollRemoteRouterAndIsm( destination, @@ -394,7 +405,7 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { uint256 balanceBefore = address(this).balance; // act - CallLib.Call[] memory calls = getCalls(data); + CallLib.Call[] memory calls = getCalls(data, value); originIcaRouter.callRemote{value: gasPaymentQuote}( destination, TypeCasts.bytes32ToAddress(calls[0].to), @@ -404,11 +415,15 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { // assert uint256 balanceAfter = address(this).balance; - assertRemoteCallReceived(data); assertIgpPayment(balanceBefore, balanceAfter, igp.getDefaultGasUsage()); + + assertRemoteCallReceived(data, value); } - function testFuzz_callRemoteWithDefault(bytes32 data) public { + function testFuzz_callRemoteWithDefault( + bytes32 data, + uint256 value + ) public { // arrange originIcaRouter.enrollRemoteRouterAndIsm( destination, @@ -420,16 +435,19 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { // act originIcaRouter.callRemote{value: gasPaymentQuote}( destination, - getCalls(data) + getCalls(data, value) ); // assert uint256 balanceAfter = address(this).balance; - assertRemoteCallReceived(data); + assertRemoteCallReceived(data, value); assertIgpPayment(balanceBefore, balanceAfter, igp.getDefaultGasUsage()); } - function testFuzz_overrideAndCallRemote(bytes32 data) public { + function testFuzz_overrideAndCallRemote( + bytes32 data, + uint256 value + ) public { // arrange originIcaRouter.enrollRemoteRouterAndIsm( destination, @@ -441,20 +459,21 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { // act originIcaRouter.callRemote{value: gasPaymentQuote}( destination, - getCalls(data) + getCalls(data, value) ); // assert uint256 balanceAfter = address(this).balance; - assertRemoteCallReceived(data); + assertRemoteCallReceived(data, value); assertIgpPayment(balanceBefore, balanceAfter, igp.getDefaultGasUsage()); } function testFuzz_callRemoteWithoutDefaults_revert_noRouter( - bytes32 data + bytes32 data, + uint256 value ) public { // assert error - CallLib.Call[] memory calls = getCalls(data); + CallLib.Call[] memory calls = getCalls(data, value); vm.expectRevert(bytes("no router specified for destination")); originIcaRouter.callRemote(destination, calls); } @@ -462,7 +481,8 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { function testFuzz_customMetadata_forIgp( uint64 gasLimit, uint64 overpayment, - bytes32 data + bytes32 data, + uint256 value ) public { // arrange bytes memory metadata = StandardHookMetadata.formatMetadata( @@ -481,20 +501,21 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { // act originIcaRouter.callRemote{ value: gasLimit * igp.gasPrice() + overpayment - }(destination, getCalls(data), metadata); + }(destination, getCalls(data, value), metadata); // assert uint256 balanceAfter = address(this).balance; - assertRemoteCallReceived(data); + assertRemoteCallReceived(data, value); assertIgpPayment(balanceBefore, balanceAfter, gasLimit); } function testFuzz_customMetadata_reverts_underpayment( uint64 gasLimit, uint64 payment, - bytes32 data + bytes32 data, + uint256 value ) public { - CallLib.Call[] memory calls = getCalls(data); + CallLib.Call[] memory calls = getCalls(data, value); vm.assume(payment < gasLimit * igp.gasPrice()); // arrange bytes memory metadata = StandardHookMetadata.formatMetadata( @@ -518,7 +539,10 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { ); } - function testFuzz_callRemoteWithOverrides_default(bytes32 data) public { + function testFuzz_callRemoteWithOverrides_default( + bytes32 data, + uint256 value + ) public { // arrange uint256 balanceBefore = address(this).balance; @@ -527,18 +551,19 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { destination, routerOverride, ismOverride, - getCalls(data) + getCalls(data, value) ); // assert uint256 balanceAfter = address(this).balance; - assertRemoteCallReceived(data); + assertRemoteCallReceived(data, value); assertIgpPayment(balanceBefore, balanceAfter, igp.getDefaultGasUsage()); } function testFuzz_callRemoteWithOverrides_metadata( uint64 gasLimit, - bytes32 data + bytes32 data, + uint256 value ) public { // arrange bytes memory metadata = StandardHookMetadata.formatMetadata( @@ -552,15 +577,24 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { // act originIcaRouter.callRemoteWithOverrides{ value: gasLimit * igp.gasPrice() - }(destination, routerOverride, ismOverride, getCalls(data), metadata); + }( + destination, + routerOverride, + ismOverride, + getCalls(data, value), + metadata + ); // assert uint256 balanceAfter = address(this).balance; - assertRemoteCallReceived(data); + assertRemoteCallReceived(data, value); assertIgpPayment(balanceBefore, balanceAfter, gasLimit); } - function testFuzz_callRemoteWithFailingIsmOverride(bytes32 data) public { + function testFuzz_callRemoteWithFailingIsmOverride( + bytes32 data, + uint256 value + ) public { // arrange string memory failureMessage = "failing ism"; bytes32 failingIsm = TypeCasts.addressToBytes32( @@ -572,7 +606,7 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { destination, routerOverride, failingIsm, - getCalls(data), + getCalls(data, value), "" ); @@ -581,7 +615,10 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { environment.processNextPendingMessage(); } - function testFuzz_callRemoteWithFailingDefaultIsm(bytes32 data) public { + function testFuzz_callRemoteWithFailingDefaultIsm( + bytes32 data, + uint256 value + ) public { // arrange string memory failureMessage = "failing ism"; FailingIsm failingIsm = new FailingIsm(failureMessage); @@ -592,7 +629,7 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { destination, routerOverride, bytes32(0), - getCalls(data), + getCalls(data, value), "" ); @@ -601,7 +638,10 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { environment.processNextPendingMessage(); } - function testFuzz_getLocalInterchainAccount(bytes32 data) public { + function testFuzz_getLocalInterchainAccount( + bytes32 data, + uint256 value + ) public { // check OwnableMulticall destinationIca = destinationIcaRouter .getLocalInterchainAccount( @@ -628,12 +668,12 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { destination, routerOverride, ismOverride, - getCalls(data), + getCalls(data, value), "" ); // recheck - assertRemoteCallReceived(data); + assertRemoteCallReceived(data, value); assert(address(destinationIca).code.length != 0); } From 40fa920c086f5a7cb69bd85ce44c8cd19a33dc18 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:50:14 -0400 Subject: [PATCH 112/224] feat: Update Renzo script to deploy Taiko (#4638) --- .../warp/configGetters/getRenzoEZETHWarpConfig.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts index fdb00d30a..10cca7fc6 100644 --- a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts @@ -26,6 +26,7 @@ const chainsToDeploy = [ 'ethereum', 'fraxtal', 'zircuit', + 'taiko', ]; export const ezEthValidators = { @@ -99,6 +100,13 @@ export const ezEthValidators = { '0x7ac6584c068eb2a72d4db82a7b7cd5ab34044061', // luganodes ], }, + taiko: { + threshold: 1, + validators: [ + '0x2f007c82672f2bb97227d4e3f80ac481bfb40a2a', // luganodes + '0xd4F6000d8e1108bd4998215d51d5dF559BdB43a1', // Renzo + ], + }, }; export const ezEthSafes: Record = { @@ -112,6 +120,7 @@ export const ezEthSafes: Record = { ethereum: '0xD1e6626310fD54Eceb5b9a51dA2eC329D6D4B68A', fraxtal: '0x8410927C286A38883BC23721e640F31D3E3E79F8', zircuit: '0x8410927C286A38883BC23721e640F31D3E3E79F8', + taiko: '0x8410927C286A38883BC23721e640F31D3E3E79F8', }; export const getRenzoEZETHWarpConfig = async (): Promise< From ed77033979d79a8f3e376396b0e67a7a8fa56d4d Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:16:08 -0400 Subject: [PATCH 113/224] fix(cli): rollback gnosis tx builder protocol type (#4650) ### Description This rollsback the added ProtocolType for Gnosis safe which was added only for typing. Replace with `any` and will revisit ### Backward compatibility Yes ### Testing None --- typescript/sdk/src/providers/ProviderType.ts | 21 ------------------- .../sdk/src/providers/providerBuilders.ts | 1 - .../ethersV5/EV5GnosisSafeTxBuilder.ts | 13 ++++++++---- typescript/sdk/src/token/TokenStandard.ts | 1 - typescript/utils/src/types.ts | 1 - 5 files changed, 9 insertions(+), 28 deletions(-) diff --git a/typescript/sdk/src/providers/ProviderType.ts b/typescript/sdk/src/providers/ProviderType.ts index 7f017ab35..c74a9995d 100644 --- a/typescript/sdk/src/providers/ProviderType.ts +++ b/typescript/sdk/src/providers/ProviderType.ts @@ -5,7 +5,6 @@ import type { } from '@cosmjs/cosmwasm-stargate'; import type { EncodeObject as CmTransaction } from '@cosmjs/proto-signing'; import type { DeliverTxResponse, StargateClient } from '@cosmjs/stargate'; -import { SafeTransactionData } from '@safe-global/safe-core-sdk-types'; import type { Connection, Transaction as SolTransaction, @@ -39,7 +38,6 @@ export const PROTOCOL_TO_DEFAULT_PROVIDER_TYPE: Record< ProviderType > = { [ProtocolType.Ethereum]: ProviderType.EthersV5, - [ProtocolType.GnosisTxBuilder]: ProviderType.EthersV5, [ProtocolType.Sealevel]: ProviderType.SolanaWeb3, [ProtocolType.Cosmos]: ProviderType.CosmJsWasm, }; @@ -53,12 +51,6 @@ type ProtocolTypesMapping = { contract: EthersV5Contract; receipt: EthersV5TransactionReceipt; }; - [ProtocolType.GnosisTxBuilder]: { - transaction: EthersV5Transaction; - provider: EthersV5Provider; - contract: EthersV5Contract; - receipt: GnosisTransactionBuilderReceipt; - }; [ProtocolType.Sealevel]: { transaction: SolanaWeb3Transaction; provider: SolanaWeb3Provider; @@ -267,19 +259,6 @@ export interface CosmJsTransactionReceipt receipt: DeliverTxResponse; } -export interface GnosisTransactionBuilderReceipt - extends TypedTransactionReceiptBase { - type: ProviderType.GnosisTxBuilder; - receipt: GnosisTransactionBuilderPayload; -} - -export interface GnosisTransactionBuilderPayload { - version: string; - chainId: string; - meta: {}; - transactions: SafeTransactionData[]; -} - export interface CosmJsWasmTransactionReceipt extends TypedTransactionReceiptBase { type: ProviderType.CosmJsWasm; diff --git a/typescript/sdk/src/providers/providerBuilders.ts b/typescript/sdk/src/providers/providerBuilders.ts index 2be4100ee..bc8051b1b 100644 --- a/typescript/sdk/src/providers/providerBuilders.ts +++ b/typescript/sdk/src/providers/providerBuilders.ts @@ -135,7 +135,6 @@ export const protocolToDefaultProviderBuilder: Record< ProviderBuilderFn > = { [ProtocolType.Ethereum]: defaultEthersV5ProviderBuilder, - [ProtocolType.GnosisTxBuilder]: defaultEthersV5ProviderBuilder, [ProtocolType.Sealevel]: defaultSolProviderBuilder, [ProtocolType.Cosmos]: defaultCosmJsWasmProviderBuilder, }; diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts index e3f90f61c..e9a3ecb7e 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts @@ -6,13 +6,20 @@ import { assert } from '@hyperlane-xyz/utils'; // @ts-ignore import { getSafe, getSafeService } from '../../../../utils/gnosisSafe.js'; import { MultiProvider } from '../../../MultiProvider.js'; -import { GnosisTransactionBuilderPayload } from '../../../ProviderType.js'; import { PopulatedTransaction, PopulatedTransactions } from '../../types.js'; import { TxSubmitterType } from '../TxSubmitterTypes.js'; import { EV5GnosisSafeTxSubmitter } from './EV5GnosisSafeTxSubmitter.js'; import { EV5GnosisSafeTxBuilderProps } from './types.js'; +// TODO: Use this return type in submit() +export interface GnosisTransactionBuilderPayload { + version: string; + chainId: string; + meta: {}; + transactions: SafeTransactionData[]; +} + /** * This class is used to create a Safe Transaction Builder compatible object. * It is not a true Submitter because it does not submits any transactions. @@ -51,9 +58,7 @@ export class EV5GnosisSafeTxBuilder extends EV5GnosisSafeTxSubmitter { * * @param txs - An array of populated transactions */ - public async submit( - ...txs: PopulatedTransactions - ): Promise { + public async submit(...txs: PopulatedTransactions): Promise { const transactions: SafeTransactionData[] = await Promise.all( txs.map( async (tx: PopulatedTransaction) => diff --git a/typescript/sdk/src/token/TokenStandard.ts b/typescript/sdk/src/token/TokenStandard.ts index 85ef6e6d5..002501d32 100644 --- a/typescript/sdk/src/token/TokenStandard.ts +++ b/typescript/sdk/src/token/TokenStandard.ts @@ -159,7 +159,6 @@ export const TOKEN_TYPE_TO_STANDARD: Record = { export const PROTOCOL_TO_NATIVE_STANDARD: Record = { [ProtocolType.Ethereum]: TokenStandard.EvmNative, - [ProtocolType.GnosisTxBuilder]: TokenStandard.EvmNative, [ProtocolType.Cosmos]: TokenStandard.CosmosNative, [ProtocolType.Sealevel]: TokenStandard.SealevelNative, }; diff --git a/typescript/utils/src/types.ts b/typescript/utils/src/types.ts index 7261e4904..3d79f0058 100644 --- a/typescript/utils/src/types.ts +++ b/typescript/utils/src/types.ts @@ -5,7 +5,6 @@ export enum ProtocolType { Ethereum = 'ethereum', Sealevel = 'sealevel', Cosmos = 'cosmos', - GnosisTxBuilder = 'gnosisTxBuilder', } // A type that also allows for literal values of the enum export type ProtocolTypeValue = `${ProtocolType}`; From ad4d61f962014fe5e9185eb5efb7b1375c97d4cb Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:38:11 +0100 Subject: [PATCH 114/224] chore: agave 2.x validator in sealevel e2e (#4643) ### Description Solana Mainnet is hard forking in 1-2 weeks and one of the RPC methods we were using will be removed. This PR updates that RPC and runs e2e with an agave `v2.x` network to ensure compatibility. As in the [svm warp route guide](https://docs.hyperlane.xyz/docs/guides/deploy-svm-warp-route), we still use `v1.14.x` to compile programs. More details: - `v2.0` migration [guide](https://github.com/anza-xyz/agave/wiki/Agave-v2.0-Transition-Guide) - `v2.0` release [schedule](https://github.com/anza-xyz/agave/wiki/v2.0-Release-Schedule) - `solana` to `agave` client transition [guide](https://github.com/anza-xyz/agave/wiki/Agave-Transition) ### Drive-by changes The solana cli installer logic in e2e is parameterized with `version` and `url` ### Backward compatibility Yes - no dependency upgrade was needed to switch to the new rpc method ### Testing E2E for general network compatiblity. The Jito submission retry logic (where the new rpc is used) wasn't tested - I'm confident it works but this is non-critical, as failed submission will eventually end up in the prep queue again --- .../chains/hyperlane-sealevel/src/mailbox.rs | 15 +++++------ rust/main/utils/run-locally/src/main.rs | 16 +++++++++--- rust/main/utils/run-locally/src/solana.rs | 25 +++++++++++++++---- rust/sealevel/client/src/cmd_utils.rs | 6 +++++ rust/sealevel/client/src/main.rs | 3 ++- 5 files changed, 49 insertions(+), 16 deletions(-) diff --git a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs index e919b2de7..f101435c2 100644 --- a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs @@ -33,6 +33,7 @@ use solana_client::{ rpc_client::SerializableTransaction, rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcSendTransactionConfig}, rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType}, + rpc_response::Response, }; use solana_sdk::{ account::Account, @@ -48,7 +49,7 @@ use solana_sdk::{ transaction::{Transaction, VersionedTransaction}, }; use solana_transaction_status::{ - EncodedConfirmedBlock, EncodedTransaction, EncodedTransactionWithStatusMeta, + EncodedConfirmedBlock, EncodedTransaction, EncodedTransactionWithStatusMeta, TransactionStatus, UiInnerInstructions, UiInstruction, UiMessage, UiParsedInstruction, UiReturnDataEncoding, UiTransaction, UiTransactionReturnData, UiTransactionStatusMeta, }; @@ -354,15 +355,15 @@ impl SealevelMailbox { }; for status_retry in 0..GET_STATUS_RETRIES { - match self + let signature_statuses: Response>> = self .provider .rpc() - .get_signature_status(&signature) + .get_signature_statuses(&[*signature]) .await - .map_err(ChainCommunicationError::from_other)? - { - Some(Ok(_)) => return Ok(*signature), - Some(Err(e)) => return Err(ChainCommunicationError::from_other(e)), + .map_err(ChainCommunicationError::from_other)?; + let signature_status = signature_statuses.value.first().cloned().flatten(); + match signature_status { + Some(_) => return Ok(*signature), None => { if !self .provider diff --git a/rust/main/utils/run-locally/src/main.rs b/rust/main/utils/run-locally/src/main.rs index 65ff63199..ac9166063 100644 --- a/rust/main/utils/run-locally/src/main.rs +++ b/rust/main/utils/run-locally/src/main.rs @@ -313,7 +313,11 @@ fn main() -> ExitCode { // let solana_paths = if config.sealevel_enabled { - let (solana_path, solana_path_tempdir) = install_solana_cli_tools().join(); + let (solana_path, solana_path_tempdir) = install_solana_cli_tools( + SOLANA_CONTRACTS_CLI_RELEASE_URL.to_owned(), + SOLANA_CONTRACTS_CLI_VERSION.to_owned(), + ) + .join(); state.data.push(Box::new(solana_path_tempdir)); let solana_program_builder = build_solana_programs(solana_path.clone()); Some((solana_program_builder.join(), solana_path)) @@ -358,8 +362,14 @@ fn main() -> ExitCode { } let solana_ledger_dir = tempdir().unwrap(); - let solana_config_path = if let Some((solana_program_path, solana_path)) = solana_paths.clone() - { + let solana_config_path = if let Some((solana_program_path, _)) = solana_paths.clone() { + // use the agave 2.x validator version to ensure mainnet compatibility + let (solana_path, solana_path_tempdir) = install_solana_cli_tools( + SOLANA_NETWORK_CLI_RELEASE_URL.to_owned(), + SOLANA_NETWORK_CLI_VERSION.to_owned(), + ) + .join(); + state.data.push(Box::new(solana_path_tempdir)); let start_solana_validator = start_solana_test_validator( solana_path.clone(), solana_program_path, diff --git a/rust/main/utils/run-locally/src/solana.rs b/rust/main/utils/run-locally/src/solana.rs index e3c8956b7..022d086a6 100644 --- a/rust/main/utils/run-locally/src/solana.rs +++ b/rust/main/utils/run-locally/src/solana.rs @@ -13,8 +13,14 @@ use crate::program::Program; use crate::utils::{as_task, concat_path, AgentHandles, ArbitraryData, TaskHandle}; use crate::SOLANA_AGNET_BIN_PATH; -/// The Solana CLI tool version to download and use. -const SOLANA_CLI_VERSION: &str = "1.14.20"; +/// Solana CLI version for compiling programs +pub const SOLANA_CONTRACTS_CLI_VERSION: &str = "1.14.20"; +pub const SOLANA_CONTRACTS_CLI_RELEASE_URL: &str = "github.com/solana-labs/solana"; + +/// Solana version used by mainnet validators +pub const SOLANA_NETWORK_CLI_VERSION: &str = "2.0.13"; +pub const SOLANA_NETWORK_CLI_RELEASE_URL: &str = "github.com/anza-xyz/agave"; + const SOLANA_PROGRAM_LIBRARY_ARCHIVE: &str = "https://github.com/hyperlane-xyz/solana-program-library/releases/download/2024-08-23/spl.tar.gz"; @@ -71,10 +77,17 @@ const SOLANA_OVERHEAD_CONFIG_FILE: &str = "../sealevel/environments/local-e2e/ov // Install the CLI tools and return the path to the bin dir. #[apply(as_task)] -pub fn install_solana_cli_tools() -> (PathBuf, impl ArbitraryData) { +pub fn install_solana_cli_tools( + release_url: String, + release_version: String, +) -> (PathBuf, impl ArbitraryData) { let solana_download_dir = tempdir().unwrap(); let solana_tools_dir = tempdir().unwrap(); - log!("Downloading solana cli release v{}", SOLANA_CLI_VERSION); + log!( + "Downloading solana cli release v{} from {}", + release_version, + release_url + ); let solana_release_name = { // best effort to pick one of the supported targets let target = if cfg!(target_os = "linux") { @@ -97,7 +110,9 @@ pub fn install_solana_cli_tools() -> (PathBuf, impl ArbitraryData) { Program::new("curl") .arg("output", &solana_archive_name) .flag("location") - .cmd(format!("https://github.com/solana-labs/solana/releases/download/v{SOLANA_CLI_VERSION}/{solana_archive_name}")) + .cmd(format!( + "https://{release_url}/releases/download/v{release_version}/{solana_archive_name}" + )) .flag("silent") .working_dir(solana_download_dir.as_ref().to_str().unwrap()) .run() diff --git a/rust/sealevel/client/src/cmd_utils.rs b/rust/sealevel/client/src/cmd_utils.rs index 872725112..e0cd3ff68 100644 --- a/rust/sealevel/client/src/cmd_utils.rs +++ b/rust/sealevel/client/src/cmd_utils.rs @@ -4,6 +4,8 @@ use std::{ io::Write, path::{Path, PathBuf}, process::{Command, Stdio}, + thread::sleep, + time::Duration, }; use solana_client::{client_error::ClientError, rpc_client::RpcClient}; @@ -77,6 +79,10 @@ pub(crate) fn deploy_program( } build_cmd(command.as_slice(), None, None); + + // TODO: use commitment level instead of just sleeping here? + println!("Sleeping for 2 seconds to allow program to be deployed"); + sleep(Duration::from_secs(2)); } pub(crate) fn create_new_directory(parent_dir: &Path, name: &str) -> PathBuf { diff --git a/rust/sealevel/client/src/main.rs b/rust/sealevel/client/src/main.rs index 8e9f3e586..bf014785c 100644 --- a/rust/sealevel/client/src/main.rs +++ b/rust/sealevel/client/src/main.rs @@ -895,7 +895,7 @@ fn process_mailbox_cmd(ctx: Context, cmd: MailboxCmd) { }; } -fn process_token_cmd(ctx: Context, cmd: TokenCmd) { +fn process_token_cmd(mut ctx: Context, cmd: TokenCmd) { match cmd.cmd { TokenSubCmd::Query(query) => { let (token_account, token_bump) = @@ -1024,6 +1024,7 @@ fn process_token_cmd(ctx: Context, cmd: TokenCmd) { } TokenSubCmd::TransferRemote(xfer) => { is_keypair(&xfer.sender).unwrap(); + ctx.commitment = CommitmentConfig::finalized(); let sender = read_keypair_file(xfer.sender).unwrap(); let recipient = if xfer.recipient.starts_with("0x") { From 3254472e02d5b62e422c3f89da617f6f33b53408 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:48:45 +0100 Subject: [PATCH 115/224] feat: sept 30 mainnet batch (#4613) ### Description Deploy to immutablezkevm rari rootstock alephzeroevm chiliz lumia superposition ### Drive-by changes - fix igp defaults - helper for updating agent configs + running prettier ### Related issues na ### Backward compatibility ye ### Testing manual --- .changeset/early-dots-serve.md | 5 + .registryrc | 2 +- package.json | 1 + rust/main/config/mainnet_config.json | 470 ++++++++++++++ rust/main/config/testnet_config.json | 32 +- .../config/environments/mainnet3/agent.ts | 33 +- .../mainnet3/aw-validators/hyperlane.json | 21 + .../config/environments/mainnet3/chains.ts | 5 + .../mainnet3/core/verification.json | 532 ++++++++++++++++ .../config/environments/mainnet3/funding.ts | 9 +- .../environments/mainnet3/gasPrices.json | 90 ++- .../infra/config/environments/mainnet3/igp.ts | 2 +- .../mainnet3/ism/verification.json | 602 ++++++++++++++++++ .../middleware/accounts/verification.json | 147 +++++ .../mainnet3/supportedChainNames.ts | 7 + .../mainnet3/testrecipient/verification.json | 8 + .../environments/mainnet3/tokenPrices.json | 129 ++-- .../environments/mainnet3/validators.ts | 71 +++ typescript/infra/config/environments/utils.ts | 66 +- typescript/infra/src/config/gas-oracle.ts | 11 +- typescript/sdk/src/consts/multisigIsm.ts | 35 + 21 files changed, 2139 insertions(+), 139 deletions(-) create mode 100644 .changeset/early-dots-serve.md diff --git a/.changeset/early-dots-serve.md b/.changeset/early-dots-serve.md new file mode 100644 index 000000000..24e3a51f5 --- /dev/null +++ b/.changeset/early-dots-serve.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Add deployments for chains: immutablezkevm, rari, rootstock, alephzeroevm, chiliz, lumia, and superposition diff --git a/.registryrc b/.registryrc index 2c81d3cdd..92dafe4b6 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -a87a555d19834d6d3dada72ccdcb3661ba9ff003 +8afda069c23f8974a8679d666942be509ed64dad diff --git a/package.json b/package.json index 36ea71a2a..072ac6c78 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "packageManager": "yarn@4.0.2", "private": true, "scripts": { + "agent-configs": "yarn --cwd typescript/infra/ update-agent-config:mainnet3 && yarn --cwd typescript/infra/ update-agent-config:testnet4 && yarn prettier", "build": "yarn workspaces foreach --all --parallel --topological run build", "clean": "yarn workspaces foreach --all --parallel run clean", "prettier": "yarn workspaces foreach --since --parallel run prettier", diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index 9a2257b5f..aef06b31a 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -4057,6 +4057,476 @@ "index": { "from": 26847587 } + }, + "alephzeroevm": { + "blockExplorers": [ + { + "apiUrl": "https://evm-explorer.alephzero.org/api", + "family": "blockscout", + "name": "Aleph Zero Explorer", + "url": "https://evm-explorer.alephzero.org" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 1 + }, + "chainId": 41455, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Aleph Zero EVM", + "displayNameShort": "Aleph Zero EVM", + "domainId": 41455, + "gasCurrencyCoinGeckoId": "aleph-zero", + "index": { + "from": 3421962 + }, + "name": "alephzeroevm", + "nativeToken": { + "decimals": 18, + "name": "AZERO", + "symbol": "AZERO" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.alephzero.raas.gelato.cloud" + }, + { + "http": "https://alephzero.drpc.org" + } + ], + "technicalStack": "arbitrumnitro", + "aggregationHook": "0x66b3b9f399d415Bd6CcC94407deB2AB86750Cac2", + "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", + "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "pausableIsm": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "protocolFee": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticAggregationIsm": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "storageGasOracle": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "testRecipient": "0x989B7307d266151BE763935C856493D968b2affF", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76" + }, + "chiliz": { + "blockExplorers": [ + { + "apiUrl": "https://api.routescan.io/v2/network/mainnet/evm/88888/etherscan/api", + "family": "routescan", + "name": "Chiliscan", + "url": "https://chiliscan.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 1 + }, + "chainId": 88888, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Chiliz", + "domainId": 88888, + "gasCurrencyCoinGeckoId": "chiliz", + "name": "chiliz", + "nativeToken": { + "decimals": 18, + "name": "Chiliz", + "symbol": "CHZ" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.ankr.com/chiliz" + }, + { + "http": "https://chiliz.publicnode.com" + } + ], + "aggregationHook": "0x66b3b9f399d415Bd6CcC94407deB2AB86750Cac2", + "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", + "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "pausableIsm": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "protocolFee": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticAggregationIsm": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "storageGasOracle": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "testRecipient": "0x989B7307d266151BE763935C856493D968b2affF", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "index": { + "from": 17051552 + } + }, + "immutablezkevm": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.immutable.com/api/eth-rpc", + "family": "blockscout", + "name": "Immutable Explorer", + "url": "https://explorer.immutable.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 13371, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Immutable zkEVM", + "domainId": 13371, + "gasCurrencyCoinGeckoId": "immutable-x", + "name": "immutablezkevm", + "nativeToken": { + "decimals": 18, + "name": "Immutable", + "symbol": "IMX" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.immutable.com" + }, + { + "http": "https://immutable.gateway.tenderly.co" + } + ], + "aggregationHook": "0x66b3b9f399d415Bd6CcC94407deB2AB86750Cac2", + "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", + "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "pausableIsm": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "protocolFee": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticAggregationIsm": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "storageGasOracle": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "testRecipient": "0x989B7307d266151BE763935C856493D968b2affF", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "index": { + "from": 12797545 + }, + "transactionOverrides": { + "maxPriorityFeePerGas": 100000000000, + "maxFeePerGas": 100000000000 + } + }, + "lumia": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.lumia.org/api/eth-rpc", + "family": "blockscout", + "name": "Lumia Prism Explorer", + "url": "https://explorer.lumia.org" + } + ], + "blocks": { + "confirmations": 3, + "estimateBlockTime": 4, + "reorgPeriod": 1 + }, + "chainId": 994873017, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Lumia Prism", + "domainId": 994873017, + "gasCurrencyCoinGeckoId": "orion-protocol", + "name": "lumia", + "nativeToken": { + "decimals": 18, + "name": "Lumia", + "symbol": "LUMIA" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://994873017.rpc.thirdweb.com" + }, + { + "http": "https://mainnet-rpc.lumia.org" + } + ], + "aggregationHook": "0x2F4cf1a8DBDb31689BD62695029362C821401BA9", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "interchainAccountIsm": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainAccountRouter": "0xC9c1A8E0d7A389ff4E3A5ab1C3F9555c50BaD325", + "interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "interchainSecurityModule": "0x68ec44d6aB0dE138eaA159D74C5A2b473919f3df", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "pausableIsm": "0x5d69BC38eF3eDb491c0b7186BEc4eC45c4013f93", + "protocolFee": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x68ec44d6aB0dE138eaA159D74C5A2b473919f3df", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "testRecipient": "0xf7D882A816D4845BB221Ceb03CE531d1e7645F60", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x989B7307d266151BE763935C856493D968b2affF", + "index": { + "from": 1923136 + } + }, + "rari": { + "blockExplorers": [ + { + "apiUrl": "https://mainnet.explorer.rarichain.org/api", + "family": "blockscout", + "name": "Rari Mainnet Explorer", + "url": "https://mainnet.explorer.rarichain.org" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 1380012617, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "RARI Chain", + "domainId": 1380012617, + "gasCurrencyCoinGeckoId": "ethereum", + "index": { + "from": 541753 + }, + "name": "rari", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet.rpc.rarichain.org/http" + } + ], + "technicalStack": "arbitrumnitro", + "aggregationHook": "0x66b3b9f399d415Bd6CcC94407deB2AB86750Cac2", + "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", + "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "pausableIsm": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "protocolFee": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticAggregationIsm": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "storageGasOracle": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "testRecipient": "0x989B7307d266151BE763935C856493D968b2affF", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76" + }, + "rootstock": { + "blockExplorers": [ + { + "apiUrl": "https://rootstock.blockscout.com/api", + "family": "blockscout", + "name": "Blockscout", + "url": "https://rootstock.blockscout.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 30, + "reorgPeriod": 4 + }, + "chainId": 30, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Rootstock", + "domainId": 30, + "gasCurrencyCoinGeckoId": "rootstock", + "name": "rootstock", + "nativeToken": { + "decimals": 18, + "name": "Rootstock Smart Bitcoin", + "symbol": "RBTC" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.mainnet.rootstock.io/kXhXHf6TnnfW1POvr4UT0YUvujmuju-M" + }, + { + "http": "https://public-node.rsk.co" + }, + { + "http": "https://mycrypto.rsk.co" + } + ], + "transactionOverrides": { + "gasPrice": 70000000 + }, + "aggregationHook": "0xA530b21B2c1517ceFcAAE890c7f8A167e4C0f51E", + "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", + "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "fallbackRoutingHook": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "interchainAccountIsm": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainAccountRouter": "0xC9c1A8E0d7A389ff4E3A5ab1C3F9555c50BaD325", + "interchainGasPaymaster": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", + "interchainSecurityModule": "0x3D409C61721f9D5558A3AdfA45A215C795533377", + "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "merkleTreeHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "pausableHook": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", + "pausableIsm": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "protocolFee": "0x989B7307d266151BE763935C856493D968b2affF", + "proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticAggregationIsm": "0x3D409C61721f9D5558A3AdfA45A215C795533377", + "staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "storageGasOracle": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918", + "testRecipient": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "index": { + "from": 6749741 + } + }, + "superposition": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.superposition.so/api", + "family": "blockscout", + "name": "Superposition Explorer", + "url": "https://explorer.superposition.so/" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 1 + }, + "chainId": 55244, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Superposition", + "domainId": 55244, + "gasCurrencyCoinGeckoId": "ethereum", + "index": { + "from": 1201 + }, + "name": "superposition", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.superposition.so" + } + ], + "technicalStack": "arbitrumnitro", + "aggregationHook": "0x2F4cf1a8DBDb31689BD62695029362C821401BA9", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "interchainAccountIsm": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "interchainAccountRouter": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d", + "interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "interchainSecurityModule": "0x68ec44d6aB0dE138eaA159D74C5A2b473919f3df", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "pausableIsm": "0x5d69BC38eF3eDb491c0b7186BEc4eC45c4013f93", + "protocolFee": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x68ec44d6aB0dE138eaA159D74C5A2b473919f3df", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "testRecipient": "0x71388C9E25BE7b229B5d17Df7D4DB3F7DA7C962d", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x989B7307d266151BE763935C856493D968b2affF" } }, "defaultRpcConsensusType": "fallback" diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index 6f10162a2..bec39173c 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -276,10 +276,10 @@ "aggregationHook": "0x331eb40963dc11F5BB271308c42d97ac6e41F124", "blockExplorers": [ { - "apiUrl": "https://connext-sepolia.blockscout.com/api", + "apiUrl": "https://scan.testnet.everclear.org/api", "family": "blockscout", - "name": "Connext Explorer", - "url": "https://connext-sepolia.blockscout.com" + "name": "Everclear Testnet Explorer", + "url": "https://scan.testnet.everclear.org/" } ], "blocks": { @@ -292,7 +292,7 @@ "name": "Everclear", "url": "https://everclear.org" }, - "displayName": "Connext Sepolia", + "displayName": "Everclear Sepolia", "domainId": 6398, "domainRoutingIsm": "0x4ac19e0bafc2aF6B98094F0a1B817dF196551219", "domainRoutingIsmFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", @@ -956,7 +956,7 @@ { "apiUrl": "https://testnet-explorer.superposition.so/api", "family": "blockscout", - "name": "CatScan", + "name": "Superposition Testnet Explorer", "url": "https://testnet-explorer.superposition.so" } ], @@ -1006,7 +1006,11 @@ "validatorAnnounce": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", "staticMerkleRootWeightedMultisigIsmFactory": "0xE67CfA164cDa449Ae38a0a09391eF6bCDf8e4e2c", "staticMessageIdWeightedMultisigIsmFactory": "0x867f2089D09903f208AeCac84E599B90E5a4A821", - "gasCurrencyCoinGeckoId": "superposition" + "gasCurrencyCoinGeckoId": "superposition", + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + } }, "berabartio": { "blockExplorers": [ @@ -1136,6 +1140,10 @@ "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", "index": { "from": 4591544 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" } }, "citreatestnet": { @@ -1261,6 +1269,10 @@ "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", "index": { "from": 12137144 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" } }, "hyperliquidevmtestnet": { @@ -1385,6 +1397,10 @@ "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", "index": { "from": 2054457 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" } }, "suavetoliman": { @@ -1445,6 +1461,10 @@ "validatorAnnounce": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", "index": { "from": 1921514 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" } }, "test1": { diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 04d2e99fa..532e327e9 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -55,6 +55,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< // Generally, we run all production validators in the Hyperlane context. [Role.Validator]: { ancient8: true, + alephzeroevm: true, arbitrum: true, astar: true, astarzkevm: true, @@ -66,6 +67,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< bsc: true, celo: true, cheesechain: true, + chiliz: true, coredao: true, cyber: true, degenchain: true, @@ -78,12 +80,14 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fraxtal: true, fusemainnet: true, gnosis: true, + immutablezkevm: true, inevm: true, injective: true, kroma: true, linea: true, lisk: true, lukso: true, + lumia: true, mantapacific: true, mantle: true, merlin: true, @@ -99,15 +103,18 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< polygon: true, polygonzkevm: true, proofofplay: true, + rari: true, real: true, redstone: true, + rootstock: true, sanko: true, scroll: true, sei: true, shibarium: true, solanamainnet: true, + superposition: true, taiko: true, - tangle: false, + tangle: true, viction: true, worldchain: true, xai: true, @@ -117,6 +124,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< zoramainnet: true, }, [Role.Relayer]: { + alephzeroevm: true, ancient8: true, arbitrum: true, astar: true, @@ -129,6 +137,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< bsc: true, celo: true, cheesechain: true, + chiliz: true, coredao: true, cyber: true, degenchain: true, @@ -141,12 +150,14 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fraxtal: true, fusemainnet: true, gnosis: true, + immutablezkevm: true, inevm: true, injective: true, kroma: true, linea: true, lisk: true, lukso: true, + lumia: true, mantapacific: true, mantle: true, merlin: true, @@ -163,15 +174,18 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< polygon: true, polygonzkevm: true, proofofplay: true, + rari: true, real: true, redstone: true, + rootstock: true, sanko: true, scroll: true, sei: true, shibarium: true, solanamainnet: true, + superposition: true, taiko: true, - tangle: false, + tangle: true, viction: true, worldchain: true, xai: true, @@ -182,6 +196,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< }, [Role.Scraper]: { ancient8: true, + alephzeroevm: true, arbitrum: true, astar: true, astarzkevm: true, @@ -193,6 +208,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< bsc: true, celo: true, cheesechain: true, + chiliz: true, coredao: true, cyber: true, degenchain: true, @@ -206,6 +222,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fraxtal: true, fusemainnet: true, gnosis: true, + immutablezkevm: true, inevm: true, // Cannot scrape non-EVM chains injective: false, @@ -213,6 +230,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< linea: true, lisk: true, lukso: true, + lumia: true, mantapacific: true, mantle: true, merlin: true, @@ -230,8 +248,10 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< polygon: true, polygonzkevm: true, proofofplay: true, + rari: true, real: true, redstone: true, + rootstock: true, sanko: true, scroll: true, // Out of caution around pointer contracts (https://www.docs.sei.io/dev-interoperability/pointer-contracts) not being compatible @@ -240,8 +260,9 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< shibarium: true, // Cannot scrape non-EVM chains solanamainnet: false, + superposition: true, taiko: true, - tangle: false, + tangle: true, // Has RPC non-compliance that breaks scraping. viction: false, worldchain: true, @@ -393,7 +414,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'bf53f08-20240926-223824', + tag: '6f414af-20241004-131949', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -402,7 +423,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: '9c056c7-20240911-154357', + tag: '6f414af-20241004-131949', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -412,7 +433,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '9c056c7-20240911-154357', + tag: '6f414af-20241004-131949', }, resources: scraperResources, }, diff --git a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json index 2e38a8dd6..5f6881882 100644 --- a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json @@ -2,6 +2,9 @@ "ancient8": { "validators": ["0xbb5842ae0e05215b53df4787a29144efb7e67551"] }, + "alephzeroevm": { + "validators": ["0xcae8fab142adc4e434bb7409e40dd932cc3851aa"] + }, "arbitrum": { "validators": [ "0x4d966438fe9e2b1e7124c87bbb90cb4f0f6c59a1", @@ -55,6 +58,9 @@ "cheesechain": { "validators": ["0x478fb53c6860ae8fc35235ba0d38d49b13128226"] }, + "chiliz": { + "validators": ["0x82d024f453b1a3f3f6606226f06b038da27596f3"] + }, "coredao": { "validators": ["0xbd6e158a3f5830d99d7d2bce192695bc4a148de2"] }, @@ -99,6 +105,9 @@ "0xb93a72cee19402553c9dd7fed2461aebd04e2454" ] }, + "immutablezkevm": { + "validators": ["0xa787c2952a4d22f776ee6e87e828e6f75de24330"] + }, "inevm": { "validators": [ "0xf9e35ee88e4448a3673b4676a4e153e3584a08eb", @@ -121,6 +130,9 @@ "lukso": { "validators": ["0xa5e953701dcddc5b958b5defb677a829d908df6d"] }, + "lumia": { + "validators": ["0x9e283254ed2cd2c80f007348c2822fc8e5c2fa5f"] + }, "mantapacific": { "validators": [ "0x8e668c97ad76d0e28375275c41ece4972ab8a5bc", @@ -190,12 +202,18 @@ "proofofplay": { "validators": ["0xcda40baa71970a06e5f55e306474de5ca4e21c3b"] }, + "rari": { + "validators": ["0x989d6862e09de21337078efbd86843a3eb1133e3"] + }, "real": { "validators": ["0xaebadd4998c70b05ce8715cf0c3cb8862fe0beec"] }, "redstone": { "validators": ["0x1400b9737007f7978d8b4bbafb4a69c83f0641a7"] }, + "rootstock": { + "validators": ["0xcb8e3a72cf427feff27416d0e2ec375a052eaaee"] + }, "sanko": { "validators": ["0x795c37d5babbc44094b084b0c89ed9db9b5fae39"] }, @@ -215,6 +233,9 @@ "solanamainnet": { "validators": ["0x28464752829b3ea59a497fca0bdff575c534c3ff"] }, + "superposition": { + "validators": ["0x5978d0e6afa9270ddb87cff43a8fa7a763a5dfc4"] + }, "taiko": { "validators": ["0xa930073c8f2d0b2f7423ea32293e0d1362e65d79"] }, diff --git a/typescript/infra/config/environments/mainnet3/chains.ts b/typescript/infra/config/environments/mainnet3/chains.ts index 7af35defe..b9a8976f7 100644 --- a/typescript/infra/config/environments/mainnet3/chains.ts +++ b/typescript/infra/config/environments/mainnet3/chains.ts @@ -65,6 +65,11 @@ export const chainMetadataOverrides: ChainMap> = { maxPriorityFeePerGas: 50 * 10 ** 9, // 50 gwei }, }, + rootstock: { + transactionOverrides: { + gasPrice: 7 * 10 ** 7, // 0.07 gwei + }, + }, }; export const getRegistry = async (useSecrets = true): Promise => diff --git a/typescript/infra/config/environments/mainnet3/core/verification.json b/typescript/infra/config/environments/mainnet3/core/verification.json index 4c982fd36..0336137d8 100644 --- a/typescript/infra/config/environments/mainnet3/core/verification.json +++ b/typescript/infra/config/environments/mainnet3/core/verification.json @@ -3635,5 +3635,537 @@ "constructorArguments": "000000000000000000000000b129828b9eda48192d0b2db35d0e40dcf51b3594", "isProxy": false } + ], + "alephzeroevm": [ + { + "name": "ProxyAdmin", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000a1ef", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D" + }, + { + "name": "PausableIsm", + "address": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000dab56c5a1efffdd23f6bd1243e457b1575984bc6", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "constructorArguments": "0000000000000000000000002d5918c3602f17937ff982f7bb7110774d3a24ad0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD" + }, + { + "name": "ProtocolFee", + "address": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + } + ], + "superposition": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000d7cc", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x5d69BC38eF3eDb491c0b7186BEc4eC45c4013f93", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000009c44e6b8f0db517c2c3a0478caac5349b614f912", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "constructorArguments": "0000000000000000000000004757bdd68bba8a6d901cec82e61e184ff2986918000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918" + }, + { + "name": "ProtocolFee", + "address": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x989B7307d266151BE763935C856493D968b2affF", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "rari": [ + { + "name": "ProxyAdmin", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000052415249", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D" + }, + { + "name": "PausableIsm", + "address": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000dab56c5a1efffdd23f6bd1243e457b1575984bc6", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "constructorArguments": "0000000000000000000000002d5918c3602f17937ff982f7bb7110774d3a24ad0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD" + }, + { + "name": "ProtocolFee", + "address": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + } + ], + "immutablezkevm": [ + { + "name": "ProxyAdmin", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000343b", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D" + }, + { + "name": "PausableIsm", + "address": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000dab56c5a1efffdd23f6bd1243e457b1575984bc6", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "constructorArguments": "0000000000000000000000002d5918c3602f17937ff982f7bb7110774d3a24ad0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD" + }, + { + "name": "ProtocolFee", + "address": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + } + ], + "lumia": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b4c8eb9", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x5d69BC38eF3eDb491c0b7186BEc4eC45c4013f93", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000009c44e6b8f0db517c2c3a0478caac5349b614f912", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "constructorArguments": "0000000000000000000000004757bdd68bba8a6d901cec82e61e184ff2986918000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918" + }, + { + "name": "ProtocolFee", + "address": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x989B7307d266151BE763935C856493D968b2affF", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "chiliz": [ + { + "name": "ProxyAdmin", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000015b38", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D" + }, + { + "name": "PausableIsm", + "address": "0x662771d29DFf0d7C36bB9BB6d4241a02e77585d9", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000dab56c5a1efffdd23f6bd1243e457b1575984bc6", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x73db9c7430548f399e335f3424e8d56080e9010c", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "constructorArguments": "0000000000000000000000002d5918c3602f17937ff982f7bb7110774d3a24ad0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD" + }, + { + "name": "ProtocolFee", + "address": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + } + ], + "rootstock": [ + { + "name": "ProxyAdmin", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000001e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D" + }, + { + "name": "PausableIsm", + "address": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000053e912b41125d6094590a7dbef1360d3d56eea19", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", + "constructorArguments": "0000000000000000000000009024a3902b542c87a5c4a2b3e15d60b2f087dc3e0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E" + }, + { + "name": "ProtocolFee", + "address": "0x989B7307d266151BE763935C856493D968b2affF", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index 19b385e96..c3dda72d2 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '11fbb13-20240921-100452', + tag: '422876d-20241003-134157', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron @@ -27,6 +27,7 @@ export const keyFunderConfig: KeyFunderConfig< // desired balance config, must be set for each chain desiredBalancePerChain: { ancient8: '0.5', + alephzeroevm: '100', arbitrum: '0.5', astar: '100', astarzkevm: '0.05', @@ -38,6 +39,7 @@ export const keyFunderConfig: KeyFunderConfig< bsc: '5', celo: '3', cheesechain: '50', + chiliz: '200', coredao: '25', cyber: '0.05', degenchain: '100', @@ -49,11 +51,13 @@ export const keyFunderConfig: KeyFunderConfig< fraxtal: '0.2', fusemainnet: '20', gnosis: '5', + immutablezkevm: '25', inevm: '3', kroma: '0.05', linea: '0.2', lisk: '0.05', lukso: '20', + lumia: '1', mantapacific: '0.2', mantle: '20', merlin: '0.002', @@ -67,12 +71,15 @@ export const keyFunderConfig: KeyFunderConfig< polygon: '20', polygonzkevm: '0.5', proofofplay: '0.05', + rari: '0.05', real: '0.1', redstone: '0.2', + rootstock: '0.002', sanko: '2', scroll: '0.5', sei: '50', shibarium: '50', + superposition: '0.05', taiko: '0.2', tangle: '2', viction: '3', diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 01ea5465c..93651372e 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -3,8 +3,12 @@ "amount": "0.001000252", "decimals": 9 }, + "alephzeroevm": { + "amount": "40.0", + "decimals": 9 + }, "arbitrum": { - "amount": "0.1", + "amount": "0.017537", "decimals": 9 }, "astar": { @@ -12,15 +16,15 @@ "decimals": 9 }, "astarzkevm": { - "amount": "0.0562", + "amount": "0.0357", "decimals": 9 }, "avalanche": { - "amount": "43.212830197", + "amount": "25.0", "decimals": 9 }, "base": { - "amount": "0.013571998", + "amount": "0.003185677", "decimals": 9 }, "bitlayer": { @@ -28,7 +32,7 @@ "decimals": 9 }, "blast": { - "amount": "0.5", + "amount": "0.003481616", "decimals": 9 }, "bob": { @@ -36,7 +40,7 @@ "decimals": 9 }, "bsc": { - "amount": "5.0", + "amount": "1.0", "decimals": 9 }, "celo": { @@ -47,6 +51,10 @@ "amount": "1.0", "decimals": 9 }, + "chiliz": { + "amount": "2600.0", + "decimals": 9 + }, "coredao": { "amount": "30.0", "decimals": 9 @@ -64,15 +72,15 @@ "decimals": 9 }, "eclipsemainnet": { - "amount": "0.0000001", - "decimals": 1 + "amount": "0.001", + "decimals": 9 }, "endurance": { - "amount": "1.500000007", + "amount": "3.0756015", "decimals": 9 }, "ethereum": { - "amount": "10", + "amount": "12.537447318", "decimals": 9 }, "everclear": { @@ -88,11 +96,15 @@ "decimals": 9 }, "fusemainnet": { - "amount": "50.0", + "amount": "20.0", "decimals": 9 }, "gnosis": { - "amount": "5.877696928", + "amount": "2.000000007", + "decimals": 9 + }, + "immutablezkevm": { + "amount": "10.00000005", "decimals": 9 }, "inevm": { @@ -108,7 +120,7 @@ "decimals": 9 }, "linea": { - "amount": "0.110844655", + "amount": "0.148525014", "decimals": 9 }, "lisk": { @@ -116,11 +128,15 @@ "decimals": 9 }, "lukso": { - "amount": "2.113054947", + "amount": "0.82770224", + "decimals": 9 + }, + "lumia": { + "amount": "1.0", "decimals": 9 }, "mantapacific": { - "amount": "0.011", + "amount": "0.00129795", "decimals": 9 }, "mantle": { @@ -132,7 +148,7 @@ "decimals": 9 }, "metis": { - "amount": "1.682845607", + "amount": "1.247735823", "decimals": 9 }, "mint": { @@ -140,7 +156,7 @@ "decimals": 9 }, "mode": { - "amount": "0.01", + "amount": "0.001000313", "decimals": 9 }, "molten": { @@ -160,7 +176,7 @@ "decimals": 9 }, "optimism": { - "amount": "0.25", + "amount": "0.051272957", "decimals": 9 }, "osmosis": { @@ -168,23 +184,31 @@ "decimals": 1 }, "polygon": { - "amount": "219.572738168", + "amount": "30.004451589", "decimals": 9 }, "polygonzkevm": { - "amount": "3.95", + "amount": "0.183", "decimals": 9 }, "proofofplay": { "amount": "0.01", "decimals": 9 }, + "rari": { + "amount": "0.03", + "decimals": 9 + }, "real": { - "amount": "0.24", + "amount": "0.022", "decimals": 9 }, "redstone": { - "amount": "0.0003", + "amount": "0.00010005", + "decimals": 9 + }, + "rootstock": { + "amount": "0.07", "decimals": 9 }, "sanko": { @@ -192,20 +216,24 @@ "decimals": 9 }, "scroll": { - "amount": "1.3231", + "amount": "0.042025013", "decimals": 9 }, "sei": { - "amount": "120.0", + "amount": "100.005260996", "decimals": 9 }, "shibarium": { - "amount": "54.30595191", + "amount": "8.558763474", "decimals": 9 }, "solanamainnet": { - "amount": "0.5", - "decimals": 1 + "amount": "0.001", + "decimals": 9 + }, + "superposition": { + "amount": "0.01", + "decimals": 9 }, "taiko": { "amount": "0.050000001", @@ -220,15 +248,15 @@ "decimals": 9 }, "worldchain": { - "amount": "0.002002589", + "amount": "0.001000251", "decimals": 9 }, "xai": { - "amount": "0.23886", + "amount": "0.1", "decimals": 9 }, "xlayer": { - "amount": "9.67", + "amount": "7.52", "decimals": 9 }, "zetachain": { @@ -240,7 +268,7 @@ "decimals": 9 }, "zoramainnet": { - "amount": "0.001000252", + "amount": "0.001000259", "decimals": 9 } } diff --git a/typescript/infra/config/environments/mainnet3/igp.ts b/typescript/infra/config/environments/mainnet3/igp.ts index 2833db1a1..6b0d8fbbc 100644 --- a/typescript/infra/config/environments/mainnet3/igp.ts +++ b/typescript/infra/config/environments/mainnet3/igp.ts @@ -31,7 +31,7 @@ const storageGasOracleConfig: AllStorageGasOracleConfigs = (local, remote) => getTokenExchangeRateFromValues(local, remote, tokenPrices), (local) => parseFloat(tokenPrices[local]), - getOverheadWithOverrides, + (local, remote) => getOverheadWithOverrides(local, remote), ); export const igp: ChainMap = objMap( diff --git a/typescript/infra/config/environments/mainnet3/ism/verification.json b/typescript/infra/config/environments/mainnet3/ism/verification.json index 160c21939..c789ad542 100644 --- a/typescript/infra/config/environments/mainnet3/ism/verification.json +++ b/typescript/infra/config/environments/mainnet3/ism/verification.json @@ -5024,5 +5024,607 @@ "constructorArguments": "", "isProxy": true } + ], + "alephzeroevm": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + } + ], + "superposition": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "rari": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + } + ], + "immutablezkevm": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + } + ], + "lumia": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "chiliz": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + } + ], + "rootstock": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x70032dF7C43e5C3611705C21b1528850ac9ce88A", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0xC17126bfdA167e88ea89847aCC63aaE7FB898CB0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0xb6A3aDDAc0d8bD0B38E17083F70D6B3b6e65967e", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0xe139ceA3397ABfE745B3A4a9f6976A6519754100", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x70296bdA00742EA05A46aAE3B11b16C38134c992", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x8aEA374F73d0b1182A6cdf5Cc9143f777D03b279", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xDE3c6d94dA0b4c066b46eDE6ECf9F10237E8389a", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json index d10e534a6..63e698e48 100644 --- a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json @@ -1199,5 +1199,152 @@ "isProxy": true, "expectedimplementation": "0x376aD181E8cd45eAd5403F78d5A871D08c3c4D77" } + ], + "alephzeroevm": [ + { + "name": "InterchainAccountIsm", + "address": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + } + ], + "rari": [ + { + "name": "InterchainAccountIsm", + "address": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + } + ], + "superposition": [ + { + "name": "InterchainAccountIsm", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d", + "constructorArguments": "0000000000000000000000006fb36672365c7c797028c400a61c58c0ecc53cd2000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f4000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2" + } + ], + "chiliz": [ + { + "name": "InterchainAccountIsm", + "address": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + } + ], + "immutablezkevm": [ + { + "name": "InterchainAccountIsm", + "address": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + } + ], + "lumia": [ + { + "name": "InterchainAccountIsm", + "address": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xC9c1A8E0d7A389ff4E3A5ab1C3F9555c50BaD325", + "constructorArguments": "000000000000000000000000504236da6344e5e144def5653c2b1d0ffd18cb7d000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d569fb1753167312ec5b78526743f2bea027e5d8000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d" + } + ], + "rootstock": [ + { + "name": "InterchainAccountIsm", + "address": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xC9c1A8E0d7A389ff4E3A5ab1C3F9555c50BaD325", + "constructorArguments": "000000000000000000000000504236da6344e5e144def5653c2b1d0ffd18cb7d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d569fb1753167312ec5b78526743f2bea027e5d8000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d" + } ] } diff --git a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts index ec68bab48..71e08134b 100644 --- a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts +++ b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts @@ -2,6 +2,7 @@ // Placing them here instead of adjacent chains file to avoid circular dep export const mainnet3SupportedChainNames = [ 'ancient8', + 'alephzeroevm', 'arbitrum', 'astar', 'astarzkevm', @@ -13,6 +14,7 @@ export const mainnet3SupportedChainNames = [ 'bsc', 'celo', 'cheesechain', + 'chiliz', 'coredao', 'cyber', 'degenchain', @@ -25,12 +27,14 @@ export const mainnet3SupportedChainNames = [ 'fraxtal', 'fusemainnet', 'gnosis', + 'immutablezkevm', 'inevm', 'injective', 'kroma', 'linea', 'lisk', 'lukso', + 'lumia', 'mantapacific', 'mantle', 'merlin', @@ -46,13 +50,16 @@ export const mainnet3SupportedChainNames = [ 'polygon', 'polygonzkevm', 'proofofplay', + 'rari', 'real', 'redstone', + 'rootstock', 'sanko', 'scroll', 'sei', 'shibarium', 'solanamainnet', + 'superposition', 'taiko', 'tangle', 'viction', diff --git a/typescript/infra/config/environments/mainnet3/testrecipient/verification.json b/typescript/infra/config/environments/mainnet3/testrecipient/verification.json index 6003193f5..aa476dffb 100644 --- a/typescript/infra/config/environments/mainnet3/testrecipient/verification.json +++ b/typescript/infra/config/environments/mainnet3/testrecipient/verification.json @@ -94,5 +94,13 @@ "isProxy": false, "name": "TestRecipient" } + ], + "lumia": [ + { + "name": "TestRecipient", + "address": "0xf7D882A816D4845BB221Ceb03CE531d1e7645F60", + "constructorArguments": "", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index 0abb12d06..ec0d19a46 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -1,63 +1,70 @@ { - "ancient8": "2411.78", - "arbitrum": "2411.78", - "astar": "0.058925", - "astarzkevm": "2411.78", - "avalanche": "24.66", - "base": "2411.78", - "bitlayer": "59677", - "blast": "2411.78", - "bob": "2411.78", - "bsc": "552.99", - "celo": "0.444888", - "cheesechain": "0.00192649", - "coredao": "0.936135", - "cyber": "2411.78", - "degenchain": "0.00324113", - "dogechain": "0.107549", - "eclipsemainnet": "2411.78", - "endurance": "2.28", - "ethereum": "2411.78", - "everclear": "2411.78", - "flare": "0.01486694", - "fraxtal": "2389.6", - "fusemainnet": "0.0254922", - "gnosis": "1.011", - "inevm": "19.13", - "injective": "19.13", - "kroma": "2411.78", - "linea": "2411.78", - "lisk": "2411.78", - "lukso": "2.11", - "mantapacific": "2411.78", - "mantle": "0.571121", - "merlin": "59786", - "metis": "31.92", - "mint": "2411.78", - "mode": "2411.78", - "molten": "0.671515", - "moonbeam": "0.170166", - "neutron": "0.368584", - "oortmainnet": "0.091528", - "optimism": "2411.78", - "osmosis": "0.412102", - "polygon": "0.426289", - "polygonzkevm": "2411.78", - "proofofplay": "2411.78", - "real": "2411.78", - "redstone": "2411.78", - "sanko": "34.23", - "scroll": "2411.78", - "sei": "0.304985", - "shibarium": "0.407481", - "solanamainnet": "137.07", - "taiko": "2411.78", - "tangle": "1.001", - "viction": "0.437209", - "worldchain": "2411.78", - "xai": "0.190543", - "xlayer": "40.24", - "zetachain": "0.489689", - "zircuit": "2411.78", - "zoramainnet": "2411.78" + "ancient8": "2311.16", + "alephzeroevm": "0.388993", + "arbitrum": "2311.16", + "astar": "0.057834", + "astarzkevm": "2311.16", + "avalanche": "24.01", + "base": "2311.16", + "bitlayer": "60074", + "blast": "2311.16", + "bob": "2311.16", + "bsc": "535.48", + "celo": "0.62334", + "cheesechain": "0.00302691", + "chiliz": "0.057695", + "coredao": "0.842108", + "cyber": "2311.16", + "degenchain": "0.00679235", + "dogechain": "0.101709", + "eclipsemainnet": "2311.16", + "endurance": "1.91", + "ethereum": "2311.16", + "everclear": "2311.16", + "flare": "0.01584458", + "fraxtal": "2308.24", + "fusemainnet": "0.02806214", + "gnosis": "1.003", + "immutablezkevm": "1.48", + "inevm": "18.76", + "injective": "18.76", + "kroma": "2311.16", + "linea": "2311.16", + "lisk": "2311.16", + "lukso": "1.53", + "lumia": "1.074", + "mantapacific": "2311.16", + "mantle": "0.558701", + "merlin": "59977", + "metis": "32.07", + "mint": "2311.16", + "mode": "2311.16", + "molten": "0.754836", + "moonbeam": "0.155475", + "neutron": "0.364817", + "oortmainnet": "0.122189", + "optimism": "2311.16", + "osmosis": "0.513827", + "polygon": "0.366532", + "polygonzkevm": "2311.16", + "proofofplay": "2311.16", + "rari": "2311.16", + "real": "1", + "redstone": "2311.16", + "rootstock": "60206", + "sanko": "41.68", + "scroll": "2311.16", + "sei": "0.387949", + "shibarium": "0.398162", + "solanamainnet": "134.05", + "superposition": "2311.16", + "taiko": "2311.16", + "tangle": "1", + "viction": "0.352221", + "worldchain": "2311.16", + "xai": "0.176832", + "xlayer": "39.69", + "zetachain": "0.53849", + "zircuit": "2311.16", + "zoramainnet": "2311.16" } diff --git a/typescript/infra/config/environments/mainnet3/validators.ts b/typescript/infra/config/environments/mainnet3/validators.ts index fb0609db2..0e0fd209d 100644 --- a/typescript/infra/config/environments/mainnet3/validators.ts +++ b/typescript/infra/config/environments/mainnet3/validators.ts @@ -896,5 +896,76 @@ export const validatorChainConfig = ( 'oortmainnet', ), }, + + immutablezkevm: { + interval: 5, + reorgPeriod: getReorgPeriod('immutablezkevm'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xa787c2952a4d22f776ee6e87e828e6f75de24330'], + }, + 'immutablezkevm', + ), + }, + rari: { + interval: 5, + reorgPeriod: getReorgPeriod('rari'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x989d6862e09de21337078efbd86843a3eb1133e3'], + }, + 'rari', + ), + }, + rootstock: { + interval: 5, + reorgPeriod: getReorgPeriod('rootstock'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xcb8e3a72cf427feff27416d0e2ec375a052eaaee'], + }, + 'rootstock', + ), + }, + alephzeroevm: { + interval: 5, + reorgPeriod: getReorgPeriod('alephzeroevm'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xcae8fab142adc4e434bb7409e40dd932cc3851aa'], + }, + 'alephzeroevm', + ), + }, + chiliz: { + interval: 5, + reorgPeriod: getReorgPeriod('chiliz'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x82d024f453b1a3f3f6606226f06b038da27596f3'], + }, + 'chiliz', + ), + }, + lumia: { + interval: 5, + reorgPeriod: getReorgPeriod('lumia'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x9e283254ed2cd2c80f007348c2822fc8e5c2fa5f'], + }, + 'lumia', + ), + }, + superposition: { + interval: 5, + reorgPeriod: getReorgPeriod('superposition'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x5978d0e6afa9270ddb87cff43a8fa7a763a5dfc4'], + }, + 'superposition', + ), + }, }; }; diff --git a/typescript/infra/config/environments/utils.ts b/typescript/infra/config/environments/utils.ts index a9286077b..48830ad61 100644 --- a/typescript/infra/config/environments/utils.ts +++ b/typescript/infra/config/environments/utils.ts @@ -21,34 +21,48 @@ export const s3BucketName = ( ) => `${context}-${environment}-${chainName}-validator-${index}`; /** - * - * @param addresses Validator addresses, provided in order of deployment priority - * only the first `count` addresses will be used - * @param context - * @param environment - * @param chain - * @param count Number of validators to use - * @returns + * Creates a validator base config for a single chain + * @param environment The environment name + * @param context The context + * @param chain The chain name + * @param addresses Validator addresses for the chain + * @returns Array of ValidatorBaseConfig for the chain */ -export const validatorBaseConfigsFn = ( +const createChainValidatorBaseConfigs = ( environment: string, context: Contexts, -): (( - addresses: Record, chain: ChainName, -) => ValidatorBaseConfig[]) => { - return (addresses, chain) => { - return addresses[context].map((address, index) => { - const bucketName = s3BucketName(context, environment, chain, index); - return { - name: bucketName, - address, - checkpointSyncer: { - type: CheckpointSyncerType.S3, - bucket: bucketName, - region: s3BucketRegion, - }, - }; - }); - }; + addresses: string[] = [], +): ValidatorBaseConfig[] => { + return addresses.map((address, index) => { + const bucketName = s3BucketName(context, environment, chain, index); + return { + name: bucketName, + address, + checkpointSyncer: { + type: CheckpointSyncerType.S3, + bucket: bucketName, + region: s3BucketRegion, + }, + }; + }); }; + +/** + * Creates validator base configs for a given context and environment + * @param environment The environment name + * @param context The context + * @returns Function to generate ValidatorBaseConfig[] for a specific chain + */ +export const validatorBaseConfigsFn = + (environment: string, context: Contexts) => + ( + addresses: Partial>, + chain: ChainName, + ): ValidatorBaseConfig[] => + createChainValidatorBaseConfigs( + environment, + context, + chain, + addresses[context], + ); diff --git a/typescript/infra/src/config/gas-oracle.ts b/typescript/infra/src/config/gas-oracle.ts index 0f2e45a91..ac3516d10 100644 --- a/typescript/infra/src/config/gas-oracle.ts +++ b/typescript/infra/src/config/gas-oracle.ts @@ -236,16 +236,15 @@ export function getTokenExchangeRateFromValues( // Workaround for chicken-egg dependency problem. // We need to provide some default value here to satisfy the config on initial load, // whilst knowing that it will get overwritten when a script actually gets run. - if (!tokenPrices[local] || !tokenPrices[remote]) { - return BigNumber.from(1); - } - + // We set default token price to 1 to mitigate underflow/overflow errors that occurred + // on some pairings if the exchange rate itself was set to 1. + const defaultValue = '1'; const localValue = ethers.utils.parseUnits( - tokenPrices[local], + tokenPrices[local] ?? defaultValue, TOKEN_EXCHANGE_RATE_DECIMALS, ); const remoteValue = ethers.utils.parseUnits( - tokenPrices[remote], + tokenPrices[remote] ?? defaultValue, TOKEN_EXCHANGE_RATE_DECIMALS, ); diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index a602dd28c..ac68c1f9e 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -3,6 +3,11 @@ import { ChainMap } from '../types.js'; // TODO: consider migrating these to the registry too export const defaultMultisigConfigs: ChainMap = { + alephzeroevm: { + threshold: 1, + validators: ['0xcae8fab142adc4e434bb7409e40dd932cc3851aa'], + }, + alfajores: { threshold: 2, validators: [ @@ -164,6 +169,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + chiliz: { + threshold: 1, + validators: ['0x82d024f453b1a3f3f6606226f06b038da27596f3'], + }, + citreatestnet: { threshold: 1, validators: ['0x60d7380a41eb95c49be18f141efd2fde5e3dba20'], @@ -322,6 +332,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0xea673a92a23ca319b9d85cc16b248645cd5158da'], }, + immutablezkevm: { + threshold: 1, + validators: ['0xa787c2952a4d22f776ee6e87e828e6f75de24330'], + }, + inevm: { threshold: 2, validators: [ @@ -376,6 +391,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + lumia: { + threshold: 1, + validators: ['0x9e283254ed2cd2c80f007348c2822fc8e5c2fa5f'], + }, + mantapacific: { threshold: 5, validators: [ @@ -535,6 +555,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + rari: { + threshold: 1, + validators: ['0x989d6862e09de21337078efbd86843a3eb1133e3'], + }, + real: { threshold: 2, validators: [ @@ -553,6 +578,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + rootstock: { + threshold: 1, + validators: ['0xcb8e3a72cf427feff27416d0e2ec375a052eaaee'], + }, + sanko: { threshold: 2, validators: [ @@ -660,6 +690,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0xf58f6e30aabba34e8dd7f79b3168507192e2cc9b'], }, + superposition: { + threshold: 1, + validators: ['0x5978d0e6afa9270ddb87cff43a8fa7a763a5dfc4'], + }, + superpositiontestnet: { threshold: 1, validators: ['0x1d3168504b23b73cdf9c27f13bb0a595d7f1a96a'], From ac2bef951012f010be2e674036ad83dd9d3600f4 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Wed, 9 Oct 2024 14:27:23 +0100 Subject: [PATCH 116/224] feat: Deploy Scraper for Injective, Neutron, Osmosis and Sei chains (#4653) ### Description Deploy Scraper for Injective, Neutron, Osmosis and Sei chains 1. Enable Scraper role for Injective, Neutron, Osmosis and Sei chains in hyperlane context (production) 2. Upgrade Scraper docker image in hyperlane context. ### Related issues https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/3356 ### Backward compatibility Yes ### Testing Manual scraping locally --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../config/environments/mainnet3/agent.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 532e327e9..b0fe723f7 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -213,7 +213,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< cyber: true, degenchain: true, dogechain: true, - // Cannot scrape non-EVM chains + // Cannot scrape Sealevel chains eclipsemainnet: false, endurance: true, ethereum: true, @@ -224,8 +224,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< gnosis: true, immutablezkevm: true, inevm: true, - // Cannot scrape non-EVM chains - injective: false, + injective: true, kroma: true, linea: true, lisk: true, @@ -239,12 +238,10 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< mode: true, molten: true, moonbeam: true, - // Cannot scrape non-EVM chains - neutron: false, + neutron: true, oortmainnet: true, optimism: true, - // Cannot scrape non-EVM chains - osmosis: false, + osmosis: true, polygon: true, polygonzkevm: true, proofofplay: true, @@ -254,11 +251,9 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< rootstock: true, sanko: true, scroll: true, - // Out of caution around pointer contracts (https://www.docs.sei.io/dev-interoperability/pointer-contracts) not being compatible - // and the scraper not gracefully handling txs that may not exist via the eth RPC, we don't run the scraper. - sei: false, + sei: true, shibarium: true, - // Cannot scrape non-EVM chains + // Cannot scrape Sealevel chains solanamainnet: false, superposition: true, taiko: true, @@ -433,7 +428,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '6f414af-20241004-131949', + tag: '3254472-20241009-111928', }, resources: scraperResources, }, From 45eb3ae5e300d6eb921ee3c9a75193cf51d39b10 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:42:27 +0100 Subject: [PATCH 117/224] fix: sealevel unit tests flake (#4655) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../validator-announce/tests/functional.rs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/rust/sealevel/programs/validator-announce/tests/functional.rs b/rust/sealevel/programs/validator-announce/tests/functional.rs index cf1b5f0f5..450f88b88 100644 --- a/rust/sealevel/programs/validator-announce/tests/functional.rs +++ b/rust/sealevel/programs/validator-announce/tests/functional.rs @@ -1,6 +1,6 @@ use hyperlane_core::{Announcement, H160}; -use std::str::FromStr; +use std::{str::FromStr, thread::sleep}; use account_utils::SizedData; use borsh::BorshSerialize; @@ -300,12 +300,7 @@ async fn test_announce() { storage_location: announcement.storage_location, signature, }; - let ( - validator_storage_locations_key, - validator_storage_locations_bump_seed, - replay_protection_key, - _replay_protection_bump_seed, - ) = announce( + let announcement_res = announce( &mut banks_client, &payer, program_id, @@ -315,6 +310,17 @@ async fn test_announce() { .await .unwrap(); + // there's a race condition that isn't fixed by setting `CommitmentLevel::Confirmed` + // just wait a bit to ensure the account is created + sleep(std::time::Duration::from_secs(1)); + + let ( + validator_storage_locations_key, + validator_storage_locations_bump_seed, + replay_protection_key, + _replay_protection_bump_seed, + ) = announcement_res; + assert_successful_announcement( &mut banks_client, program_id, From fcfe91113f49f824714173209046d916e0a0ad99 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:12:04 +0100 Subject: [PATCH 118/224] fix: reuse SDK tx type in submitters (#4642) ### Description Updating the types in the submitters because they were using their own types instead of the existing ones for some reason. ### Drive-by changes move `createTransferOwnershipTx` from the abstract hyperlane module to the evm module deployer, as it's EVM specific ### Related issues na ### Backward compatibility yes ### Testing ci --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/gorgeous-rivers-search.md | 6 +++ typescript/cli/src/config/submit.ts | 18 ++++--- .../sdk/src/core/AbstractHyperlaneModule.ts | 47 +------------------ typescript/sdk/src/core/EvmCoreModule.ts | 3 +- .../sdk/src/deploy/EvmModuleDeployer.ts | 43 ++++++++++++++++- typescript/sdk/src/index.ts | 10 +--- .../providers/transactions/schemas.test.ts | 31 +----------- .../sdk/src/providers/transactions/schemas.ts | 11 ----- .../ethersV5/EV5GnosisSafeTxBuilder.ts | 6 +-- .../ethersV5/EV5GnosisSafeTxSubmitter.ts | 9 ++-- .../EV5ImpersonatedAccountTxSubmitter.ts | 4 +- .../ethersV5/EV5JsonRpcTxSubmitter.ts | 4 +- .../EV5InterchainAccountTxTransformer.ts | 14 +++--- .../sdk/src/providers/transactions/types.ts | 14 +----- .../sdk/src/token/EvmERC20WarpModule.ts | 3 +- 15 files changed, 85 insertions(+), 138 deletions(-) create mode 100644 .changeset/gorgeous-rivers-search.md diff --git a/.changeset/gorgeous-rivers-search.md b/.changeset/gorgeous-rivers-search.md new file mode 100644 index 000000000..a96034113 --- /dev/null +++ b/.changeset/gorgeous-rivers-search.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': patch +'@hyperlane-xyz/sdk': patch +--- + +Reuse SDK transaction typings in tx submitters diff --git a/typescript/cli/src/config/submit.ts b/typescript/cli/src/config/submit.ts index e2f66a003..45f3367b0 100644 --- a/typescript/cli/src/config/submit.ts +++ b/typescript/cli/src/config/submit.ts @@ -1,11 +1,9 @@ import { stringify as yamlStringify } from 'yaml'; import { - PopulatedTransactions, - PopulatedTransactionsSchema, + AnnotatedEV5Transaction, SubmissionStrategy, } from '@hyperlane-xyz/sdk'; -import { PopulatedTransaction } from '@hyperlane-xyz/sdk'; import { MultiProvider } from '@hyperlane-xyz/sdk'; import { assert, errorToString } from '@hyperlane-xyz/utils'; @@ -72,20 +70,20 @@ export async function runSubmit({ */ function getChainFromTxs( multiProvider: MultiProvider, - transactions: PopulatedTransactions, + transactions: AnnotatedEV5Transaction[], ) { const firstTransaction = transactions[0]; + assert(firstTransaction.chainId, 'Invalid transaction: chainId is required'); const sameChainIds = transactions.every( - (t: PopulatedTransaction) => t.chainId === firstTransaction.chainId, + (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): PopulatedTransactions { - const transactionsFileContent = readYamlOrJson( - transactionsFilepath.trim(), - ); - return PopulatedTransactionsSchema.parse(transactionsFileContent); +function getTransactions( + transactionsFilepath: string, +): AnnotatedEV5Transaction[] { + return readYamlOrJson(transactionsFilepath.trim()); } diff --git a/typescript/sdk/src/core/AbstractHyperlaneModule.ts b/typescript/sdk/src/core/AbstractHyperlaneModule.ts index d4eadabae..b4a42ec30 100644 --- a/typescript/sdk/src/core/AbstractHyperlaneModule.ts +++ b/typescript/sdk/src/core/AbstractHyperlaneModule.ts @@ -1,17 +1,8 @@ import { Logger } from 'pino'; -import { Ownable__factory } from '@hyperlane-xyz/core'; -import { - Address, - Annotated, - ProtocolType, - eqAddress, -} from '@hyperlane-xyz/utils'; +import { Annotated, ProtocolType } from '@hyperlane-xyz/utils'; -import { - AnnotatedEV5Transaction, - ProtocolTypedTransaction, -} from '../providers/ProviderType.js'; +import { ProtocolTypedTransaction } from '../providers/ProviderType.js'; import { ChainNameOrId } from '../types.js'; export type HyperlaneModuleParams< @@ -43,40 +34,6 @@ export abstract class HyperlaneModule< config: TConfig, ): Promise['transaction'][]>>; - /** - * Transfers ownership of a contract to a new owner. - * - * @param actualOwner - The current owner of the contract. - * @param expectedOwner - The expected new owner of the contract. - * @param deployedAddress - The address of the deployed contract. - * @param chainId - The chain ID of the network the contract is deployed on. - * @returns An array of annotated EV5 transactions that need to be executed to update the owner. - */ - static createTransferOwnershipTx(params: { - actualOwner: Address; - expectedOwner: Address; - deployedAddress: Address; - chainId: number; - }): AnnotatedEV5Transaction[] { - const { actualOwner, expectedOwner, deployedAddress, chainId } = params; - const updateTransactions: AnnotatedEV5Transaction[] = []; - if (eqAddress(actualOwner, expectedOwner)) { - return []; - } - - updateTransactions.push({ - annotation: `Transferring ownership of ${deployedAddress} from current owner ${actualOwner} to new owner ${expectedOwner}`, - chainId, - to: deployedAddress, - data: Ownable__factory.createInterface().encodeFunctionData( - 'transferOwnership(address)', - [expectedOwner], - ), - }); - - return updateTransactions; - } - // /* // Types and static methods can be challenging. Ensure each implementation includes a static create function. // Currently, include TConfig to maintain the structure for ISM/Hook configurations. diff --git a/typescript/sdk/src/core/EvmCoreModule.ts b/typescript/sdk/src/core/EvmCoreModule.ts index f8f726c52..fd4e96018 100644 --- a/typescript/sdk/src/core/EvmCoreModule.ts +++ b/typescript/sdk/src/core/EvmCoreModule.ts @@ -17,6 +17,7 @@ import { } from '../contracts/types.js'; import { DeployedCoreAddresses } from '../core/schemas.js'; import { CoreConfig } from '../core/types.js'; +import { EvmModuleDeployer } from '../deploy/EvmModuleDeployer.js'; import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js'; import { ProxyFactoryFactories, @@ -201,7 +202,7 @@ export class EvmCoreModule extends HyperlaneModule< actualConfig: CoreConfig, expectedConfig: CoreConfig, ): AnnotatedEV5Transaction[] { - return EvmCoreModule.createTransferOwnershipTx({ + return EvmModuleDeployer.createTransferOwnershipTx({ actualOwner: actualConfig.owner, expectedOwner: expectedConfig.owner, deployedAddress: this.args.addresses.mailbox, diff --git a/typescript/sdk/src/deploy/EvmModuleDeployer.ts b/typescript/sdk/src/deploy/EvmModuleDeployer.ts index 377a1ffd2..6b2a09eba 100644 --- a/typescript/sdk/src/deploy/EvmModuleDeployer.ts +++ b/typescript/sdk/src/deploy/EvmModuleDeployer.ts @@ -2,15 +2,22 @@ import { ethers } from 'ethers'; import { Logger } from 'pino'; import { + Ownable__factory, StaticAddressSetFactory, StaticThresholdAddressSetFactory, TransparentUpgradeableProxy__factory, } from '@hyperlane-xyz/core'; import { buildArtifact as coreBuildArtifact } from '@hyperlane-xyz/core/buildArtifact.js'; -import { Address, addBufferToGasLimit, rootLogger } from '@hyperlane-xyz/utils'; +import { + Address, + addBufferToGasLimit, + eqAddress, + rootLogger, +} from '@hyperlane-xyz/utils'; import { HyperlaneContracts, HyperlaneFactories } from '../contracts/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; +import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { ChainMap, ChainName } from '../types.js'; import { isProxy, proxyConstructorArgs } from './proxy.js'; @@ -315,4 +322,38 @@ export class EvmModuleDeployer { return address; } + + /** + * Transfers ownership of a contract to a new owner. + * + * @param actualOwner - The current owner of the contract. + * @param expectedOwner - The expected new owner of the contract. + * @param deployedAddress - The address of the deployed contract. + * @param chainId - The chain ID of the network the contract is deployed on. + * @returns An array of annotated EV5 transactions that need to be executed to update the owner. + */ + public static createTransferOwnershipTx(params: { + actualOwner: Address; + expectedOwner: Address; + deployedAddress: Address; + chainId: number; + }): AnnotatedEV5Transaction[] { + const { actualOwner, expectedOwner, deployedAddress, chainId } = params; + const updateTransactions: AnnotatedEV5Transaction[] = []; + if (eqAddress(actualOwner, expectedOwner)) { + return []; + } + + updateTransactions.push({ + annotation: `Transferring ownership of ${deployedAddress} from current owner ${actualOwner} to new owner ${expectedOwner}`, + chainId, + to: deployedAddress, + data: Ownable__factory.createInterface().encodeFunctionData( + 'transferOwnership(address)', + [expectedOwner], + ), + }); + + return updateTransactions; + } } diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index 4959adacf..754166a62 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -312,15 +312,7 @@ export { excludeProviderMethods, } from './providers/SmartProvider/ProviderMethods.js'; export { HyperlaneSmartProvider } from './providers/SmartProvider/SmartProvider.js'; -export { - PopulatedTransactionSchema, - PopulatedTransactionsSchema, -} from './providers/transactions/schemas.js'; -export { - CallData, - PopulatedTransaction, - PopulatedTransactions, -} from './providers/transactions/types.js'; +export { CallData } from './providers/transactions/types.js'; export { SubmitterMetadataSchema } from './providers/transactions/submitter/schemas.js'; export { TxSubmitterInterface } from './providers/transactions/submitter/TxSubmitterInterface.js'; diff --git a/typescript/sdk/src/providers/transactions/schemas.test.ts b/typescript/sdk/src/providers/transactions/schemas.test.ts index 248878d30..8631a3f55 100644 --- a/typescript/sdk/src/providers/transactions/schemas.test.ts +++ b/typescript/sdk/src/providers/transactions/schemas.test.ts @@ -2,43 +2,16 @@ import { expect } from 'chai'; import { Address } from '@hyperlane-xyz/utils'; -import { CallDataSchema, PopulatedTransactionSchema } from './schemas.js'; -import { CallData, PopulatedTransaction } from './types.js'; +import { CallDataSchema } from './schemas.js'; +import { CallData } from './types.js'; describe('transactions schemas', () => { const ADDRESS_MOCK: Address = '0x1234567890123456789012345678901234567890'; const DATA_MOCK: string = '0xabcdef'; - const CHAIN_ID_MOCK: number = 1; const VALUE_MOCK: string = '100'; const INVALID_ADDRESS: Address = '0x1'; - describe('PopulatedTransactionSchema', () => { - it('should parse valid PopulatedTransaction', () => { - const validPopulatedTransaction: PopulatedTransaction = { - to: ADDRESS_MOCK, - data: DATA_MOCK, - chainId: CHAIN_ID_MOCK, - }; - const result = PopulatedTransactionSchema.safeParse( - validPopulatedTransaction, - ); - expect(result.success).to.be.true; - }); - - it('should fail parsing invalid PopulatedTransaction', () => { - const invalidPopulatedTransaction: PopulatedTransaction = { - to: INVALID_ADDRESS, - data: DATA_MOCK, - chainId: CHAIN_ID_MOCK, - }; - const result = PopulatedTransactionSchema.safeParse( - invalidPopulatedTransaction, - ); - expect(result.success).to.be.false; - }); - }); - describe('CallDataSchema', () => { it('should parse valid CallData', () => { const validCallData: CallData = { diff --git a/typescript/sdk/src/providers/transactions/schemas.ts b/typescript/sdk/src/providers/transactions/schemas.ts index b9071ae1c..7547f47e4 100644 --- a/typescript/sdk/src/providers/transactions/schemas.ts +++ b/typescript/sdk/src/providers/transactions/schemas.ts @@ -4,17 +4,6 @@ import { ZHash } from '../../metadata/customZodTypes.js'; export const BigNumberSchema = z.string(); -export const PopulatedTransactionSchema = z.object({ - to: ZHash, - data: z.string(), - chainId: z.number(), -}); - -export const PopulatedTransactionsSchema = - PopulatedTransactionSchema.array().refine((txs) => txs.length > 0, { - message: 'Populated Transactions cannot be empty', - }); - export const CallDataSchema = z.object({ to: ZHash, data: z.string(), diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts index e9a3ecb7e..7e8b61408 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts @@ -6,7 +6,7 @@ import { assert } from '@hyperlane-xyz/utils'; // @ts-ignore import { getSafe, getSafeService } from '../../../../utils/gnosisSafe.js'; import { MultiProvider } from '../../../MultiProvider.js'; -import { PopulatedTransaction, PopulatedTransactions } from '../../types.js'; +import { AnnotatedEV5Transaction } from '../../../ProviderType.js'; import { TxSubmitterType } from '../TxSubmitterTypes.js'; import { EV5GnosisSafeTxSubmitter } from './EV5GnosisSafeTxSubmitter.js'; @@ -58,10 +58,10 @@ export class EV5GnosisSafeTxBuilder extends EV5GnosisSafeTxSubmitter { * * @param txs - An array of populated transactions */ - public async submit(...txs: PopulatedTransactions): Promise { + public async submit(...txs: AnnotatedEV5Transaction[]): Promise { const transactions: SafeTransactionData[] = await Promise.all( txs.map( - async (tx: PopulatedTransaction) => + async (tx: AnnotatedEV5Transaction) => ( await this.createSafeTransaction(tx) ).data, diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts index 491594e60..9ed8ef98b 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts @@ -7,7 +7,7 @@ import { Address, assert, rootLogger } from '@hyperlane-xyz/utils'; // @ts-ignore import { canProposeSafeTransactions, getSafe, getSafeService } from '../../../../utils/gnosisSafe.js'; import { MultiProvider } from '../../../MultiProvider.js'; -import { PopulatedTransaction, PopulatedTransactions } from '../../types.js'; +import { AnnotatedEV5Transaction } from '../../../ProviderType.js'; import { TxSubmitterType } from '../TxSubmitterTypes.js'; import { EV5TxSubmitterInterface } from './EV5TxSubmitterInterface.js'; @@ -68,10 +68,11 @@ export class EV5GnosisSafeTxSubmitter implements EV5TxSubmitterInterface { data, value, chainId, - }: PopulatedTransaction): Promise { + }: AnnotatedEV5Transaction): Promise { const nextNonce: number = await this.safeService.getNextNonce( this.props.safeAddress, ); + assert(chainId, 'Invalid PopulatedTransaction: chainId is required'); const txChain = this.multiProvider.getChainName(chainId); assert( txChain === this.props.chain, @@ -83,11 +84,11 @@ export class EV5GnosisSafeTxSubmitter implements EV5TxSubmitterInterface { }); } - public async submit(...txs: PopulatedTransactions): Promise { + public async submit(...txs: AnnotatedEV5Transaction[]): Promise { return this.proposeIndividualTransactions(txs); } - private async proposeIndividualTransactions(txs: PopulatedTransactions) { + private async proposeIndividualTransactions(txs: AnnotatedEV5Transaction[]) { const safeTransactions: SafeTransaction[] = []; for (const tx of txs) { const safeTransaction = await this.createSafeTransaction(tx); diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5ImpersonatedAccountTxSubmitter.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5ImpersonatedAccountTxSubmitter.ts index 9a6866e35..f0fea448a 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5ImpersonatedAccountTxSubmitter.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5ImpersonatedAccountTxSubmitter.ts @@ -8,7 +8,7 @@ import { stopImpersonatingAccount, } from '../../../../utils/fork.js'; import { MultiProvider } from '../../../MultiProvider.js'; -import { PopulatedTransactions } from '../../types.js'; +import { AnnotatedEV5Transaction } from '../../../ProviderType.js'; import { TxSubmitterType } from '../TxSubmitterTypes.js'; import { EV5JsonRpcTxSubmitter } from './EV5JsonRpcTxSubmitter.js'; @@ -30,7 +30,7 @@ export class EV5ImpersonatedAccountTxSubmitter extends EV5JsonRpcTxSubmitter { } public async submit( - ...txs: PopulatedTransactions + ...txs: AnnotatedEV5Transaction[] ): Promise { const impersonatedAccount = await impersonateAccount( this.props.userAddress, diff --git a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.ts b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.ts index 30b60137d..4a3d11d47 100644 --- a/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.ts +++ b/typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.ts @@ -5,7 +5,7 @@ import { Logger } from 'pino'; import { assert, rootLogger } from '@hyperlane-xyz/utils'; import { MultiProvider } from '../../../MultiProvider.js'; -import { PopulatedTransactions } from '../../types.js'; +import { AnnotatedEV5Transaction } from '../../../ProviderType.js'; import { TxSubmitterType } from '../TxSubmitterTypes.js'; import { EV5TxSubmitterInterface } from './EV5TxSubmitterInterface.js'; @@ -20,7 +20,7 @@ export class EV5JsonRpcTxSubmitter implements EV5TxSubmitterInterface { constructor(public readonly multiProvider: MultiProvider) {} public async submit( - ...txs: PopulatedTransactions + ...txs: AnnotatedEV5Transaction[] ): Promise { const receipts: TransactionReceipt[] = []; for (const tx of txs) { diff --git a/typescript/sdk/src/providers/transactions/transformer/ethersV5/EV5InterchainAccountTxTransformer.ts b/typescript/sdk/src/providers/transactions/transformer/ethersV5/EV5InterchainAccountTxTransformer.ts index 62aefcf09..b2cce124f 100644 --- a/typescript/sdk/src/providers/transactions/transformer/ethersV5/EV5InterchainAccountTxTransformer.ts +++ b/typescript/sdk/src/providers/transactions/transformer/ethersV5/EV5InterchainAccountTxTransformer.ts @@ -9,11 +9,8 @@ import { } from '../../../../middleware/account/InterchainAccount.js'; import { ChainName } from '../../../../types.js'; import { MultiProvider } from '../../../MultiProvider.js'; -import { - CallData, - PopulatedTransaction, - PopulatedTransactions, -} from '../../types.js'; +import { AnnotatedEV5Transaction } from '../../../ProviderType.js'; +import { CallData } from '../../types.js'; import { TxTransformerType } from '../TxTransformerTypes.js'; import { EV5TxTransformerInterface } from './EV5TxTransformerInterface.js'; @@ -39,13 +36,16 @@ export class EV5InterchainAccountTxTransformer } public async transform( - ...txs: PopulatedTransactions + ...txs: AnnotatedEV5Transaction[] ): Promise { const txChainsToInnerCalls: Record = txs.reduce( ( txChainToInnerCalls: Record, - { to, data, chainId }: PopulatedTransaction, + { 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 }); diff --git a/typescript/sdk/src/providers/transactions/types.ts b/typescript/sdk/src/providers/transactions/types.ts index 4ed4e2319..49585f215 100644 --- a/typescript/sdk/src/providers/transactions/types.ts +++ b/typescript/sdk/src/providers/transactions/types.ts @@ -1,17 +1,5 @@ -import { ethers } from 'ethers'; import { z } from 'zod'; -import { - CallDataSchema, - PopulatedTransactionSchema, - PopulatedTransactionsSchema, -} from './schemas.js'; - -export type PopulatedTransaction = z.infer & - ethers.PopulatedTransaction; -export type PopulatedTransactions = z.infer< - typeof PopulatedTransactionsSchema -> & - ethers.PopulatedTransaction[]; +import { CallDataSchema } from './schemas.js'; export type CallData = z.infer; diff --git a/typescript/sdk/src/token/EvmERC20WarpModule.ts b/typescript/sdk/src/token/EvmERC20WarpModule.ts index d124093c7..19ea85489 100644 --- a/typescript/sdk/src/token/EvmERC20WarpModule.ts +++ b/typescript/sdk/src/token/EvmERC20WarpModule.ts @@ -19,6 +19,7 @@ import { HyperlaneModule, HyperlaneModuleParams, } from '../core/AbstractHyperlaneModule.js'; +import { EvmModuleDeployer } from '../deploy/EvmModuleDeployer.js'; import { EvmIsmModule } from '../ism/EvmIsmModule.js'; import { DerivedIsmConfig } from '../ism/EvmIsmReader.js'; import { MultiProvider } from '../providers/MultiProvider.js'; @@ -214,7 +215,7 @@ export class EvmERC20WarpModule extends HyperlaneModule< actualConfig: TokenRouterConfig, expectedConfig: TokenRouterConfig, ): AnnotatedEV5Transaction[] { - return EvmERC20WarpModule.createTransferOwnershipTx({ + return EvmModuleDeployer.createTransferOwnershipTx({ actualOwner: actualConfig.owner, expectedOwner: expectedConfig.owner, deployedAddress: this.args.addresses.deployedTokenRoute, From 2baaa116369c76665e67a31b97803106e823773d Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:13:39 +0100 Subject: [PATCH 119/224] chore: disable sealevel e2e when possible (#4654) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --------- Co-authored-by: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> --- .github/workflows/test.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6fcb5b6d..e1b7d7694 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -157,6 +157,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha || github.sha }} submodules: recursive + fetch-depth: 0 - name: foundry-install uses: foundry-rs/foundry-toolchain@v1 @@ -212,6 +213,16 @@ jobs: env: RUST_BACKTRACE: 'full' + - name: Check for Rust file changes + id: check-rust-changes + run: | + if [[ -n "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)" ]]; then + echo "rust_changes=true" >> $GITHUB_OUTPUT + echo "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)" + else + echo "rust_changes=false" >> $GITHUB_OUTPUT + fi + - name: agent tests (EVM and Sealevel) run: cargo run --release --bin run-locally --features test-utils if: matrix.e2e-type == 'non-cosmwasm' @@ -221,6 +232,7 @@ jobs: E2E_CI_TIMEOUT_SEC: '600' E2E_KATHY_MESSAGES: '20' RUST_BACKTRACE: 'full' + SEALEVEL_ENABLED: ${{ steps.check-rust-changes.outputs.rust_changes }} cli-advanced-e2e: runs-on: ubuntu-latest From 9c6f80cbe22689cc2da4203feba4c3857bba04a8 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:22:56 -0400 Subject: [PATCH 120/224] feat: add sei to ezeth config (#4651) ### Description add sei to ezeth config. Sei address is different so a mapping is needed - validator: sourced from luga tg, and https://t.me/c/2192542084/991 - xERC20: sourced from renzo tg. it's renamed to redEth so address is different https://t.me/c/2192542084/983 - safe address: sourced from renzo tg https://t.me/c/2192542084/934 --- .../configGetters/getRenzoEZETHWarpConfig.ts | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts index 10cca7fc6..7e6e31c6f 100644 --- a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts @@ -9,12 +9,6 @@ import { symmetricDifference } from '@hyperlane-xyz/utils'; import { getRegistry as getMainnet3Registry } from '../../chains.js'; -const lockbox = '0xC8140dA31E6bCa19b287cC35531c2212763C2059'; -const xERC20 = '0x2416092f143378750bb29b79eD961ab195CcEea5'; -const lockboxChain = 'ethereum'; -// over the default 100k to account for xerc20 gas + ISM overhead over the default ISM https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/49f41d9759fd515bfd89e6e22e799c41b27b4119/typescript/sdk/src/router/GasRouterDeployer.ts#L14 -const warpRouteOverheadGas = 200_000; - const chainsToDeploy = [ 'arbitrum', 'optimism', @@ -27,7 +21,26 @@ const chainsToDeploy = [ 'fraxtal', 'zircuit', 'taiko', + 'sei', ]; +const lockboxChain = 'ethereum'; +// over the default 100k to account for xerc20 gas + ISM overhead over the default ISM https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/49f41d9759fd515bfd89e6e22e799c41b27b4119/typescript/sdk/src/router/GasRouterDeployer.ts#L14 +const warpRouteOverheadGas = 200_000; +const lockbox = '0xC8140dA31E6bCa19b287cC35531c2212763C2059'; +const xERC20: Record<(typeof chainsToDeploy)[number], string> = { + arbitrum: '0x2416092f143378750bb29b79eD961ab195CcEea5', + optimism: '0x2416092f143378750bb29b79eD961ab195CcEea5', + base: '0x2416092f143378750bb29b79eD961ab195CcEea5', + blast: '0x2416092f143378750bb29b79eD961ab195CcEea5', + bsc: '0x2416092f143378750bb29b79eD961ab195CcEea5', + mode: '0x2416092f143378750bb29b79eD961ab195CcEea5', + linea: '0x2416092f143378750bb29b79eD961ab195CcEea5', + ethereum: '0x2416092f143378750bb29b79eD961ab195CcEea5', + fraxtal: '0x2416092f143378750bb29b79eD961ab195CcEea5', + zircuit: '0x2416092f143378750bb29b79eD961ab195CcEea5', + taiko: '0x2416092f143378750bb29b79eD961ab195CcEea5', + sei: '0x6DCfbF4729890043DFd34A93A2694E5303BA2703', // redEth +}; export const ezEthValidators = { arbitrum: { @@ -107,6 +120,13 @@ export const ezEthValidators = { '0xd4F6000d8e1108bd4998215d51d5dF559BdB43a1', // Renzo ], }, + sei: { + threshold: 1, + validators: [ + '0x7a0f4a8672f603e0c12468551db03f3956d10910', // luganodes + '0x952df7f0cb8611573a53dd7cbf29768871d9f8b0', // Renzo + ], + }, }; export const ezEthSafes: Record = { @@ -121,6 +141,7 @@ export const ezEthSafes: Record = { fraxtal: '0x8410927C286A38883BC23721e640F31D3E3E79F8', zircuit: '0x8410927C286A38883BC23721e640F31D3E3E79F8', taiko: '0x8410927C286A38883BC23721e640F31D3E3E79F8', + sei: '0x0e60fd361fF5b90088e1782e6b21A7D177d462C5', }; export const getRenzoEZETHWarpConfig = async (): Promise< @@ -136,6 +157,10 @@ export const getRenzoEZETHWarpConfig = async (): Promise< new Set(chainsToDeploy), new Set(Object.keys(ezEthSafes)), ); + const xERC20Diff = symmetricDifference( + new Set(chainsToDeploy), + new Set(Object.keys(xERC20)), + ); if (validatorDiff.size > 0) { throw new Error( `chainsToDeploy !== validatorConfig, diff is ${Array.from( @@ -148,6 +173,13 @@ export const getRenzoEZETHWarpConfig = async (): Promise< `chainsToDeploy !== safeDiff, diff is ${Array.from(safeDiff).join(', ')}`, ); } + if (xERC20Diff.size > 0) { + throw new Error( + `chainsToDeploy !== xERC20Diff, diff is ${Array.from(xERC20Diff).join( + ', ', + )}`, + ); + } const tokenConfig = Object.fromEntries( await Promise.all( @@ -161,7 +193,7 @@ export const getRenzoEZETHWarpConfig = async (): Promise< chain === lockboxChain ? TokenType.XERC20Lockbox : TokenType.XERC20, - token: chain === lockboxChain ? lockbox : xERC20, + token: chain === lockboxChain ? lockbox : xERC20[chain], owner: ezEthSafes[chain], gas: warpRouteOverheadGas, mailbox: (await registry.getChainAddresses(chain))!.mailbox, From 2afc484a2b28c28414d18dc9613361c4b9dea7e6 Mon Sep 17 00:00:00 2001 From: J M Rossy Date: Wed, 9 Oct 2024 13:16:14 -0400 Subject: [PATCH 121/224] feat: Create chain search and override widgets (#4486) ### Description - Widgets: Create `ChainSearchMenu` and `ChainDetailsMenu` components - Widgets: Add required icon and button components - Widgets: Add persisted zustand store and hooks - Widgets: Add clipboard utility functions - Utils: Migrate `fetchWithTimeout` from widgets to utils - Utils: Add `objSlice` function and improve types for `objMerge` - Utils: Add `isUrl` function - SDK: Break out BlockExplorerSchema and export separately - SDK: Migrate RPC + Explorer health tests back to SDK from registry ### Related issues Prerequisite for: - https://github.com/hyperlane-xyz/hyperlane-warp-ui-template/issues/238 - https://github.com/hyperlane-xyz/hyperlane-explorer/issues/108 - https://github.com/hyperlane-xyz/hyperlane-warp-ui-template/issues/215 Helps with: - https://github.com/hyperlane-xyz/issues/issues/1160 - https://github.com/hyperlane-xyz/issues/issues/1234 ### Backward compatibility Yes ### Testing New unit and storybook tests --- .changeset/calm-pears-clean.md | 6 + .changeset/clean-frogs-chew.md | 7 + .changeset/shy-zebras-invent.md | 8 + typescript/sdk/src/index.ts | 39 +- typescript/sdk/src/metadata/blockExplorer.ts | 33 +- .../sdk/src/metadata/chainMetadataTypes.ts | 71 ++- .../sdk/src/providers/explorerHealthTest.ts | 63 +++ typescript/sdk/src/providers/rpcHealthTest.ts | 85 +++ typescript/utils/src/async.ts | 22 + typescript/utils/src/index.ts | 6 +- typescript/utils/src/objects.test.ts | 49 +- typescript/utils/src/objects.ts | 89 ++- typescript/utils/src/result.ts | 18 + typescript/utils/src/url.ts | 9 + typescript/utils/src/yaml.ts | 17 + typescript/widgets/.storybook/main.ts | 6 + typescript/widgets/package.json | 10 +- .../widgets/src/chains/ChainAddMenu.tsx | 189 +++++++ .../widgets/src/chains/ChainDetailsMenu.tsx | 505 ++++++++++++++++++ .../src/{icons => chains}/ChainLogo.tsx | 21 +- .../widgets/src/chains/ChainSearchMenu.tsx | 322 +++++++++++ typescript/widgets/src/chains/types.ts | 4 + typescript/widgets/src/color.ts | 3 +- typescript/widgets/src/components/Button.tsx | 21 + .../widgets/src/components/CopyButton.tsx | 51 ++ .../widgets/src/components/IconButton.tsx | 24 + .../widgets/src/components/LinkButton.tsx | 21 + .../widgets/src/components/SearchMenu.tsx | 344 ++++++++++++ .../src/components/SegmentedControl.tsx | 51 ++ .../widgets/src/components/TextInput.tsx | 25 + typescript/widgets/src/components/Tooltip.tsx | 28 + typescript/widgets/src/icons/Airplane.tsx | 17 +- typescript/widgets/src/icons/Arrow.tsx | 45 ++ typescript/widgets/src/icons/BoxArrow.tsx | 24 + typescript/widgets/src/icons/Checkmark.tsx | 18 + typescript/widgets/src/icons/Chevron.tsx | 46 ++ typescript/widgets/src/icons/Circle.tsx | 6 +- typescript/widgets/src/icons/Copy.tsx | 34 ++ typescript/widgets/src/icons/Envelope.tsx | 17 +- typescript/widgets/src/icons/Filter.tsx | 18 + typescript/widgets/src/icons/Funnel.tsx | 18 + typescript/widgets/src/icons/Gear.tsx | 18 + typescript/widgets/src/icons/Lock.tsx | 17 +- typescript/widgets/src/icons/Pencil.tsx | 23 + typescript/widgets/src/icons/Plus.tsx | 18 + typescript/widgets/src/icons/PlusCircle.tsx | 18 + typescript/widgets/src/icons/QuestionMark.tsx | 19 +- typescript/widgets/src/icons/Search.tsx | 18 + typescript/widgets/src/icons/Shield.tsx | 17 +- typescript/widgets/src/icons/Spinner.tsx | 33 ++ typescript/widgets/src/icons/UpDownArrows.tsx | 19 + typescript/widgets/src/icons/WideChevron.tsx | 19 +- typescript/widgets/src/icons/X.tsx | 18 + typescript/widgets/src/icons/types.ts | 5 + typescript/widgets/src/index.ts | 45 +- .../widgets/src/layout/DropdownMenu.tsx | 45 ++ typescript/widgets/src/layout/Modal.tsx | 74 +++ typescript/widgets/src/layout/Popover.tsx | 47 ++ typescript/widgets/src/logos/Hyperlane.tsx | 25 + .../widgets/src/messages/useMessageStage.ts | 2 +- .../src/stories/ChainDetailsMenu.stories.tsx | 42 ++ .../widgets/src/stories/ChainLogo.stories.tsx | 11 +- .../src/stories/ChainSearchMenu.stories.tsx | 48 ++ .../widgets/src/stories/Modal.stories.tsx | 36 ++ typescript/widgets/src/styles.css | 13 + typescript/widgets/src/utils/clipboard.ts | 24 + typescript/widgets/src/utils/explorers.ts | 3 +- typescript/widgets/src/utils/timeout.ts | 14 - .../src/utils/useChainConnectionTest.ts | 32 ++ typescript/widgets/tailwind.config.cjs | 22 +- yarn.lock | 216 +++++++- 71 files changed, 3125 insertions(+), 206 deletions(-) create mode 100644 .changeset/calm-pears-clean.md create mode 100644 .changeset/clean-frogs-chew.md create mode 100644 .changeset/shy-zebras-invent.md create mode 100644 typescript/sdk/src/providers/explorerHealthTest.ts create mode 100644 typescript/sdk/src/providers/rpcHealthTest.ts create mode 100644 typescript/utils/src/result.ts create mode 100644 typescript/utils/src/yaml.ts create mode 100644 typescript/widgets/src/chains/ChainAddMenu.tsx create mode 100644 typescript/widgets/src/chains/ChainDetailsMenu.tsx rename typescript/widgets/src/{icons => chains}/ChainLogo.tsx (74%) create mode 100644 typescript/widgets/src/chains/ChainSearchMenu.tsx create mode 100644 typescript/widgets/src/chains/types.ts create mode 100644 typescript/widgets/src/components/Button.tsx create mode 100644 typescript/widgets/src/components/CopyButton.tsx create mode 100644 typescript/widgets/src/components/IconButton.tsx create mode 100644 typescript/widgets/src/components/LinkButton.tsx create mode 100644 typescript/widgets/src/components/SearchMenu.tsx create mode 100644 typescript/widgets/src/components/SegmentedControl.tsx create mode 100644 typescript/widgets/src/components/TextInput.tsx create mode 100644 typescript/widgets/src/components/Tooltip.tsx create mode 100644 typescript/widgets/src/icons/Arrow.tsx create mode 100644 typescript/widgets/src/icons/BoxArrow.tsx create mode 100644 typescript/widgets/src/icons/Checkmark.tsx create mode 100644 typescript/widgets/src/icons/Chevron.tsx create mode 100644 typescript/widgets/src/icons/Copy.tsx create mode 100644 typescript/widgets/src/icons/Filter.tsx create mode 100644 typescript/widgets/src/icons/Funnel.tsx create mode 100644 typescript/widgets/src/icons/Gear.tsx create mode 100644 typescript/widgets/src/icons/Pencil.tsx create mode 100644 typescript/widgets/src/icons/Plus.tsx create mode 100644 typescript/widgets/src/icons/PlusCircle.tsx create mode 100644 typescript/widgets/src/icons/Search.tsx create mode 100644 typescript/widgets/src/icons/Spinner.tsx create mode 100644 typescript/widgets/src/icons/UpDownArrows.tsx create mode 100644 typescript/widgets/src/icons/X.tsx create mode 100644 typescript/widgets/src/icons/types.ts create mode 100644 typescript/widgets/src/layout/DropdownMenu.tsx create mode 100644 typescript/widgets/src/layout/Modal.tsx create mode 100644 typescript/widgets/src/layout/Popover.tsx create mode 100644 typescript/widgets/src/logos/Hyperlane.tsx create mode 100644 typescript/widgets/src/stories/ChainDetailsMenu.stories.tsx create mode 100644 typescript/widgets/src/stories/ChainSearchMenu.stories.tsx create mode 100644 typescript/widgets/src/stories/Modal.stories.tsx create mode 100644 typescript/widgets/src/utils/clipboard.ts delete mode 100644 typescript/widgets/src/utils/timeout.ts create mode 100644 typescript/widgets/src/utils/useChainConnectionTest.ts diff --git a/.changeset/calm-pears-clean.md b/.changeset/calm-pears-clean.md new file mode 100644 index 000000000..d04b6574d --- /dev/null +++ b/.changeset/calm-pears-clean.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Break out BlockExplorerSchema and export separately +Migrate RPC + Explorer health tests back to SDK from registry diff --git a/.changeset/clean-frogs-chew.md b/.changeset/clean-frogs-chew.md new file mode 100644 index 000000000..b918b1034 --- /dev/null +++ b/.changeset/clean-frogs-chew.md @@ -0,0 +1,7 @@ +--- +'@hyperlane-xyz/utils': minor +--- + +Migrate fetchWithTimeout from widgets to utils +Add objSlice function and improve types for objMerge +Add isUrl function diff --git a/.changeset/shy-zebras-invent.md b/.changeset/shy-zebras-invent.md new file mode 100644 index 000000000..87a8d94eb --- /dev/null +++ b/.changeset/shy-zebras-invent.md @@ -0,0 +1,8 @@ +--- +'@hyperlane-xyz/widgets': minor +--- + +Create ChainSearchMenu and ChainDetailsMenu components +Add required icon and button components +Add persisted zustand store and hooks +Add clipboard utility functions diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index 754166a62..ee54c0409 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -27,10 +27,10 @@ export { testSealevelChain, } from './consts/testChains.js'; export { + attachAndConnectContracts, attachContracts, attachContractsMap, attachContractsMapAndGetForeignDeployments, - attachAndConnectContracts, connectContracts, connectContractsMap, filterAddressesMap, @@ -69,8 +69,8 @@ export { export { MultiProtocolCore } from './core/MultiProtocolCore.js'; export { CoreConfigSchema, - DeployedCoreAddressesSchema, DeployedCoreAddresses, + DeployedCoreAddressesSchema, } from './core/schemas.js'; export { TestCoreApp } from './core/TestCoreApp.js'; export { TestCoreDeployer } from './core/TestCoreDeployer.js'; @@ -195,6 +195,7 @@ export { } from './metadata/ChainMetadataManager.js'; export { BlockExplorer, + BlockExplorerSchema, ChainMetadata, ChainMetadataSchema, ChainMetadataSchemaObject, @@ -208,6 +209,8 @@ export { getDomainId, getReorgPeriod, isValidChainMetadata, + mergeChainMetadata, + mergeChainMetadataMap, } from './metadata/chainMetadataTypes.js'; export { ZChainName, ZHash } from './metadata/customZodTypes.js'; export { @@ -254,6 +257,7 @@ export { InterchainQueryConfig, InterchainQueryDeployer, } from './middleware/query/InterchainQueryDeployer.js'; +export { isBlockExplorerHealthy } from './providers/explorerHealthTest.js'; export { MultiProtocolProvider, MultiProtocolProviderOptions, @@ -302,7 +306,12 @@ export { ViemTransaction, ViemTransactionReceipt, } from './providers/ProviderType.js'; -export { ProviderRetryOptions } from './providers/SmartProvider/types.js'; +export { + isCosmJsProviderHealthy, + isEthersV5ProviderHealthy, + isRpcHealthy, + isSolanaWeb3ProviderHealthy, +} from './providers/rpcHealthTest.js'; export { HyperlaneEtherscanProvider } from './providers/SmartProvider/HyperlaneEtherscanProvider.js'; export { HyperlaneJsonRpcProvider } from './providers/SmartProvider/HyperlaneJsonRpcProvider.js'; export { @@ -312,6 +321,10 @@ export { excludeProviderMethods, } from './providers/SmartProvider/ProviderMethods.js'; export { HyperlaneSmartProvider } from './providers/SmartProvider/SmartProvider.js'; +export { + ProviderRetryOptions, + SmartProviderOptions, +} from './providers/SmartProvider/types.js'; export { CallData } from './providers/transactions/types.js'; export { SubmitterMetadataSchema } from './providers/transactions/submitter/schemas.js'; @@ -329,17 +342,17 @@ export { } from './providers/transactions/submitter/ethersV5/types.js'; export { - SubmissionStrategySchema, ChainSubmissionStrategySchema, + SubmissionStrategySchema, } from './providers/transactions/submitter/builder/schemas.js'; export { TxSubmitterBuilder } from './providers/transactions/submitter/builder/TxSubmitterBuilder.js'; export { - SubmissionStrategy, ChainSubmissionStrategy, + SubmissionStrategy, } from './providers/transactions/submitter/builder/types.js'; -export { EV5GnosisSafeTxSubmitter } from './providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.js'; export { EV5GnosisSafeTxBuilder } from './providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.js'; +export { EV5GnosisSafeTxSubmitter } from './providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.js'; export { EV5ImpersonatedAccountTxSubmitter } from './providers/transactions/submitter/ethersV5/EV5ImpersonatedAccountTxSubmitter.js'; export { EV5JsonRpcTxSubmitter } from './providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.js'; export { EV5TxSubmitterInterface } from './providers/transactions/submitter/ethersV5/EV5TxSubmitterInterface.js'; @@ -379,11 +392,11 @@ export { MailboxClientConfig, ProxiedFactories, ProxiedRouterConfig, + RemoteRouters, RouterAddress, RouterConfig, RouterViolation, RouterViolationType, - RemoteRouters, proxiedFactories, } from './router/types.js'; export { @@ -462,6 +475,7 @@ export { TOKEN_TYPE_TO_STANDARD, TokenStandard, } from './token/TokenStandard.js'; +export { TokenRouterConfig, WarpRouteDeployConfig } from './token/types.js'; export { ChainMap, ChainName, ChainNameOrId, Connection } from './types.js'; export { getCosmosRegistryChain } from './utils/cosmos.js'; export { filterByChains } from './utils/filter.js'; @@ -473,9 +487,8 @@ export { setFork, stopImpersonatingAccount, } from './utils/fork.js'; -export { MultiGeneric } from './utils/MultiGeneric.js'; -export { TokenRouterConfig, WarpRouteDeployConfig } from './token/types.js'; export { multisigIsmVerificationCost } from './utils/ism.js'; +export { MultiGeneric } from './utils/MultiGeneric.js'; export { SealevelAccountDataWrapper, SealevelInstructionWrapper, @@ -515,11 +528,11 @@ export { } from './utils/gnosisSafe.js'; export { EvmCoreModule } from './core/EvmCoreModule.js'; -export { EvmIsmModule } from './ism/EvmIsmModule.js'; -export { EvmERC20WarpModule } from './token/EvmERC20WarpModule.js'; +export { proxyAdmin } from './deploy/proxy.js'; export { - ProxyFactoryFactoriesSchema, ProxyFactoryFactoriesAddresses, + ProxyFactoryFactoriesSchema, } from './deploy/schemas.js'; +export { EvmIsmModule } from './ism/EvmIsmModule.js'; export { AnnotatedEV5Transaction } from './providers/ProviderType.js'; -export { proxyAdmin } from './deploy/proxy.js'; +export { EvmERC20WarpModule } from './token/EvmERC20WarpModule.js'; diff --git a/typescript/sdk/src/metadata/blockExplorer.ts b/typescript/sdk/src/metadata/blockExplorer.ts index 2da003937..e08f99ba6 100644 --- a/typescript/sdk/src/metadata/blockExplorer.ts +++ b/typescript/sdk/src/metadata/blockExplorer.ts @@ -2,13 +2,19 @@ import { ProtocolType } from '@hyperlane-xyz/utils'; import { ChainMetadata, ExplorerFamily } from './chainMetadataTypes.js'; -export function getExplorerBaseUrl(metadata: ChainMetadata): string | null { +export function getExplorerBaseUrl( + metadata: ChainMetadata, + index = 0, +): string | null { if (!metadata?.blockExplorers?.length) return null; - const url = new URL(metadata.blockExplorers[0].url); + const url = new URL(metadata.blockExplorers[index].url); return url.toString(); } -export function getExplorerApi(metadata: ChainMetadata): { +export function getExplorerApi( + metadata: ChainMetadata, + index = 0, +): { apiUrl: string; apiKey?: string | undefined; family?: ExplorerFamily | undefined; @@ -16,20 +22,21 @@ export function getExplorerApi(metadata: ChainMetadata): { const { protocol, blockExplorers } = metadata; // TODO solana + cosmos support here as needed if (protocol !== ProtocolType.Ethereum) return null; - if (!blockExplorers?.length || !blockExplorers[0].apiUrl) return null; + if (!blockExplorers?.length || !blockExplorers[index].apiUrl) return null; return { - apiUrl: blockExplorers[0].apiUrl, - apiKey: blockExplorers[0].apiKey, - family: blockExplorers[0].family, + apiUrl: blockExplorers[index].apiUrl, + apiKey: blockExplorers[index].apiKey, + family: blockExplorers[index].family, }; } -export function getExplorerApiUrl(metadata: ChainMetadata): string | null { - const { protocol, blockExplorers } = metadata; - // TODO solana + cosmos support here as needed - if (protocol !== ProtocolType.Ethereum) return null; - if (!blockExplorers?.length || !blockExplorers[0].apiUrl) return null; - const { apiUrl, apiKey } = blockExplorers[0]; +export function getExplorerApiUrl( + metadata: ChainMetadata, + index = 0, +): string | null { + const explorer = getExplorerApi(metadata, index)!; + if (!explorer) return null; + const { apiUrl, apiKey } = explorer; if (!apiKey) return apiUrl; const url = new URL(apiUrl); url.searchParams.set('apikey', apiKey); diff --git a/typescript/sdk/src/metadata/chainMetadataTypes.ts b/typescript/sdk/src/metadata/chainMetadataTypes.ts index b83b3f8c6..bdee44179 100644 --- a/typescript/sdk/src/metadata/chainMetadataTypes.ts +++ b/typescript/sdk/src/metadata/chainMetadataTypes.ts @@ -4,7 +4,9 @@ */ import { SafeParseReturnType, z } from 'zod'; -import { ProtocolType } from '@hyperlane-xyz/utils'; +import { ProtocolType, objMerge } from '@hyperlane-xyz/utils'; + +import { ChainMap } from '../types.js'; import { ZChainName, ZNzUint, ZUint } from './customZodTypes.js'; @@ -67,6 +69,29 @@ export const RpcUrlSchema = z.object({ export type RpcUrl = z.infer; +export const BlockExplorerSchema = z.object({ + name: z.string().describe('A human readable name for the explorer.'), + url: z.string().url().describe('The base URL for the explorer.'), + apiUrl: z + .string() + .url() + .describe('The base URL for requests to the explorer API.'), + apiKey: z + .string() + .optional() + .describe( + 'An API key for the explorer (recommended for better reliability).', + ), + family: z + .nativeEnum(ExplorerFamily) + .optional() + .describe( + 'The type of the block explorer. See ExplorerFamily for valid values.', + ), +}); + +export type BlockExplorer = z.infer; + export const NativeTokenSchema = z.object({ name: z.string(), symbol: z.string(), @@ -87,28 +112,7 @@ export const ChainMetadataSchemaObject = z.object({ .describe('The human readable address prefix for the chains using bech32.'), blockExplorers: z - .array( - z.object({ - name: z.string().describe('A human readable name for the explorer.'), - url: z.string().url().describe('The base URL for the explorer.'), - apiUrl: z - .string() - .url() - .describe('The base URL for requests to the explorer API.'), - apiKey: z - .string() - .optional() - .describe( - 'An API key for the explorer (recommended for better reliability).', - ), - family: z - .nativeEnum(ExplorerFamily) - .optional() - .describe( - 'The type of the block explorer. See ExplorerFamily for valid values.', - ), - }), - ) + .array(BlockExplorerSchema) .optional() .describe('A list of block explorers with data for this chain'), @@ -230,7 +234,7 @@ export const ChainMetadataSchemaObject = z.object({ rpcUrls: z .array(RpcUrlSchema) - .nonempty() + .min(1) .describe('The list of RPC endpoints for interacting with the chain.'), slip44: z.number().optional().describe('The SLIP-0044 coin type.'), @@ -341,11 +345,6 @@ export type ChainMetadata = z.infer< > & Ext; -export type BlockExplorer = Exclude< - ChainMetadata['blockExplorers'], - undefined ->[number]; - export function safeParseChainMetadata( c: ChainMetadata, ): SafeParseReturnType { @@ -373,3 +372,17 @@ export function getReorgPeriod(chainMetadata: ChainMetadata): number { return chainMetadata.blocks.reorgPeriod; else throw new Error('Chain has no reorg period'); } + +export function mergeChainMetadata( + base: ChainMetadata, + overrides: Partial | undefined, +): ChainMetadata { + return objMerge(base, overrides || {}, 10, true); +} + +export function mergeChainMetadataMap( + base: ChainMap, + overrides: ChainMap | undefined> | undefined, +): ChainMap { + return objMerge>(base, overrides || {}, 10, true); +} diff --git a/typescript/sdk/src/providers/explorerHealthTest.ts b/typescript/sdk/src/providers/explorerHealthTest.ts new file mode 100644 index 000000000..4e6d8be3f --- /dev/null +++ b/typescript/sdk/src/providers/explorerHealthTest.ts @@ -0,0 +1,63 @@ +import { ChainMetadata } from '@hyperlane-xyz/sdk'; +import { Address, ProtocolType, rootLogger } from '@hyperlane-xyz/utils'; + +import { + getExplorerAddressUrl, + getExplorerBaseUrl, + getExplorerTxUrl, +} from '../metadata/blockExplorer.js'; + +const PROTOCOL_TO_ADDRESS: Record = { + [ProtocolType.Ethereum]: '0x0000000000000000000000000000000000000000', + [ProtocolType.Sealevel]: '11111111111111111111111111111111', + [ProtocolType.Cosmos]: 'cosmos100000000000000000000000000000000000000', +}; + +const PROTOCOL_TO_TX_HASH: Partial> = { + [ProtocolType.Ethereum]: + '0x0000000000000000000000000000000000000000000000000000000000000000', + [ProtocolType.Cosmos]: + '0000000000000000000000000000000000000000000000000000000000000000', +}; + +export async function isBlockExplorerHealthy( + chainMetadata: ChainMetadata, + explorerIndex: number, + address?: Address, + txHash?: string, +): Promise { + const baseUrl = getExplorerBaseUrl(chainMetadata, explorerIndex); + address ??= PROTOCOL_TO_ADDRESS[chainMetadata.protocol]; + txHash ??= PROTOCOL_TO_TX_HASH[chainMetadata.protocol]; + + if (!baseUrl) return false; + rootLogger.debug(`Got base url: ${baseUrl}`); + + rootLogger.debug(`Checking explorer home for ${chainMetadata.name}`); + await fetch(baseUrl); + rootLogger.debug(`Explorer home exists for ${chainMetadata.name}`); + + if (address) { + rootLogger.debug( + `Checking explorer address page for ${chainMetadata.name}`, + ); + const addressUrl = getExplorerAddressUrl(chainMetadata, address); + if (!addressUrl) return false; + rootLogger.debug(`Got address url: ${addressUrl}`); + const addressReq = await fetch(addressUrl); + if (!addressReq.ok && addressReq.status !== 404) return false; + rootLogger.debug(`Explorer address page okay for ${chainMetadata.name}`); + } + + if (txHash) { + rootLogger.debug(`Checking explorer tx page for ${chainMetadata.name}`); + const txUrl = getExplorerTxUrl(chainMetadata, txHash); + if (!txUrl) return false; + rootLogger.debug(`Got tx url: ${txUrl}`); + const txReq = await fetch(txUrl); + if (!txReq.ok && txReq.status !== 404) return false; + rootLogger.debug(`Explorer tx page okay for ${chainMetadata.name}`); + } + + return true; +} diff --git a/typescript/sdk/src/providers/rpcHealthTest.ts b/typescript/sdk/src/providers/rpcHealthTest.ts new file mode 100644 index 000000000..47b9ece24 --- /dev/null +++ b/typescript/sdk/src/providers/rpcHealthTest.ts @@ -0,0 +1,85 @@ +import { Mailbox__factory } from '@hyperlane-xyz/core'; +import { Address, rootLogger } from '@hyperlane-xyz/utils'; + +import { ChainMetadata } from '../metadata/chainMetadataTypes.js'; + +import { + CosmJsProvider, + CosmJsWasmProvider, + EthersV5Provider, + ProviderType, + SolanaWeb3Provider, +} from './ProviderType.js'; +import { protocolToDefaultProviderBuilder } from './providerBuilders.js'; + +export async function isRpcHealthy( + metadata: ChainMetadata, + rpcIndex: number, +): Promise { + const rpc = metadata.rpcUrls[rpcIndex]; + const builder = protocolToDefaultProviderBuilder[metadata.protocol]; + const provider = builder([rpc], metadata.chainId); + if (provider.type === ProviderType.EthersV5) + return isEthersV5ProviderHealthy(provider.provider, metadata); + else if (provider.type === ProviderType.SolanaWeb3) + return isSolanaWeb3ProviderHealthy(provider.provider, metadata); + else if ( + provider.type === ProviderType.CosmJsWasm || + provider.type === ProviderType.CosmJs + ) + return isCosmJsProviderHealthy(provider.provider, metadata); + else + throw new Error( + `Unsupported provider type ${provider.type}, new health check required`, + ); +} + +export async function isEthersV5ProviderHealthy( + provider: EthersV5Provider['provider'], + metadata: ChainMetadata, + mailboxAddress?: Address, +): Promise { + const chainName = metadata.name; + const blockNumber = await provider.getBlockNumber(); + if (!blockNumber || blockNumber < 0) return false; + rootLogger.debug(`Block number is okay for ${chainName}`); + + if (mailboxAddress) { + const mailbox = Mailbox__factory.createInterface(); + const topics = mailbox.encodeFilterTopics( + mailbox.events['DispatchId(bytes32)'], + [], + ); + rootLogger.debug(`Checking mailbox logs for ${chainName}`); + const mailboxLogs = await provider.getLogs({ + address: mailboxAddress, + topics, + fromBlock: blockNumber - 99, + toBlock: blockNumber, + }); + if (!mailboxLogs) return false; + rootLogger.debug(`Mailbox logs okay for ${chainName}`); + } + return true; +} + +export async function isSolanaWeb3ProviderHealthy( + provider: SolanaWeb3Provider['provider'], + metadata: ChainMetadata, +): Promise { + const blockNumber = await provider.getBlockHeight(); + if (!blockNumber || blockNumber < 0) return false; + rootLogger.debug(`Block number is okay for ${metadata.name}`); + return true; +} + +export async function isCosmJsProviderHealthy( + provider: CosmJsProvider['provider'] | CosmJsWasmProvider['provider'], + metadata: ChainMetadata, +): Promise { + const readyProvider = await provider; + const blockNumber = await readyProvider.getHeight(); + if (!blockNumber || blockNumber < 0) return false; + rootLogger.debug(`Block number is okay for ${metadata.name}`); + return true; +} diff --git a/typescript/utils/src/async.ts b/typescript/utils/src/async.ts index 0aa4d7a8e..f9bda74eb 100644 --- a/typescript/utils/src/async.ts +++ b/typescript/utils/src/async.ts @@ -55,6 +55,28 @@ export async function runWithTimeout( } } +/** + * Executes a fetch request that fails after a timeout via an AbortController. + * @param resource resource to fetch (e.g URL) + * @param options fetch call options object + * @param timeout timeout MS (default 10_000) + * @returns fetch response + */ +export async function fetchWithTimeout( + resource: RequestInfo, + options?: RequestInit, + timeout = 10_000, +) { + const controller = new AbortController(); + const id = setTimeout(() => controller.abort(), timeout); + const response = await fetch(resource, { + ...options, + signal: controller.signal, + }); + clearTimeout(id); + return response; +} + /** * Retries an async function if it raises an exception, * using exponential backoff. diff --git a/typescript/utils/src/index.ts b/typescript/utils/src/index.ts index 7f4c15841..e45994f8f 100644 --- a/typescript/utils/src/index.ts +++ b/typescript/utils/src/index.ts @@ -50,6 +50,7 @@ export { export { chunk, exclude, randomElement } from './arrays.js'; export { concurrentMap, + fetchWithTimeout, pollAsync, raceWithContext, retryAsync, @@ -114,10 +115,12 @@ export { objMap, objMapEntries, objMerge, + objOmit, pick, promiseObjAll, stringifyObject, } from './objects.js'; +export { Result, failure, success } from './result.js'; export { difference, setEquality, symmetricDifference } from './sets.js'; export { errorToString, @@ -156,6 +159,7 @@ export { TokenCaip19Id, WithAddress, } from './types.js'; -export { isHttpsUrl } from './url.js'; +export { isHttpsUrl, isUrl } from './url.js'; export { assert } from './validation.js'; export { BaseValidator, ValidatorConfig } from './validator.js'; +export { tryParseJsonOrYaml } from './yaml.js'; diff --git a/typescript/utils/src/objects.test.ts b/typescript/utils/src/objects.test.ts index 61d3b5a76..e454a2b17 100644 --- a/typescript/utils/src/objects.test.ts +++ b/typescript/utils/src/objects.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { deepCopy, deepEquals } from './objects.js'; +import { deepCopy, deepEquals, objMerge, objOmit } from './objects.js'; describe('Object utilities', () => { it('deepEquals', () => { @@ -13,4 +13,51 @@ describe('Object utilities', () => { expect(deepCopy({ a: 1, b: 2 })).to.eql({ a: 1, b: 2 }); expect(deepCopy({ a: 1, b: 2 })).to.not.eql({ a: 1, b: 3 }); }); + + it('objMerge', () => { + const obj1 = { a: 1, b: 2, c: { d: '4' } }; + const obj2 = { b: 3, c: { d: '5' } }; + const merged = objMerge(obj1, obj2); + expect(merged).to.eql({ a: 1, b: 3, c: { d: '5' } }); + }); + + it('objMerge with array', () => { + const obj1 = { a: 1, b: { c: ['arr1'] } }; + const obj2 = { a: 2, b: { c: ['arr2'] } }; + const merged = objMerge(obj1, obj2, 10, true); + expect(merged).to.eql({ a: 2, b: { c: ['arr2', 'arr1'] } }); + }); + + it('objMerge without array', () => { + const obj1 = { a: 1, b: { c: ['arr1'] } }; + const obj2 = { a: 2, b: { c: ['arr2'] } }; + const merged = objMerge(obj1, obj2, 10, false); + expect(merged).to.eql({ a: 2, b: { c: ['arr2'] } }); + }); + + it('objOmit', () => { + const obj1 = { a: 1, b: { c: ['arr1'], d: 'string' } }; + const obj2 = { a: true, b: { c: true } }; + const omitted = objOmit(obj1, obj2); + expect(omitted).to.eql({ b: { d: 'string' } }); + }); + + it('objOmit with array', () => { + const obj1 = { a: 1, b: { c: ['arr1', 'arr2'], d: 'string' } }; + const obj2 = { b: { c: ['arr1'] } }; + const omitted1_2 = objOmit(obj1, obj2, 10, true); + expect(omitted1_2).to.eql({ a: 1, b: { c: ['arr2'], d: 'string' } }); + + const obj3 = { a: [{ b: 1 }], c: 2 }; + const obj4 = { a: [{ b: 1 }] }; + const omitted3_4 = objOmit(obj3, obj4, 10, true); + expect(omitted3_4).to.eql({ a: [], c: 2 }); + }); + + it('objOmit without array', () => { + const obj1 = { a: 1, b: { c: ['arr1', 'arr2'], d: 'string' } }; + const obj2 = { b: { c: ['arr1'] } }; + const omitted1_2 = objOmit(obj1, obj2, 10, false); + expect(omitted1_2).to.eql({ a: 1, b: { d: 'string' } }); + }); }); diff --git a/typescript/utils/src/objects.ts b/typescript/utils/src/objects.ts index fda23c0b4..b97d4e662 100644 --- a/typescript/utils/src/objects.ts +++ b/typescript/utils/src/objects.ts @@ -98,34 +98,87 @@ export function pick(obj: Record, keys: K[]) { return ret as Record; } -// Recursively merges b into a -// Where there are conflicts, b takes priority over a -export function objMerge( +/** + * Returns a new object that recursively merges b into a + * Where there are conflicts, b takes priority over a + * @param a - The first object + * @param b - The second object + * @param max_depth - The maximum depth to recurse + * @param mergeArrays - If true, arrays will be concatenated instead of replaced + */ +export function objMerge( a: Record, b: Record, max_depth = 10, -): any { + mergeArrays = false, +): T { if (max_depth === 0) { throw new Error('objMerge tried to go too deep'); } - if (isObject(a) && isObject(b)) { - const ret: Record = {}; - const aKeys = new Set(Object.keys(a)); - const bKeys = new Set(Object.keys(b)); - const allKeys = new Set([...aKeys, ...bKeys]); - for (const key of allKeys.values()) { - if (aKeys.has(key) && bKeys.has(key)) { - ret[key] = objMerge(a[key], b[key], max_depth - 1); - } else if (aKeys.has(key)) { - ret[key] = a[key]; + if (!isObject(a) || !isObject(b)) { + return (b ? b : a) as T; + } + const ret: Record = {}; + const aKeys = new Set(Object.keys(a)); + const bKeys = new Set(Object.keys(b)); + const allKeys = new Set([...aKeys, ...bKeys]); + for (const key of allKeys.values()) { + if (aKeys.has(key) && bKeys.has(key)) { + if (mergeArrays && Array.isArray(a[key]) && Array.isArray(b[key])) { + ret[key] = [...b[key], ...a[key]]; } else { - ret[key] = b[key]; + ret[key] = objMerge(a[key], b[key], max_depth - 1, mergeArrays); + } + } else if (aKeys.has(key)) { + ret[key] = a[key]; + } else { + ret[key] = b[key]; + } + } + return ret as T; +} + +/** + * Return a new object with the fields in b removed from a + * @param a Base object to remove fields from + * @param b The partial object to remove from the base object + * @param max_depth The maximum depth to recurse + * @param sliceArrays If true, arrays will have values sliced out instead of being removed entirely + */ +export function objOmit = any>( + a: Record, + b: Record, + max_depth = 10, + sliceArrays = false, +): T { + if (max_depth === 0) { + throw new Error('objSlice tried to go too deep'); + } + if (!isObject(a) || !isObject(b)) { + return a as T; + } + const ret: Record = {}; + const aKeys = new Set(Object.keys(a)); + const bKeys = new Set(Object.keys(b)); + for (const key of aKeys.values()) { + if (bKeys.has(key)) { + if (sliceArrays && Array.isArray(a[key]) && Array.isArray(b[key])) { + ret[key] = a[key].filter( + (v: any) => !b[key].some((bv: any) => deepEquals(v, bv)), + ); + } else if (isObject(a[key]) && isObject(b[key])) { + const sliced = objOmit(a[key], b[key], max_depth - 1, sliceArrays); + if (Object.keys(sliced).length > 0) { + ret[key] = sliced; + } + } else if (!!b[key] == false) { + ret[key] = objOmit(a[key], b[key], max_depth - 1, sliceArrays); } + } else { + ret[key] = a[key]; } - return ret; - } else { - return b ? b : a; } + return ret as T; } export function invertKeysAndValues(data: any) { diff --git a/typescript/utils/src/result.ts b/typescript/utils/src/result.ts new file mode 100644 index 000000000..27c01ad53 --- /dev/null +++ b/typescript/utils/src/result.ts @@ -0,0 +1,18 @@ +/********* RESULT MONAD *********/ +export type Result = + | { + success: true; + data: T; + } + | { + success: false; + error: string; + }; + +export function success(data: T): Result { + return { success: true, data }; +} + +export function failure(error: string): Result { + return { success: false, error }; +} diff --git a/typescript/utils/src/url.ts b/typescript/utils/src/url.ts index c93e96cf7..e1cca81ff 100644 --- a/typescript/utils/src/url.ts +++ b/typescript/utils/src/url.ts @@ -1,3 +1,12 @@ +export function isUrl(value: string) { + try { + const url = new URL(value); + return !!url.hostname; + } catch (error) { + return false; + } +} + export function isHttpsUrl(value: string) { try { const url = new URL(value); diff --git a/typescript/utils/src/yaml.ts b/typescript/utils/src/yaml.ts new file mode 100644 index 000000000..48ff7ecd9 --- /dev/null +++ b/typescript/utils/src/yaml.ts @@ -0,0 +1,17 @@ +import { parse as yamlParse } from 'yaml'; + +import { rootLogger } from './logging.js'; +import { Result, failure, success } from './result.js'; + +export function tryParseJsonOrYaml(input: string): Result { + try { + if (input.startsWith('{')) { + return success(JSON.parse(input)); + } else { + return success(yamlParse(input)); + } + } catch (error) { + rootLogger.error('Error parsing JSON or YAML', error); + return failure('Input is not valid JSON or YAML'); + } +} diff --git a/typescript/widgets/.storybook/main.ts b/typescript/widgets/.storybook/main.ts index 564564080..2afe9d398 100644 --- a/typescript/widgets/.storybook/main.ts +++ b/typescript/widgets/.storybook/main.ts @@ -1,4 +1,5 @@ import type { StorybookConfig } from '@storybook/react-vite'; +import { mergeConfig } from 'vite'; const config: StorybookConfig = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], @@ -15,5 +16,10 @@ const config: StorybookConfig = { docs: { autodocs: true, }, + async viteFinal(config, { configType }) { + return mergeConfig(config, { + define: { 'process.env': {} }, + }); + }, }; export default config; diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 34732b858..cff1e46ac 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -7,10 +7,14 @@ "react-dom": "^18" }, "dependencies": { - "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.4.0" + "@headlessui/react": "^2.1.8", + "@hyperlane-xyz/sdk": "5.4.0", + "@hyperlane-xyz/utils": "5.4.0", + "clsx": "^2.1.1", + "react-tooltip": "^5.28.0" }, "devDependencies": { + "@hyperlane-xyz/registry": "4.3.6", "@storybook/addon-essentials": "^7.6.14", "@storybook/addon-interactions": "^7.6.14", "@storybook/addon-links": "^7.6.14", @@ -34,7 +38,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "storybook": "^7.6.14", - "tailwindcss": "^3.2.4", + "tailwindcss": "^3.4.13", "ts-node": "^10.8.0", "typescript": "5.3.3", "vite": "^5.1.1" diff --git a/typescript/widgets/src/chains/ChainAddMenu.tsx b/typescript/widgets/src/chains/ChainAddMenu.tsx new file mode 100644 index 000000000..1b8beb617 --- /dev/null +++ b/typescript/widgets/src/chains/ChainAddMenu.tsx @@ -0,0 +1,189 @@ +import clsx from 'clsx'; +import React, { useState } from 'react'; + +import { DEFAULT_GITHUB_REGISTRY } from '@hyperlane-xyz/registry'; +import { + ChainMap, + ChainMetadata, + ChainMetadataSchema, + MultiProtocolProvider, +} from '@hyperlane-xyz/sdk'; +import { + Result, + failure, + success, + tryParseJsonOrYaml, +} from '@hyperlane-xyz/utils'; + +import { ColorPalette } from '../color.js'; +import { Button } from '../components/Button.js'; +import { CopyButton } from '../components/CopyButton.js'; +import { LinkButton } from '../components/LinkButton.js'; +import { ChevronIcon } from '../icons/Chevron.js'; +import { PlusIcon } from '../icons/Plus.js'; + +export interface ChainAddMenuProps { + chainMetadata: ChainMap; + overrideChainMetadata?: ChainMap | undefined>; + onChangeOverrideMetadata: ( + overrides?: ChainMap | undefined>, + ) => void; + onClickBack?: () => void; +} + +export function ChainAddMenu(props: ChainAddMenuProps) { + return ( +
+
+
+
+ ); +} + +function Header({ onClickBack }: Pick) { + return ( +
+ {!!onClickBack && ( + +
+ + Back +
+
+ )} +

Add chain metadata

+

+ Add metadata for chains not yet included in the{' '} + + Hyperlane Canonical Registry + + . Note, this data will only be used locally in your own browser. It does + not affect the registry. +

+
+ ); +} + +function Form({ + chainMetadata, + overrideChainMetadata, + onChangeOverrideMetadata, + onClickBack, +}: ChainAddMenuProps) { + const [textInput, setTextInput] = useState(''); + const [error, setError] = useState(null); + + const onChangeInput = (e: React.ChangeEvent) => { + setTextInput(e.target.value); + setError(null); + }; + + const onClickAdd = () => { + const result = tryParseMetadataInput(textInput, chainMetadata); + if (result.success) { + onChangeOverrideMetadata({ + ...overrideChainMetadata, + [result.data.name]: result.data, + }); + setTextInput(''); + onClickBack?.(); + } else { + setError(`Invalid config: ${result.error}`); + } + }; + + return ( +
+
+ + {error &&
{error}
} + +
+ +
+ ); +} + +function tryParseMetadataInput( + input: string, + existingChainMetadata: ChainMap, +): Result { + const parsed = tryParseJsonOrYaml(input); + if (!parsed.success) return parsed; + + const result = ChainMetadataSchema.safeParse(parsed.data); + + if (!result.success) { + console.error('Error validating chain config', result.error); + const firstIssue = result.error.issues[0]; + return failure(`${firstIssue.path} => ${firstIssue.message}`); + } + + const newMetadata = result.data as ChainMetadata; + const multiProvider = new MultiProtocolProvider(existingChainMetadata); + + if (multiProvider.tryGetChainMetadata(newMetadata.name)) { + 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) + ) { + return failure('domainId is already in use by another chain'); + } + + return success(newMetadata); +} + +const placeholderText = `# YAML data +--- +chainId: 11155111 +name: sepolia +displayName: Sepolia +protocol: ethereum +rpcUrls: + - http: https://foobar.com +blockExplorers: + - name: Sepolia Etherscan + family: etherscan + url: https://sepolia.etherscan.io + apiUrl: https://api-sepolia.etherscan.io/api + apiKey: '12345' +blocks: + confirmations: 1 + estimateBlockTime: 13 +`; diff --git a/typescript/widgets/src/chains/ChainDetailsMenu.tsx b/typescript/widgets/src/chains/ChainDetailsMenu.tsx new file mode 100644 index 000000000..15478fbba --- /dev/null +++ b/typescript/widgets/src/chains/ChainDetailsMenu.tsx @@ -0,0 +1,505 @@ +import clsx from 'clsx'; +import React, { PropsWithChildren, useEffect, useMemo, useState } from 'react'; +import { stringify as yamlStringify } from 'yaml'; + +import { DEFAULT_GITHUB_REGISTRY } from '@hyperlane-xyz/registry'; +import { + ChainMetadata, + isValidChainMetadata, + mergeChainMetadata, +} from '@hyperlane-xyz/sdk'; +import { + Result, + failure, + isNullish, + isUrl, + objMerge, + objOmit, + success, + tryParseJsonOrYaml, +} from '@hyperlane-xyz/utils'; + +import { ColorPalette } from '../color.js'; +import { CopyButton } from '../components/CopyButton.js'; +import { IconButton } from '../components/IconButton.js'; +import { LinkButton } from '../components/LinkButton.js'; +import { TextInput } from '../components/TextInput.js'; +import { Tooltip } from '../components/Tooltip.js'; +import { BoxArrowIcon } from '../icons/BoxArrow.js'; +import { CheckmarkIcon } from '../icons/Checkmark.js'; +import { ChevronIcon } from '../icons/Chevron.js'; +import { Circle } from '../icons/Circle.js'; +import { PlusCircleIcon } from '../icons/PlusCircle.js'; +import { Spinner } from '../icons/Spinner.js'; +import { XIcon } from '../icons/X.js'; +import { useConnectionHealthTest } from '../utils/useChainConnectionTest.js'; + +import { ChainLogo } from './ChainLogo.js'; +import { ChainConnectionType } from './types.js'; + +export interface ChainDetailsMenuProps { + chainMetadata: ChainMetadata; + overrideChainMetadata?: Partial; + onChangeOverrideMetadata: (overrides?: Partial) => void; + onClickBack?: () => void; + onRemoveChain?: () => void; +} + +export function ChainDetailsMenu(props: ChainDetailsMenuProps) { + const mergedMetadata = useMemo( + () => + mergeChainMetadata( + props.chainMetadata || {}, + props.overrideChainMetadata || {}, + ), + [props], + ); + + return ( +
+ + + + + + +
+ ); +} + +function ChainHeader({ + chainMetadata, + onClickBack, +}: Pick) { + return ( +
+ {!!onClickBack && ( + +
+ + Back +
+
+ )} +
+ +

{`${chainMetadata.displayName} Metadata`}

+
+
+ ); +} + +function ButtonRow({ chainMetadata, onRemoveChain }: ChainDetailsMenuProps) { + const { name } = chainMetadata; + + const copyValue = useMemo( + () => yamlStringify(chainMetadata), + [chainMetadata], + ); + + return ( +
+ +
+ + Copy Metadata + +
+ {onRemoveChain && ( + + + Delete Chain + + )} +
+ ); +} + +function ChainRpcs(props: ChainDetailsMenuProps) { + return ( + + ); +} + +function ChainExplorers(props: ChainDetailsMenuProps) { + return ( + + ); +} + +function ConnectionsSection({ + chainMetadata, + overrideChainMetadata, + onChangeOverrideMetadata, + header, + type, + tooltip, +}: ChainDetailsMenuProps & { + header: string; + type: ChainConnectionType; + tooltip?: string; +}) { + const values = getConnectionValues(chainMetadata, type); + + return ( +
+ {header} + {values.map((_, i) => ( + + ))} + +
+ ); +} + +function AddConnectionButton({ + chainMetadata, + overrideChainMetadata, + onChangeOverrideMetadata, + type, +}: ChainDetailsMenuProps & { + type: ChainConnectionType; +}) { + const [isAdding, setIsAdding] = useState(false); + const [isInvalid, setIsInvalid] = useState(false); + const [url, setUrl] = useState(''); + + const onClickDismiss = () => { + setIsAdding(false); + setIsInvalid(false); + setUrl(''); + }; + + const onClickAdd = (e?: React.FormEvent) => { + e?.preventDefault(); + + const currentValues = getConnectionValues(chainMetadata, type); + const newValue = url?.trim(); + if (!newValue || !isUrl(newValue) || currentValues.includes(newValue)) { + setIsInvalid(true); + return; + } + let newOverrides: Partial = {}; + if (type === ChainConnectionType.RPC) { + newOverrides = { + rpcUrls: [{ http: newValue }], + }; + } else if (type === ChainConnectionType.Explorer) { + const hostName = new URL(newValue).hostname; + newOverrides = { + blockExplorers: [{ url: newValue, apiUrl: newValue, name: hostName }], + }; + } + onChangeOverrideMetadata( + objMerge>( + overrideChainMetadata || {}, + newOverrides, + 10, + true, + ), + ); + onClickDismiss(); + }; + + if (!isAdding) { + return ( + setIsAdding(true)}> + +
{`Add new ${type}`}
+
+ ); + } + + return ( + onClickAdd(e)} + > + +
+ + onClickAdd()} + className="htw-bg-gray-600 htw-rounded-sm htw-px-1" + > + + + + + +
+ + ); +} + +function ChainInfo({ chainMetadata }: { chainMetadata: ChainMetadata }) { + const { chainId, domainId, deployer, isTestnet } = chainMetadata; + + return ( +
+ Chain Information +
+
+ Chain Id + {chainId} +
+
+ Domain Id + {domainId} +
+
+ + Contract Deployer + + + {deployer?.name || 'Unknown'} + +
+
+ Chain Type + + {isTestnet ? 'Testnet' : 'Mainnet'} + +
+
+
+ ); +} + +function MetadataOverride({ + chainMetadata, + overrideChainMetadata, + onChangeOverrideMetadata, +}: ChainDetailsMenuProps) { + const stringified = overrideChainMetadata + ? yamlStringify(overrideChainMetadata) + : ''; + const [overrideInput, setOverrideInput] = useState(stringified); + const showButton = overrideInput !== stringified; + const [isInvalid, setIsInvalid] = useState(false); + + // Keep input in sync with external changes + useEffect(() => { + setOverrideInput(stringified); + }, [stringified]); + + const onChangeInput = (e: React.ChangeEvent) => { + setOverrideInput(e.target.value); + setIsInvalid(false); + }; + + const onClickSetOverride = () => { + const trimmed = overrideInput?.trim(); + if (!trimmed) { + onChangeOverrideMetadata(undefined); + return; + } + const result = tryParseInput(trimmed, chainMetadata); + if (result.success) { + onChangeOverrideMetadata(result.data); + setOverrideInput(trimmed); + setIsInvalid(false); + } else { + setIsInvalid(true); + } + }; + + return ( +
+ + Metadata Overrides + +
+ + + + +
+
+ ); +} + +function SectionHeader({ + children, + className, + tooltip, +}: PropsWithChildren<{ className?: string; tooltip?: string }>) { + return ( +
+

+ {children} +

+ {tooltip && } +
+ ); +} + +function ConnectionRow({ + chainMetadata, + overrideChainMetadata = {}, + onChangeOverrideMetadata, + index, + type, +}: ChainDetailsMenuProps & { + index: number; + type: ChainConnectionType; +}) { + const isHealthy = useConnectionHealthTest(chainMetadata, index, type); + const value = getConnectionValues(chainMetadata, type)[index]; + const isRemovable = isOverrideConnection(overrideChainMetadata, type, value); + + const onClickRemove = () => { + let toOmit: Partial = {}; + if (type === ChainConnectionType.RPC) { + toOmit = { + rpcUrls: [ + overrideChainMetadata.rpcUrls!.find((r) => r.http === value)!, + ], + }; + } else if (type === ChainConnectionType.Explorer) { + toOmit = { + blockExplorers: [ + overrideChainMetadata.blockExplorers!.find((r) => r.url === value)!, + ], + }; + } + onChangeOverrideMetadata( + objOmit>(overrideChainMetadata, toOmit, 10, true), + ); + }; + + return ( +
+ {isNullish(isHealthy) && type == ChainConnectionType.RPC && ( + + )} + {isNullish(isHealthy) && type == ChainConnectionType.Explorer && ( + + )} + {!isNullish(isHealthy) && ( + + )} +
{value}
+ {isRemovable && ( + + + + )} +
+ ); +} + +function getConnectionValues( + chainMetadata: Partial, + type: ChainConnectionType, +) { + return ( + (type === ChainConnectionType.RPC + ? chainMetadata.rpcUrls?.map((r) => r.http) + : chainMetadata.blockExplorers?.map((b) => b.url)) || [] + ); +} + +function isOverrideConnection( + overrides: Partial | undefined, + type: ChainConnectionType, + value: string, +) { + return getConnectionValues(overrides || {}, type).includes(value); +} + +function tryParseInput( + input: string, + existingChainMetadata: ChainMetadata, +): Result> { + const parsed = tryParseJsonOrYaml>(input); + if (!parsed.success) return parsed; + const merged = mergeChainMetadata(existingChainMetadata, parsed.data); + const isValid = isValidChainMetadata(merged); + return isValid ? success(parsed.data) : failure('Invalid metadata overrides'); +} diff --git a/typescript/widgets/src/icons/ChainLogo.tsx b/typescript/widgets/src/chains/ChainLogo.tsx similarity index 74% rename from typescript/widgets/src/icons/ChainLogo.tsx rename to typescript/widgets/src/chains/ChainLogo.tsx index 6384477c8..082c8eaf3 100644 --- a/typescript/widgets/src/icons/ChainLogo.tsx +++ b/typescript/widgets/src/chains/ChainLogo.tsx @@ -2,8 +2,8 @@ import React, { ReactElement, useEffect, useState } from 'react'; import type { IRegistry } from '@hyperlane-xyz/registry'; -import { Circle } from './Circle.js'; -import { QuestionMarkIcon } from './QuestionMark.js'; +import { Circle } from '../icons/Circle.js'; +import { QuestionMarkIcon } from '../icons/QuestionMark.js'; type SvgIcon = (props: { width: number; @@ -13,7 +13,8 @@ type SvgIcon = (props: { export interface ChainLogoProps { chainName: string; - registry: IRegistry; + logoUri?: string; + registry?: IRegistry; size?: number; background?: boolean; Icon?: SvgIcon; // Optional override for the logo in the registry @@ -21,6 +22,7 @@ export interface ChainLogoProps { export function ChainLogo({ chainName, + logoUri, registry, size = 32, background = false, @@ -31,17 +33,18 @@ export function ChainLogo({ const iconSize = Math.floor(size / 1.9); const [svgLogos, setSvgLogos] = useState({}); - const logoUri = svgLogos[chainName]; + const uri = logoUri || svgLogos[chainName]; useEffect(() => { - if (!chainName || svgLogos[chainName] || Icon) return; + if (!chainName || svgLogos[chainName] || logoUri || Icon || !registry) + return; registry .getChainLogoUri(chainName) .then((uri) => uri && setSvgLogos({ ...svgLogos, [chainName]: uri })) .catch((err) => console.error(err)); }, [chainName, registry, svgLogos, Icon]); - if (!logoUri && !Icon) { + if (!uri && !Icon) { return ( {chainName ? ( @@ -55,11 +58,11 @@ export function ChainLogo({ if (background) { return ( - + {Icon ? ( ) : ( - {title} + {title} )} ); @@ -67,7 +70,7 @@ export function ChainLogo({ return Icon ? ( ) : ( - {title} + {title} ); } } diff --git a/typescript/widgets/src/chains/ChainSearchMenu.tsx b/typescript/widgets/src/chains/ChainSearchMenu.tsx new file mode 100644 index 000000000..bb3faf7f1 --- /dev/null +++ b/typescript/widgets/src/chains/ChainSearchMenu.tsx @@ -0,0 +1,322 @@ +import React, { useCallback, useMemo } from 'react'; + +import { + ChainMap, + ChainMetadata, + ChainName, + mergeChainMetadataMap, +} from '@hyperlane-xyz/sdk'; +import { ProtocolType } from '@hyperlane-xyz/utils'; + +import { + SearchMenu, + SortOrderOption, + SortState, +} from '../components/SearchMenu.js'; +import { SegmentedControl } from '../components/SegmentedControl.js'; + +import { ChainAddMenu } from './ChainAddMenu.js'; +import { ChainDetailsMenu } from './ChainDetailsMenu.js'; +import { ChainLogo } from './ChainLogo.js'; + +enum ChainSortByOption { + Name = 'name', + ChainId = 'chain id', + Protocol = 'protocol', +} + +enum FilterTestnetOption { + Testnet = 'testnet', + Mainnet = 'mainnet', +} + +interface ChainFilterState { + type?: FilterTestnetOption; + protocol?: ProtocolType; +} + +const defaultFilterState: ChainFilterState = { + type: undefined, + protocol: undefined, +}; + +interface CustomListItemField { + header: string; + data: ChainMap<{ display: string; sortValue: number }>; +} + +export interface ChainSearchMenuProps { + chainMetadata: ChainMap; + overrideChainMetadata?: ChainMap | undefined>; + onChangeOverrideMetadata: ( + overrides?: ChainMap | undefined>, + ) => void; + onClickChain: (chain: ChainMetadata) => void; + // Replace the default 2nd column (deployer) with custom data + customListItemField?: CustomListItemField; + // Auto-navigate to a chain details menu + showChainDetails?: ChainName; + // Auto-navigate to a chain add menu + showAddChainMenu?: boolean; + // Include add button above list + showAddChainButton?: boolean; +} + +export function ChainSearchMenu({ + chainMetadata, + onChangeOverrideMetadata, + overrideChainMetadata, + onClickChain, + customListItemField, + showChainDetails, + showAddChainButton, + showAddChainMenu, +}: ChainSearchMenuProps) { + const [drilldownChain, setDrilldownChain] = React.useState< + ChainName | undefined + >(showChainDetails); + + const [addChain, setAddChain] = React.useState(showAddChainMenu || false); + + const { listData, mergedMetadata } = useMemo(() => { + const mergedMetadata = mergeChainMetadataMap( + chainMetadata, + overrideChainMetadata, + ); + return { mergedMetadata, listData: Object.values(mergedMetadata) }; + }, [chainMetadata]); + + const { ListComponent, searchFn, sortOptions, defaultSortState } = + useCustomizedListItems(customListItemField); + + if (drilldownChain && mergedMetadata[drilldownChain]) { + const isLocalOverrideChain = !chainMetadata[drilldownChain]; + const onRemoveChain = () => { + const newOverrides = { ...overrideChainMetadata }; + delete newOverrides[drilldownChain]; + onChangeOverrideMetadata(newOverrides); + }; + + return ( + + onChangeOverrideMetadata({ + ...overrideChainMetadata, + [drilldownChain]: o, + }) + } + onClickBack={() => setDrilldownChain(undefined)} + onRemoveChain={isLocalOverrideChain ? onRemoveChain : undefined} + /> + ); + } + + if (addChain) { + return ( + setAddChain(false)} + /> + ); + } + + return ( + , + ChainSortByOption, + ChainFilterState + > + data={listData} + ListComponent={ListComponent} + searchFn={searchFn} + onClickItem={onClickChain} + onClickEditItem={(chain) => setDrilldownChain(chain.name)} + sortOptions={sortOptions} + defaultSortState={defaultSortState} + FilterComponent={ChainFilters} + defaultFilterState={defaultFilterState} + placeholder="Chain Name or ID" + onClickAddItem={showAddChainButton ? () => setAddChain(true) : undefined} + /> + ); +} + +function ChainListItem({ + data: chain, + customField, +}: { + data: ChainMetadata; + customField?: CustomListItemField; +}) { + return ( + <> +
+
+ +
+
+
+ {chain.displayName} +
+
+ {chain.isTestnet ? 'Testnet' : 'Mainnet'} +
+
+
+
+
+ {customField + ? customField.data[chain.name].display || 'Unknown' + : chain.deployer?.name || 'Unknown deployer'} +
+
+ {customField ? customField.header : 'Deployer'} +
+
+ + ); +} + +function ChainFilters({ + value, + onChange, +}: { + value: ChainFilterState; + onChange: (s: ChainFilterState) => void; +}) { + return ( +
+
+ + onChange({ ...value, type: selected })} + allowEmpty + /> +
+
+ + onChange({ ...value, protocol: selected })} + allowEmpty + /> +
+
+ ); +} + +function chainSearch({ + data, + query, + sort, + filter, + customListItemField, +}: { + data: ChainMetadata[]; + query: string; + sort: SortState; + filter: ChainFilterState; + customListItemField?: CustomListItemField; +}) { + const queryFormatted = query.trim().toLowerCase(); + return ( + data + // Query search + .filter( + (chain) => + chain.name.includes(queryFormatted) || + chain.displayName?.toLowerCase().includes(queryFormatted) || + chain.chainId.toString().includes(queryFormatted) || + chain.domainId?.toString().includes(queryFormatted), + ) + // Filter options + .filter((chain) => { + let included = true; + if (filter.type) { + included &&= + !!chain.isTestnet === (filter.type === FilterTestnetOption.Testnet); + } + if (filter.protocol) { + included &&= chain.protocol === filter.protocol; + } + return included; + }) + // Sort options + .sort((c1, c2) => { + // Special case handling for if the chains are being sorted by the + // custom field provided to ChainSearchMenu + if (customListItemField && sort.sortBy === customListItemField.header) { + const result = + customListItemField.data[c1.name].sortValue - + customListItemField.data[c2.name].sortValue; + return sort.sortOrder === SortOrderOption.Asc ? result : -result; + } + + // Otherwise sort by the default options + let sortValue1 = c1.name; + let sortValue2 = c2.name; + if (sort.sortBy === ChainSortByOption.ChainId) { + sortValue1 = c1.chainId.toString(); + sortValue2 = c2.chainId.toString(); + } else if (sort.sortBy === ChainSortByOption.Protocol) { + sortValue1 = c1.protocol; + sortValue2 = c2.protocol; + } + return sort.sortOrder === SortOrderOption.Asc + ? sortValue1.localeCompare(sortValue2) + : sortValue2.localeCompare(sortValue1); + }) + ); +} + +/** + * This hook creates closures around the provided customListItemField data + * This is useful because SearchMenu will do handle the list item rendering and + * management but the custom data is more or a chain-search-specific concern + */ +function useCustomizedListItems(customListItemField) { + // Create closure of ChainListItem but with customField pre-bound + const ListComponent = useCallback( + ({ data }: { data: ChainMetadata<{ disabled?: boolean }> }) => ( + + ), + [ChainListItem, customListItemField], + ); + + // Bind the custom field to the search function + const searchFn = useCallback( + (args: Parameters[0]) => + chainSearch({ ...args, customListItemField }), + [customListItemField], + ); + + // Merge the custom field into the sort options if a custom field exists + const sortOptions = useMemo( + () => [ + ...(customListItemField ? [customListItemField.header] : []), + ...Object.values(ChainSortByOption), + ], + [customListItemField], + ) as ChainSortByOption[]; + + // Sort by the custom field by default, if one is provided + const defaultSortState = useMemo( + () => + customListItemField + ? { + sortBy: customListItemField.header, + sortOrder: SortOrderOption.Desc, + } + : undefined, + [customListItemField], + ) as SortState | undefined; + + return { ListComponent, searchFn, sortOptions, defaultSortState }; +} diff --git a/typescript/widgets/src/chains/types.ts b/typescript/widgets/src/chains/types.ts new file mode 100644 index 000000000..bf00bb9de --- /dev/null +++ b/typescript/widgets/src/chains/types.ts @@ -0,0 +1,4 @@ +export enum ChainConnectionType { + RPC = 'rpc', + Explorer = 'explorer', +} diff --git a/typescript/widgets/src/color.ts b/typescript/widgets/src/color.ts index f3c3c3be2..273572c71 100644 --- a/typescript/widgets/src/color.ts +++ b/typescript/widgets/src/color.ts @@ -1,10 +1,11 @@ export enum ColorPalette { Black = '#010101', White = '#FFFFFF', - Blue = '#2362C0', + Blue = '#2764C1', DarkBlue = '#162A4A', LightBlue = '#82A8E4', Pink = '#CF2FB3', + LightGray = '#D3D4D7', Gray = '#6B7280', Beige = '#F1EDE9', Red = '#BF1B15', diff --git a/typescript/widgets/src/components/Button.tsx b/typescript/widgets/src/components/Button.tsx new file mode 100644 index 000000000..3177af05b --- /dev/null +++ b/typescript/widgets/src/components/Button.tsx @@ -0,0 +1,21 @@ +import clsx from 'clsx'; +import React, { ButtonHTMLAttributes, PropsWithChildren } from 'react'; + +type Props = PropsWithChildren>; + +export function Button(props: Props) { + const { className, children, ...rest } = props; + + const base = + 'htw-flex htw-items-center htw-justify-center htw-rounded-sm htw-transition-all'; + const onHover = 'hover:htw-opacity-80'; + const onDisabled = 'disabled:htw-opacity-30 disabled:htw-cursor-default'; + const onActive = 'active:htw-scale-95'; + const allClasses = clsx(base, onHover, onDisabled, onActive, className); + + return ( + + ); +} diff --git a/typescript/widgets/src/components/CopyButton.tsx b/typescript/widgets/src/components/CopyButton.tsx new file mode 100644 index 000000000..8db0b5ccb --- /dev/null +++ b/typescript/widgets/src/components/CopyButton.tsx @@ -0,0 +1,51 @@ +import React, { + ButtonHTMLAttributes, + PropsWithChildren, + useState, +} from 'react'; + +import { CheckmarkIcon } from '../icons/Checkmark.js'; +import { CopyIcon } from '../icons/Copy.js'; +import { tryClipboardSet } from '../utils/clipboard.js'; + +type Props = PropsWithChildren> & { + width?: number; + height?: number; + copyValue: string; +}; + +export function CopyButton({ + width, + height, + copyValue, + className, + children, + ...rest +}: Props) { + const [showCheckmark, setShowCheckmark] = useState(false); + + const onClick = async () => { + const result = await tryClipboardSet(copyValue); + if (result) { + setShowCheckmark(true); + setTimeout(() => setShowCheckmark(false), 2000); + } + }; + + return ( + + ); +} diff --git a/typescript/widgets/src/components/IconButton.tsx b/typescript/widgets/src/components/IconButton.tsx new file mode 100644 index 000000000..bc515ee7e --- /dev/null +++ b/typescript/widgets/src/components/IconButton.tsx @@ -0,0 +1,24 @@ +import clsx from 'clsx'; +import React, { ButtonHTMLAttributes, PropsWithChildren } from 'react'; + +type Props = PropsWithChildren> & { + width?: number; + height?: number; +}; + +export function IconButton(props: Props) { + const { className, children, ...rest } = props; + + const base = + 'htw-flex htw-items-center htw-justify-center htw-transition-all'; + const onHover = 'hover:htw-opacity-70 hover:htw-scale-105'; + const onDisabled = 'disabled:htw-opacity-30 disabled:htw-cursor-default'; + const onActive = 'active:htw-opacity-60'; + const allClasses = clsx(base, onHover, onDisabled, onActive, className); + + return ( + + ); +} diff --git a/typescript/widgets/src/components/LinkButton.tsx b/typescript/widgets/src/components/LinkButton.tsx new file mode 100644 index 000000000..026bf6ba1 --- /dev/null +++ b/typescript/widgets/src/components/LinkButton.tsx @@ -0,0 +1,21 @@ +import clsx from 'clsx'; +import React, { ButtonHTMLAttributes, PropsWithChildren } from 'react'; + +type Props = PropsWithChildren>; + +export function LinkButton(props: Props) { + const { className, children, ...rest } = props; + + const base = + 'htw-flex htw-items-center htw-justify-center htw-transition-all'; + const onHover = 'hover:htw-underline htw-underline-offset-2'; + const onDisabled = 'disabled:htw-opacity-30 disabled:htw-cursor-default'; + const onActive = 'active:htw-opacity-70'; + const allClasses = clsx(base, onHover, onDisabled, onActive, className); + + return ( + + ); +} diff --git a/typescript/widgets/src/components/SearchMenu.tsx b/typescript/widgets/src/components/SearchMenu.tsx new file mode 100644 index 000000000..74c900704 --- /dev/null +++ b/typescript/widgets/src/components/SearchMenu.tsx @@ -0,0 +1,344 @@ +import clsx from 'clsx'; +import React, { ComponentType, useMemo, useState } from 'react'; + +import { deepEquals, isObject, toTitleCase } from '@hyperlane-xyz/utils'; + +import { ColorPalette } from '../color.js'; +import { ArrowIcon } from '../icons/Arrow.js'; +import { PencilIcon } from '../icons/Pencil.js'; +import { PlusIcon } from '../icons/Plus.js'; +import { SearchIcon } from '../icons/Search.js'; +import { XIcon } from '../icons/X.js'; +import { DropdownMenu } from '../layout/DropdownMenu.js'; +import { Popover } from '../layout/Popover.js'; + +import { IconButton } from './IconButton.js'; +import { InputProps, TextInput } from './TextInput.js'; + +export interface SearchMenuProps< + ListItemData extends { disabled?: boolean }, + SortBy extends string, + FilterState, +> { + // The list of data items to show + data: ListItemData[]; + // The component with which the list items will be rendered + ListComponent: ComponentType<{ data: ListItemData }>; + // Handler for list item click event + onClickItem: (item: ListItemData) => void; + // Handler for edit list item click event + onClickEditItem: (item: ListItemData) => void; + // Handler for searching through list item data + searchFn: (args: { + data: ListItemData[]; + query: string; + sort: SortState; + filter: FilterState; + }) => ListItemData[]; + // List of sort options + sortOptions: SortBy[]; + // Default sort state for list data + defaultSortState?: SortState; + // The component with which the filter state will be rendered + FilterComponent: ComponentType<{ + value: FilterState; + onChange: (s: FilterState) => void; + }>; + // Default filter state for list data + defaultFilterState: FilterState; + // Placeholder text for the search input + placeholder?: string; + // Handler for add button click event + onClickAddItem?: () => void; +} + +export function SearchMenu< + ListItem extends { disabled?: boolean }, + SortBy extends string, + FilterState, +>({ + data, + ListComponent, + searchFn, + onClickItem, + onClickEditItem, + sortOptions, + defaultSortState, + FilterComponent, + defaultFilterState, + placeholder, + onClickAddItem, +}: SearchMenuProps) { + const [searchQuery, setSearchQuery] = useState(''); + const [isEditMode, setIsEditMode] = useState(false); + const [sortState, setSortState] = useState>( + defaultSortState || { + sortBy: sortOptions[0], + sortOrder: SortOrderOption.Asc, + }, + ); + const [filterState, setFilterState] = + useState(defaultFilterState); + + const results = useMemo( + () => + searchFn({ + data, + query: searchQuery, + sort: sortState, + filter: filterState, + }), + [data, searchQuery, sortState, filterState, searchFn], + ); + + return ( +
+ +
+
+ + +
+
+ setIsEditMode(!isEditMode)} + className="htw-p-1.5 htw-border htw-border-gray-200 htw-rounded-full" + title="Edit items" + > + + + {onClickAddItem && ( + + + + )} +
+
+
+ {results.length ? ( + results.map((data, i) => ( + + )) + ) : ( +
+ No results found +
+ )} +
+
+ ); +} + +function SearchBar(props: InputProps) { + return ( +
+ + +
+ ); +} + +function SortDropdown({ + options, + value, + onChange, +}: { + options: SortBy[]; + value: SortState; + onChange: (v: SortState) => void; +}) { + const onToggleOrder = () => { + onChange({ + ...value, + sortOrder: + value.sortOrder === SortOrderOption.Asc + ? SortOrderOption.Desc + : SortOrderOption.Asc, + }); + }; + + const onSetSortBy = (sortBy: SortBy) => { + onChange({ + ...value, + sortBy, + }); + }; + + return ( +
+
+ Sort +
+ + {toTitleCase(value.sortBy)} + + } + buttonClassname="htw-flex htw-items-stretch hover:htw-bg-gray-100 active:htw-scale-95" + menuClassname="htw-py-1.5 htw-px-2 htw-flex htw-flex-col htw-gap-2 htw-text-sm htw-border htw-border-gray-100" + menuItems={options.map((o) => ( +
onSetSortBy(o)} + > + {toTitleCase(o)} +
+ ))} + menuProps={{ anchor: 'bottom start' }} + /> + + + +
+ ); +} + +function FilterDropdown({ + value, + defaultValue, + onChange, + FilterComponent, +}: { + value: FilterState; + defaultValue: FilterState; + onChange: (v: FilterState) => void; + FilterComponent: ComponentType<{ + value: FilterState; + onChange: (s: FilterState) => void; + }>; +}) { + const filterValues = useMemo(() => { + if (!value || !isObject(value)) return []; + const modifiedKeys = Object.keys(value).filter( + (k) => !deepEquals(value[k], defaultValue[k]), + ); + return modifiedKeys.map((k) => value[k]); + }, [value]); + const hasFilters = filterValues.length > 0; + + const onClear = () => { + onChange(defaultValue); + }; + + return ( +
+
+ Filter +
+ + {hasFilters ? filterValues.map(toTitleCase).join(', ') : 'None'} + + } + buttonClassname="htw-h-full htw-flex htw-items-stretch hover:htw-bg-gray-100 active:htw-scale-95" + > + + + + + +
+ ); +} + +interface ListItemProps { + data: ListItemData; + isEditMode: boolean; + onClickItem: (item: ListItemData) => void; + onClickEditItem: (item: ListItemData) => void; + ListComponent: ComponentType<{ data: ListItemData }>; +} + +function ListItem({ + data, + isEditMode, + onClickEditItem, + onClickItem, + ListComponent, +}: ListItemProps) { + return ( + + ); +} + +export interface SortState { + sortBy: SortBy; + sortOrder: SortOrderOption; +} + +export enum SortOrderOption { + Asc = 'asc', + Desc = 'desc', +} diff --git a/typescript/widgets/src/components/SegmentedControl.tsx b/typescript/widgets/src/components/SegmentedControl.tsx new file mode 100644 index 000000000..71f0096a0 --- /dev/null +++ b/typescript/widgets/src/components/SegmentedControl.tsx @@ -0,0 +1,51 @@ +import React, { useState } from 'react'; + +import { toTitleCase } from '@hyperlane-xyz/utils'; + +interface SegmentedControlProps { + options: O[]; + onChange: (selected: O | undefined) => void; + allowEmpty?: boolean; +} + +export function SegmentedControl({ + options, + onChange, + allowEmpty, +}: SegmentedControlProps) { + // State to keep track of the selected option index + const [selectedIndex, setSelectedIndex] = useState( + allowEmpty ? undefined : 0, + ); + + const handleSelect = (index: number) => { + // Unselect when the same option is re-clicked + if (selectedIndex === index && allowEmpty) { + setSelectedIndex(undefined); + onChange(undefined); + } else { + setSelectedIndex(index); + onChange(options[index]); + } + }; + + return ( +
+ {options.map((option, index) => ( + + ))} +
+ ); +} diff --git a/typescript/widgets/src/components/TextInput.tsx b/typescript/widgets/src/components/TextInput.tsx new file mode 100644 index 000000000..2ddff66cc --- /dev/null +++ b/typescript/widgets/src/components/TextInput.tsx @@ -0,0 +1,25 @@ +import React, { ChangeEvent, InputHTMLAttributes } from 'react'; + +export type InputProps = Omit< + InputHTMLAttributes, + 'onChange' +> & { + onChange?: (v: string) => void; + className?: string; +}; + +export function TextInput({ onChange, className, ...props }: InputProps) { + const handleChange = (e: ChangeEvent) => { + if (onChange) onChange(e?.target?.value || ''); + }; + + return ( + + ); +} diff --git a/typescript/widgets/src/components/Tooltip.tsx b/typescript/widgets/src/components/Tooltip.tsx new file mode 100644 index 000000000..24c591132 --- /dev/null +++ b/typescript/widgets/src/components/Tooltip.tsx @@ -0,0 +1,28 @@ +import React, { AnchorHTMLAttributes } from 'react'; +import { Tooltip as ReactTooltip } from 'react-tooltip'; + +import { Circle } from '../icons/Circle.js'; +import { QuestionMarkIcon } from '../icons/QuestionMark.js'; + +type Props = AnchorHTMLAttributes & { + id: string; + content: string; + size?: number; +}; + +export function Tooltip({ id, content, size = 16, ...rest }: Props) { + return ( + <> + + + + + + + + ); +} diff --git a/typescript/widgets/src/icons/Airplane.tsx b/typescript/widgets/src/icons/Airplane.tsx index c5e2d2782..b2bb4ec3f 100644 --- a/typescript/widgets/src/icons/Airplane.tsx +++ b/typescript/widgets/src/icons/Airplane.tsx @@ -2,23 +2,12 @@ import React, { memo } from 'react'; import { ColorPalette } from '../color.js'; -interface Props { - width?: string | number; - height?: string | number; - color?: string; - classes?: string; -} +import { DefaultIconProps } from './types.js'; // Paper airplane shape -function _AirplaneIcon({ width, height, color, classes }: Props) { +function _AirplaneIcon({ color, ...rest }: DefaultIconProps) { return ( - + & { + direction: 'n' | 'e' | 's' | 'w'; +}; + +function _ArrowIcon({ fill, className, direction, ...rest }: Props) { + let directionClass; + switch (direction) { + case 'n': + directionClass = 'htw-rotate-180'; + break; + case 'e': + directionClass = '-htw-rotate-90'; + break; + case 's': + directionClass = ''; + break; + case 'w': + directionClass = 'htw-rotate-90'; + break; + default: + throw new Error(`Invalid direction ${direction}`); + } + + return ( + + + + ); +} + +export const ArrowIcon = memo(_ArrowIcon); diff --git a/typescript/widgets/src/icons/BoxArrow.tsx b/typescript/widgets/src/icons/BoxArrow.tsx new file mode 100644 index 000000000..43ae2def2 --- /dev/null +++ b/typescript/widgets/src/icons/BoxArrow.tsx @@ -0,0 +1,24 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _BoxArrowIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + + ); +} + +export const BoxArrowIcon = memo(_BoxArrowIcon); diff --git a/typescript/widgets/src/icons/Checkmark.tsx b/typescript/widgets/src/icons/Checkmark.tsx new file mode 100644 index 000000000..d20c3619b --- /dev/null +++ b/typescript/widgets/src/icons/Checkmark.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _CheckmarkIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const CheckmarkIcon = memo(_CheckmarkIcon); diff --git a/typescript/widgets/src/icons/Chevron.tsx b/typescript/widgets/src/icons/Chevron.tsx new file mode 100644 index 000000000..7ca74727a --- /dev/null +++ b/typescript/widgets/src/icons/Chevron.tsx @@ -0,0 +1,46 @@ +import React, { SVGProps, memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +type Props = SVGProps & { + direction: 'n' | 'e' | 's' | 'w'; +}; + +function _ChevronIcon({ color, className, direction, ...rest }: Props) { + let directionClass; + switch (direction) { + case 'n': + directionClass = 'htw-rotate-180'; + break; + case 'e': + directionClass = '-htw-rotate-90'; + break; + case 's': + directionClass = ''; + break; + case 'w': + directionClass = 'htw-rotate-90'; + break; + default: + throw new Error(`Invalid direction ${direction}`); + } + + return ( + + + + ); +} + +export const ChevronIcon = memo(_ChevronIcon); diff --git a/typescript/widgets/src/icons/Circle.tsx b/typescript/widgets/src/icons/Circle.tsx index ef6bac364..6e847e12a 100644 --- a/typescript/widgets/src/icons/Circle.tsx +++ b/typescript/widgets/src/icons/Circle.tsx @@ -6,13 +6,13 @@ export function Circle({ size, title, bgColorSeed, - classes, + className, children, }: PropsWithChildren<{ size: string | number; title?: string; bgColorSeed?: number; - classes?: string; + className?: string; }>) { const bgColor = bgColorSeed === null || bgColorSeed == undefined @@ -21,7 +21,7 @@ export function Circle({ return (
{children} diff --git a/typescript/widgets/src/icons/Copy.tsx b/typescript/widgets/src/icons/Copy.tsx new file mode 100644 index 000000000..faf8bdbb0 --- /dev/null +++ b/typescript/widgets/src/icons/Copy.tsx @@ -0,0 +1,34 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _CopyIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + + ); +} + +export const CopyIcon = memo(_CopyIcon); diff --git a/typescript/widgets/src/icons/Envelope.tsx b/typescript/widgets/src/icons/Envelope.tsx index 777a6548e..1dd0198c6 100644 --- a/typescript/widgets/src/icons/Envelope.tsx +++ b/typescript/widgets/src/icons/Envelope.tsx @@ -2,23 +2,12 @@ import React, { memo } from 'react'; import { ColorPalette } from '../color.js'; -interface Props { - width?: string | number; - height?: string | number; - color?: string; - classes?: string; -} +import { DefaultIconProps } from './types.js'; // Envelope with checkmark -function _EnvelopeIcon({ width, height, color, classes }: Props) { +function _EnvelopeIcon({ color, ...rest }: DefaultIconProps) { return ( - + + + + ); +} + +export const FilterIcon = memo(_FilterIcon); diff --git a/typescript/widgets/src/icons/Funnel.tsx b/typescript/widgets/src/icons/Funnel.tsx new file mode 100644 index 000000000..d2bfc5b50 --- /dev/null +++ b/typescript/widgets/src/icons/Funnel.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _FunnelIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const FunnelIcon = memo(_FunnelIcon); diff --git a/typescript/widgets/src/icons/Gear.tsx b/typescript/widgets/src/icons/Gear.tsx new file mode 100644 index 000000000..044cc828c --- /dev/null +++ b/typescript/widgets/src/icons/Gear.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _GearIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const GearIcon = memo(_GearIcon); diff --git a/typescript/widgets/src/icons/Lock.tsx b/typescript/widgets/src/icons/Lock.tsx index da55c978f..f160712a1 100644 --- a/typescript/widgets/src/icons/Lock.tsx +++ b/typescript/widgets/src/icons/Lock.tsx @@ -2,22 +2,11 @@ import React, { memo } from 'react'; import { ColorPalette } from '../color.js'; -interface Props { - width?: string | number; - height?: string | number; - color?: string; - classes?: string; -} +import { DefaultIconProps } from './types.js'; -function _LockIcon({ width, height, color, classes }: Props) { +function _LockIcon({ color, ...rest }: DefaultIconProps) { return ( - + + + + + ); +} + +export const PencilIcon = memo(_PencilIcon); diff --git a/typescript/widgets/src/icons/Plus.tsx b/typescript/widgets/src/icons/Plus.tsx new file mode 100644 index 000000000..2e9643020 --- /dev/null +++ b/typescript/widgets/src/icons/Plus.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _PlusIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const PlusIcon = memo(_PlusIcon); diff --git a/typescript/widgets/src/icons/PlusCircle.tsx b/typescript/widgets/src/icons/PlusCircle.tsx new file mode 100644 index 000000000..1fa0e10c0 --- /dev/null +++ b/typescript/widgets/src/icons/PlusCircle.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _PlusCircleIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const PlusCircleIcon = memo(_PlusCircleIcon); diff --git a/typescript/widgets/src/icons/QuestionMark.tsx b/typescript/widgets/src/icons/QuestionMark.tsx index 57cf8ef18..4d987746a 100644 --- a/typescript/widgets/src/icons/QuestionMark.tsx +++ b/typescript/widgets/src/icons/QuestionMark.tsx @@ -2,24 +2,13 @@ import React, { memo } from 'react'; import { ColorPalette } from '../color.js'; -interface Props { - width?: string | number; - height?: string | number; - color?: string; - classes?: string; -} +import { DefaultIconProps } from './types.js'; -function _QuestionMarkIcon({ width, height, color, classes }: Props) { +function _QuestionMarkIcon({ color, ...rest }: DefaultIconProps) { return ( - + diff --git a/typescript/widgets/src/icons/Search.tsx b/typescript/widgets/src/icons/Search.tsx new file mode 100644 index 000000000..5fa4bdb8a --- /dev/null +++ b/typescript/widgets/src/icons/Search.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _SearchIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const SearchIcon = memo(_SearchIcon); diff --git a/typescript/widgets/src/icons/Shield.tsx b/typescript/widgets/src/icons/Shield.tsx index 9e97a02de..168593d41 100644 --- a/typescript/widgets/src/icons/Shield.tsx +++ b/typescript/widgets/src/icons/Shield.tsx @@ -2,23 +2,12 @@ import React, { memo } from 'react'; import { ColorPalette } from '../color.js'; -interface Props { - width?: string | number; - height?: string | number; - color?: string; - classes?: string; -} +import { DefaultIconProps } from './types.js'; // Shield with checkmark -function _ShieldIcon({ width, height, color, classes }: Props) { +function _ShieldIcon({ color, ...rest }: DefaultIconProps) { return ( - + + + + + ); +} + +export const Spinner = memo(_Spinner); diff --git a/typescript/widgets/src/icons/UpDownArrows.tsx b/typescript/widgets/src/icons/UpDownArrows.tsx new file mode 100644 index 000000000..6a84eb2ff --- /dev/null +++ b/typescript/widgets/src/icons/UpDownArrows.tsx @@ -0,0 +1,19 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _UpDownArrowsIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const UpDownArrowsIcon = memo(_UpDownArrowsIcon); diff --git a/typescript/widgets/src/icons/WideChevron.tsx b/typescript/widgets/src/icons/WideChevron.tsx index 8cb91412d..83ecb8323 100644 --- a/typescript/widgets/src/icons/WideChevron.tsx +++ b/typescript/widgets/src/icons/WideChevron.tsx @@ -2,14 +2,12 @@ import React, { memo } from 'react'; import { ColorPalette } from '../color.js'; -export interface WideChevronProps { - width?: string | number; - height?: string | number; +import { DefaultIconProps } from './types.js'; + +export type WideChevronProps = DefaultIconProps & { direction: 'n' | 'e' | 's' | 'w'; - color?: string; rounded?: boolean; - classes?: string; -} +}; function _WideChevron({ width, @@ -17,7 +15,8 @@ function _WideChevron({ direction, color, rounded, - classes, + className, + ...rest }: WideChevronProps) { let directionClass; switch (direction) { @@ -45,7 +44,8 @@ function _WideChevron({ width={width} height={height} fill={color || ColorPalette.Blue} - className={`${directionClass} ${classes}`} + className={`${directionClass} ${className}`} + {...rest} > @@ -57,7 +57,8 @@ function _WideChevron({ viewBox="0 0 28 27" width={width} height={height} - className={`${directionClass} ${classes}`} + className={`${directionClass} ${className}`} + {...rest} > + + + ); +} + +export const XIcon = memo(_XIcon); diff --git a/typescript/widgets/src/icons/types.ts b/typescript/widgets/src/icons/types.ts new file mode 100644 index 000000000..6e4756c51 --- /dev/null +++ b/typescript/widgets/src/icons/types.ts @@ -0,0 +1,5 @@ +import { SVGProps } from 'react'; + +export type DefaultIconProps = SVGProps & { + color?: string; +}; diff --git a/typescript/widgets/src/index.ts b/typescript/widgets/src/index.ts index 43fe2b7f6..0a25bc9a5 100644 --- a/typescript/widgets/src/index.ts +++ b/typescript/widgets/src/index.ts @@ -1,8 +1,45 @@ +export { + ChainDetailsMenu, + type ChainDetailsMenuProps, +} from './chains/ChainDetailsMenu.js'; +export { ChainLogo } from './chains/ChainLogo.js'; +export { + ChainSearchMenu, + type ChainSearchMenuProps, +} from './chains/ChainSearchMenu.js'; export { ColorPalette, seedToBgColor } from './color.js'; +export { CopyButton } from './components/CopyButton.js'; +export { IconButton } from './components/IconButton.js'; +export { LinkButton } from './components/LinkButton.js'; +export { SegmentedControl } from './components/SegmentedControl.js'; +export { TextInput } from './components/TextInput.js'; +export { Tooltip } from './components/Tooltip.js'; export * from './consts.js'; -export { ChainLogo } from './icons/ChainLogo.js'; +export { AirplaneIcon } from './icons/Airplane.js'; +export { ArrowIcon } from './icons/Arrow.js'; +export { BoxArrowIcon } from './icons/BoxArrow.js'; +export { CheckmarkIcon } from './icons/Checkmark.js'; +export { ChevronIcon } from './icons/Chevron.js'; export { Circle } from './icons/Circle.js'; +export { CopyIcon } from './icons/Copy.js'; +export { EnvelopeIcon } from './icons/Envelope.js'; +export { FilterIcon } from './icons/Filter.js'; +export { FunnelIcon } from './icons/Funnel.js'; +export { GearIcon } from './icons/Gear.js'; +export { LockIcon } from './icons/Lock.js'; +export { PlusIcon } from './icons/Plus.js'; +export { PlusCircleIcon } from './icons/PlusCircle.js'; +export { QuestionMarkIcon } from './icons/QuestionMark.js'; +export { SearchIcon } from './icons/Search.js'; +export { ShieldIcon } from './icons/Shield.js'; +export { Spinner } from './icons/Spinner.js'; +export { UpDownArrowsIcon } from './icons/UpDownArrows.js'; export { WideChevron } from './icons/WideChevron.js'; +export { XIcon } from './icons/X.js'; +export { DropdownMenu, type DropdownMenuProps } from './layout/DropdownMenu.js'; +export { Modal, useModal, type ModalProps } from './layout/Modal.js'; +export { Popover, type PopoverProps } from './layout/Popover.js'; +export { HyperlaneLogo } from './logos/Hyperlane.js'; export { MessageTimeline } from './messages/MessageTimeline.js'; export { MessageStage, @@ -13,3 +50,9 @@ export { export { useMessage } from './messages/useMessage.js'; export { useMessageStage } from './messages/useMessageStage.js'; export { useMessageTimeline } from './messages/useMessageTimeline.js'; +export { + isClipboardReadSupported, + tryClipboardGet, + tryClipboardSet, +} from './utils/clipboard.js'; +export { useConnectionHealthTest } from './utils/useChainConnectionTest.js'; diff --git a/typescript/widgets/src/layout/DropdownMenu.tsx b/typescript/widgets/src/layout/DropdownMenu.tsx new file mode 100644 index 000000000..837a219e7 --- /dev/null +++ b/typescript/widgets/src/layout/DropdownMenu.tsx @@ -0,0 +1,45 @@ +import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'; +import clsx from 'clsx'; +import React, { ComponentProps, ReactNode } from 'react'; + +export type DropdownMenuProps = { + button: ReactNode; + buttonClassname?: string; + buttonProps?: ComponentProps; + menuClassname?: string; + menuProps?: ComponentProps; + menuItems: Array['children']>; +}; + +export function DropdownMenu({ + button, + buttonClassname, + buttonProps, + menuClassname, + menuProps, + menuItems, +}: DropdownMenuProps) { + return ( + + + {button} + + + {menuItems.map((mi, i) => ( + {mi} + ))} + + + ); +} diff --git a/typescript/widgets/src/layout/Modal.tsx b/typescript/widgets/src/layout/Modal.tsx new file mode 100644 index 000000000..87c36e831 --- /dev/null +++ b/typescript/widgets/src/layout/Modal.tsx @@ -0,0 +1,74 @@ +import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react'; +import clsx from 'clsx'; +import React, { ComponentProps, PropsWithChildren, useState } from 'react'; + +import { IconButton } from '../components/IconButton.js'; +import { XIcon } from '../icons/X.js'; + +export function useModal() { + const [isOpen, setIsOpen] = useState(false); + const open = () => setIsOpen(true); + const close = () => setIsOpen(false); + return { isOpen, open, close }; +} + +export type ModalProps = PropsWithChildren<{ + isOpen: boolean; + close: () => void; + dialogClassname?: string; + dialogProps?: ComponentProps; + panelClassname?: string; + panelProps?: ComponentProps; + showCloseButton?: boolean; +}>; + +export function Modal({ + isOpen, + close, + dialogClassname, + dialogProps, + panelClassname, + panelProps, + showCloseButton, + children, +}: ModalProps) { + return ( + + +
+
+ + {children} + {showCloseButton && ( +
+ + + +
+ )} +
+
+
+
+ ); +} diff --git a/typescript/widgets/src/layout/Popover.tsx b/typescript/widgets/src/layout/Popover.tsx new file mode 100644 index 000000000..34e7793fb --- /dev/null +++ b/typescript/widgets/src/layout/Popover.tsx @@ -0,0 +1,47 @@ +import { + PopoverButton, + PopoverPanel, + Popover as _Popover, +} from '@headlessui/react'; +import clsx from 'clsx'; +import React, { ComponentProps, ReactNode } from 'react'; + +export type PopoverProps = { + button: ReactNode; + buttonClassname?: string; + buttonProps?: ComponentProps; + panelClassname?: string; + panelProps?: ComponentProps; + children: ComponentProps['children']; +}; + +export function Popover({ + button, + buttonClassname, + buttonProps, + panelClassname, + panelProps, + children, +}: PopoverProps) { + return ( + <_Popover> + + {button} + + + {children} + + + ); +} diff --git a/typescript/widgets/src/logos/Hyperlane.tsx b/typescript/widgets/src/logos/Hyperlane.tsx new file mode 100644 index 000000000..4fc430315 --- /dev/null +++ b/typescript/widgets/src/logos/Hyperlane.tsx @@ -0,0 +1,25 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; +import { DefaultIconProps } from '../icons/types.js'; + +function _HyperlaneLogo({ color, ...rest }: DefaultIconProps) { + return ( + + + + + + ); +} + +export const HyperlaneLogo = memo(_HyperlaneLogo); diff --git a/typescript/widgets/src/messages/useMessageStage.ts b/typescript/widgets/src/messages/useMessageStage.ts index 2910a6667..54345d4a9 100644 --- a/typescript/widgets/src/messages/useMessageStage.ts +++ b/typescript/widgets/src/messages/useMessageStage.ts @@ -1,10 +1,10 @@ import { useCallback, useState } from 'react'; import type { MultiProvider } from '@hyperlane-xyz/sdk'; +import { fetchWithTimeout } from '@hyperlane-xyz/utils'; import { HYPERLANE_EXPLORER_API_URL } from '../consts.js'; import { queryExplorerForBlock } from '../utils/explorers.js'; -import { fetchWithTimeout } from '../utils/timeout.js'; import { useInterval } from '../utils/useInterval.js'; import { diff --git a/typescript/widgets/src/stories/ChainDetailsMenu.stories.tsx b/typescript/widgets/src/stories/ChainDetailsMenu.stories.tsx new file mode 100644 index 000000000..37bac19be --- /dev/null +++ b/typescript/widgets/src/stories/ChainDetailsMenu.stories.tsx @@ -0,0 +1,42 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { chainMetadata } from '@hyperlane-xyz/registry'; + +import { ChainDetailsMenu } from '../chains/ChainDetailsMenu.js'; + +const meta = { + title: 'ChainDetailsMenu', + component: ChainDetailsMenu, +} satisfies Meta; +export default meta; +type Story = StoryObj; + +export const DefaultChainDetails = { + args: { + chainMetadata: chainMetadata['ethereum'], + overrideChainMetadata: undefined, + onChangeOverrideMetadata: () => {}, + onClickBack: undefined, + onRemoveChain: undefined, + }, +} satisfies Story; + +export const PartialOverrideChainDetails = { + args: { + chainMetadata: chainMetadata['ethereum'], + overrideChainMetadata: { rpcUrls: [{ http: 'https://rpc.fakeasdf.com' }] }, + onChangeOverrideMetadata: () => {}, + onClickBack: undefined, + onRemoveChain: undefined, + }, +} satisfies Story; + +export const FullOverrideChainDetails = { + args: { + chainMetadata: chainMetadata['arbitrum'], + overrideChainMetadata: chainMetadata['arbitrum'], + onChangeOverrideMetadata: () => {}, + onClickBack: () => {}, + onRemoveChain: () => {}, + }, +} satisfies Story; diff --git a/typescript/widgets/src/stories/ChainLogo.stories.tsx b/typescript/widgets/src/stories/ChainLogo.stories.tsx index 190db6ec3..312103cbf 100644 --- a/typescript/widgets/src/stories/ChainLogo.stories.tsx +++ b/typescript/widgets/src/stories/ChainLogo.stories.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { GithubRegistry } from '@hyperlane-xyz/registry'; -import { ChainLogo } from '../icons/ChainLogo.js'; +import { ChainLogo } from '../chains/ChainLogo.js'; export default { title: 'ChainLogo', @@ -15,6 +15,7 @@ const Template: ComponentStory = (args) => ( ); const registry = new GithubRegistry(); +await registry.getMetadata(); export const ChainNoBackground = Template.bind({}); ChainNoBackground.args = { @@ -56,3 +57,11 @@ FakeChainName.args = { chainName: 'myfakechain', registry, }; + +export const SpecificLogoUri = Template.bind({}); +SpecificLogoUri.args = { + chainName: 'myfakechain', + logoUri: + 'https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/main/chains/arbitrum/logo.svg', + registry, +}; diff --git a/typescript/widgets/src/stories/ChainSearchMenu.stories.tsx b/typescript/widgets/src/stories/ChainSearchMenu.stories.tsx new file mode 100644 index 000000000..0d31f1c6c --- /dev/null +++ b/typescript/widgets/src/stories/ChainSearchMenu.stories.tsx @@ -0,0 +1,48 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { chainMetadata } from '@hyperlane-xyz/registry'; +import { pick } from '@hyperlane-xyz/utils'; + +import { ChainSearchMenu } from '../chains/ChainSearchMenu.js'; + +const meta = { + title: 'ChainSearchMenu', + component: ChainSearchMenu, +} satisfies Meta; +export default meta; +type Story = StoryObj; + +export const DefaultChainSearch = { + args: { + chainMetadata, + onChangeOverrideMetadata: () => {}, + onClickChain: (chain) => console.log('Clicked', chain), + }, +} satisfies Story; + +export const WithCustomField = { + args: { + chainMetadata: pick(chainMetadata, ['alfajores', 'arbitrum', 'ethereum']), + onChangeOverrideMetadata: () => {}, + customListItemField: { + header: 'Warp Routes', + data: { + alfajores: { display: '1 token', sortValue: 1 }, + arbitrum: { display: '2 tokens', sortValue: 2 }, + ethereum: { display: '1 token', sortValue: 1 }, + }, + }, + showAddChainButton: true, + }, +} satisfies Story; + +export const WithOverrideChain = { + args: { + chainMetadata: pick(chainMetadata, ['alfajores']), + overrideChainMetadata: { + arbitrum: { ...chainMetadata['arbitrum'], displayName: 'Fake Arb' }, + }, + onChangeOverrideMetadata: () => {}, + showAddChainButton: true, + }, +} satisfies Story; diff --git a/typescript/widgets/src/stories/Modal.stories.tsx b/typescript/widgets/src/stories/Modal.stories.tsx new file mode 100644 index 000000000..ea667df31 --- /dev/null +++ b/typescript/widgets/src/stories/Modal.stories.tsx @@ -0,0 +1,36 @@ +import { Button } from '@headlessui/react'; +import { Meta, StoryObj } from '@storybook/react'; +import React, { useState } from 'react'; + +import { Modal } from '../layout/Modal.js'; + +function MyModal() { + const [isOpen, setIsOpen] = useState(false); + const open = () => setIsOpen(true); + const close = () => setIsOpen(false); + + return ( + <> + + +
Hello Modal
+
+ + ); +} + +const meta = { + title: 'Modal', + component: MyModal, +} satisfies Meta; +export default meta; +type Story = StoryObj; + +export const BasicModal = { + args: {}, +} satisfies Story; diff --git a/typescript/widgets/src/styles.css b/typescript/widgets/src/styles.css index b5c61c956..c97653790 100755 --- a/typescript/widgets/src/styles.css +++ b/typescript/widgets/src/styles.css @@ -1,3 +1,16 @@ @tailwind base; @tailwind components; @tailwind utilities; + +/* Tailwind extension to hide scrollbar */ +@layer utilities { + /* Chrome, Safari and Opera */ + .no-scrollbar::-webkit-scrollbar { + display: none; + } + + .no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } +} diff --git a/typescript/widgets/src/utils/clipboard.ts b/typescript/widgets/src/utils/clipboard.ts new file mode 100644 index 000000000..eb331af45 --- /dev/null +++ b/typescript/widgets/src/utils/clipboard.ts @@ -0,0 +1,24 @@ +export function isClipboardReadSupported() { + return !!navigator?.clipboard?.readText; +} + +export async function tryClipboardSet(value: string) { + try { + await navigator.clipboard.writeText(value); + return true; + } catch (error) { + console.error('Failed to set clipboard', error); + return false; + } +} + +export async function tryClipboardGet() { + try { + // Note: doesn't work in firefox, which only allows extensions to read clipboard + const value = await navigator.clipboard.readText(); + return value; + } catch (error) { + console.error('Failed to read from clipboard', error); + return null; + } +} diff --git a/typescript/widgets/src/utils/explorers.ts b/typescript/widgets/src/utils/explorers.ts index 95e9f264a..38c470d31 100644 --- a/typescript/widgets/src/utils/explorers.ts +++ b/typescript/widgets/src/utils/explorers.ts @@ -1,6 +1,5 @@ import type { MultiProvider } from '@hyperlane-xyz/sdk'; - -import { fetchWithTimeout } from './timeout.js'; +import { fetchWithTimeout } from '@hyperlane-xyz/utils'; export interface ExplorerQueryResponse { status: string; diff --git a/typescript/widgets/src/utils/timeout.ts b/typescript/widgets/src/utils/timeout.ts deleted file mode 100644 index fe2641ef7..000000000 --- a/typescript/widgets/src/utils/timeout.ts +++ /dev/null @@ -1,14 +0,0 @@ -export async function fetchWithTimeout( - resource: RequestInfo, - options?: RequestInit, - timeout = 10000, -) { - const controller = new AbortController(); - const id = setTimeout(() => controller.abort(), timeout); - const response = await fetch(resource, { - ...options, - signal: controller.signal, - }); - clearTimeout(id); - return response; -} diff --git a/typescript/widgets/src/utils/useChainConnectionTest.ts b/typescript/widgets/src/utils/useChainConnectionTest.ts new file mode 100644 index 000000000..920b2e7dd --- /dev/null +++ b/typescript/widgets/src/utils/useChainConnectionTest.ts @@ -0,0 +1,32 @@ +import { useEffect, useState } from 'react'; + +import { + ChainMetadata, + isBlockExplorerHealthy, + isRpcHealthy, +} from '@hyperlane-xyz/sdk'; +import { timeout } from '@hyperlane-xyz/utils'; + +import { ChainConnectionType } from '../chains/types.js'; + +const HEALTH_TEST_TIMEOUT = 5000; // 5s + +export function useConnectionHealthTest( + chainMetadata: ChainMetadata, + index: number, + type: ChainConnectionType, +) { + const [isHealthy, setIsHealthy] = useState(undefined); + const tester = + type === ChainConnectionType.RPC ? isRpcHealthy : isBlockExplorerHealthy; + + useEffect(() => { + // TODO run explorer test through CORS proxy, otherwise it's blocked by browser + if (type === ChainConnectionType.Explorer) return; + timeout(tester(chainMetadata, index), HEALTH_TEST_TIMEOUT) + .then((result) => setIsHealthy(result)) + .catch(() => setIsHealthy(false)); + }, [chainMetadata, index, tester]); + + return isHealthy; +} diff --git a/typescript/widgets/tailwind.config.cjs b/typescript/widgets/tailwind.config.cjs index 2fba31f93..f410968ec 100644 --- a/typescript/widgets/tailwind.config.cjs +++ b/typescript/widgets/tailwind.config.cjs @@ -25,7 +25,7 @@ module.exports = { 200: '#A7C2EC', 300: '#82A8E4', 400: '#5385D2', - 500: '#2362C0', + 500: '#2764c1', 600: '#1D4685', 700: '#162A4A', 800: '#11213B', @@ -66,16 +66,16 @@ module.exports = { 900: '#0F2F1E', }, pink: { - 50: '#FAEAF7', - 100: '#F0C0E8', - 200: '#EBABE0', - 300: '#E282D1', - 400: '#D858C2', - 500: '#CF2FB3', - 600: '#BA2AA1', - 700: '#A5258F', - 800: '#90207D', - 900: '#7C1C6B', + 50: '#FAEAF8', + 100: '#F2C1EA', + 200: '#EA98DC', + 300: '#E26ECE', + 400: '#DA45C0', + 500: '#D631B9', + 600: '#C02CA6', + 700: '#952281', + 800: '#6B185C', + 900: '#400E37', } }, fontSize: { diff --git a/yarn.lock b/yarn.lock index 99a2f1fe7..15930aeb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7571,6 +7571,16 @@ __metadata: languageName: node linkType: hard +"@floating-ui/dom@npm:^1.6.1": + version: 1.6.10 + resolution: "@floating-ui/dom@npm:1.6.10" + dependencies: + "@floating-ui/core": "npm:^1.6.0" + "@floating-ui/utils": "npm:^0.2.7" + checksum: c100f5ecb37fc1bea4e551977eae3992f8eba351e6b7f2642e2f84a4abd269406d5a46a14505bc583caf25ddee900a667829244c4eecf1cf60f08c1dabdf3ee9 + languageName: node + linkType: hard + "@floating-ui/react-dom@npm:^2.0.0": version: 2.1.1 resolution: "@floating-ui/react-dom@npm:2.1.1" @@ -7583,6 +7593,32 @@ __metadata: languageName: node linkType: hard +"@floating-ui/react-dom@npm:^2.1.2": + version: 2.1.2 + resolution: "@floating-ui/react-dom@npm:2.1.2" + dependencies: + "@floating-ui/dom": "npm:^1.0.0" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 2a67dc8499674e42ff32c7246bded185bb0fdd492150067caf9568569557ac4756a67787421d8604b0f241e5337de10762aee270d9aeef106d078a0ff13596c4 + languageName: node + linkType: hard + +"@floating-ui/react@npm:^0.26.16": + version: 0.26.24 + resolution: "@floating-ui/react@npm:0.26.24" + dependencies: + "@floating-ui/react-dom": "npm:^2.1.2" + "@floating-ui/utils": "npm:^0.2.8" + tabbable: "npm:^6.0.0" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 903ffbee2c6726d117086e2a83f43d6ad339970758ce7979fd16cc7cf8dc0f5b869bd72c2c8ee1bcd6c63b190bb0960effd4d403e63685fb5aeed6b185041b08 + languageName: node + linkType: hard + "@floating-ui/utils@npm:^0.2.5": version: 0.2.5 resolution: "@floating-ui/utils@npm:0.2.5" @@ -7590,6 +7626,20 @@ __metadata: languageName: node linkType: hard +"@floating-ui/utils@npm:^0.2.7": + version: 0.2.7 + resolution: "@floating-ui/utils@npm:0.2.7" + checksum: 56b1bb3f73f6ec9aabf9b1fd3dc584e0f2384d319c1a6119050eab102ae6ca8b9b0eed711c2f235ffe035188cbe9727bf36e8dcb54c8bd32176737e4be47efa8 + languageName: node + linkType: hard + +"@floating-ui/utils@npm:^0.2.8": + version: 0.2.8 + resolution: "@floating-ui/utils@npm:0.2.8" + checksum: 3e3ea3b2de06badc4baebdf358b3dbd77ccd9474a257a6ef237277895943db2acbae756477ec64de65a2a1436d94aea3107129a1feeef6370675bf2b161c1abc + languageName: node + linkType: hard + "@ganache/ethereum-address@npm:0.1.4": version: 0.1.4 resolution: "@ganache/ethereum-address@npm:0.1.4" @@ -7706,6 +7756,21 @@ __metadata: languageName: node linkType: hard +"@headlessui/react@npm:^2.1.8": + version: 2.1.8 + resolution: "@headlessui/react@npm:2.1.8" + dependencies: + "@floating-ui/react": "npm:^0.26.16" + "@react-aria/focus": "npm:^3.17.1" + "@react-aria/interactions": "npm:^3.21.3" + "@tanstack/react-virtual": "npm:^3.8.1" + peerDependencies: + react: ^18 + react-dom: ^18 + checksum: a82f115877dcc5e3d16a6b0502b6796a5bd3f38936835e241833a538c002d4ecfc3317868b0d1e9655e5de93201b0806f51bc10dbf32604e270cda4fc1636024 + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" @@ -8043,8 +8108,10 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: + "@headlessui/react": "npm:^2.1.8" "@hyperlane-xyz/registry": "npm:4.3.6" "@hyperlane-xyz/sdk": "npm:5.4.0" + "@hyperlane-xyz/utils": "npm:5.4.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" @@ -8060,6 +8127,7 @@ __metadata: "@typescript-eslint/eslint-plugin": "npm:^7.4.0" "@typescript-eslint/parser": "npm:^7.4.0" babel-loader: "npm:^8.3.0" + clsx: "npm:^2.1.1" eslint: "npm:^8.57.0" eslint-config-prettier: "npm:^9.1.0" eslint-plugin-storybook: "npm:^0.6.15" @@ -8067,8 +8135,9 @@ __metadata: prettier: "npm:^2.8.8" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" + react-tooltip: "npm:^5.28.0" storybook: "npm:^7.6.14" - tailwindcss: "npm:^3.2.4" + tailwindcss: "npm:^3.4.13" ts-node: "npm:^10.8.0" typescript: "npm:5.3.3" vite: "npm:^5.1.1" @@ -10617,6 +10686,81 @@ __metadata: languageName: node linkType: hard +"@react-aria/focus@npm:^3.17.1": + version: 3.18.2 + resolution: "@react-aria/focus@npm:3.18.2" + dependencies: + "@react-aria/interactions": "npm:^3.22.2" + "@react-aria/utils": "npm:^3.25.2" + "@react-types/shared": "npm:^3.24.1" + "@swc/helpers": "npm:^0.5.0" + clsx: "npm:^2.0.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + checksum: 4243764952737ec33f463534e69c7d581073d5531ae87504d574083a4d9a08a9e3b5a8e2b69a936bf6476a35eb8cf38db751d52629e66451be58a6c635ce9449 + languageName: node + linkType: hard + +"@react-aria/interactions@npm:^3.21.3, @react-aria/interactions@npm:^3.22.2": + version: 3.22.2 + resolution: "@react-aria/interactions@npm:3.22.2" + dependencies: + "@react-aria/ssr": "npm:^3.9.5" + "@react-aria/utils": "npm:^3.25.2" + "@react-types/shared": "npm:^3.24.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + checksum: df0ce7d438b6f9d04774120ed6a3b66ef928e8e8ce97af42b12a5feabcd8d6cdd858e14cd6ccf602bbe8c0dbb620ce94bd974f1e2b832f497c7125647f8be471 + languageName: node + linkType: hard + +"@react-aria/ssr@npm:^3.9.5": + version: 3.9.5 + resolution: "@react-aria/ssr@npm:3.9.5" + dependencies: + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + checksum: 0284561e7b084c567fd8f35e7982f201582acc937b950be8411678352682c7b45ad3ab99272cd2d6f0b4919ddaa5b0e553d784f190d1d05ceb8594bfee3f763e + languageName: node + linkType: hard + +"@react-aria/utils@npm:^3.25.2": + version: 3.25.2 + resolution: "@react-aria/utils@npm:3.25.2" + dependencies: + "@react-aria/ssr": "npm:^3.9.5" + "@react-stately/utils": "npm:^3.10.3" + "@react-types/shared": "npm:^3.24.1" + "@swc/helpers": "npm:^0.5.0" + clsx: "npm:^2.0.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + checksum: c0dbbff1f93b3f275e6db2f01c7a09ffd96da57fd373a8b3b3cb5dbb0aca99d721c2453fbd742800d0df2fbb0ffa5f3052669bbb2998db753b1090f573d5ef7b + languageName: node + linkType: hard + +"@react-stately/utils@npm:^3.10.3": + version: 3.10.3 + resolution: "@react-stately/utils@npm:3.10.3" + dependencies: + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + checksum: 0ac737e678d949787d05889bfd67047ed0ee91d93a8d727c89d7a7568a027d0cf4a53cebad13e6526c2322f51069bbaa40d5912364230e6b9374cf653683a73d + languageName: node + linkType: hard + +"@react-types/shared@npm:^3.24.1": + version: 3.24.1 + resolution: "@react-types/shared@npm:3.24.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + checksum: 5472ae35f65b2ed7c12d5ea4459f34b4aec065d2633844031d27945495b6dca6fa9bf02b6392b901fac97252e58d9b91a4baf53f4c281397fb81ce85c73b8648 + languageName: node + linkType: hard + "@resolver-engine/core@npm:^0.3.3": version: 0.3.3 resolution: "@resolver-engine/core@npm:0.3.3" @@ -12658,6 +12802,15 @@ __metadata: languageName: node linkType: hard +"@swc/helpers@npm:^0.5.0": + version: 0.5.13 + resolution: "@swc/helpers@npm:0.5.13" + dependencies: + tslib: "npm:^2.4.0" + checksum: 6ba2f7e215d32d71fce139e2cfc426b3ed7eaa709febdeb07b97260a4c9eea4784cf047cc1271be273990b08220b576b94a42b5780947c0b3be84973a847a24d + languageName: node + linkType: hard + "@szmarczak/http-timer@npm:^5.0.1": version: 5.0.1 resolution: "@szmarczak/http-timer@npm:5.0.1" @@ -12667,6 +12820,25 @@ __metadata: languageName: node linkType: hard +"@tanstack/react-virtual@npm:^3.8.1": + version: 3.10.8 + resolution: "@tanstack/react-virtual@npm:3.10.8" + dependencies: + "@tanstack/virtual-core": "npm:3.10.8" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 40a5d6089908096634fec2aa0cd646ca47c044c745e1b0d190ecbf9905ad2e6266ccd56c2550ed92f47349954dc11eb6930beac1354441ce7c98af81c5454d3f + languageName: node + linkType: hard + +"@tanstack/virtual-core@npm:3.10.8": + version: 3.10.8 + resolution: "@tanstack/virtual-core@npm:3.10.8" + checksum: 047e95fa72a0d341c0da8468799c176fd448481432f976a4780911bb4a2256aa4788d828f79fad78d127fe859b785189c13ca0fea10c560bf14d8ab8cb2c7790 + languageName: node + linkType: hard + "@testing-library/dom@npm:^9.3.1": version: 9.3.4 resolution: "@testing-library/dom@npm:9.3.4" @@ -16318,6 +16490,13 @@ __metadata: languageName: node linkType: hard +"classnames@npm:^2.3.0": + version: 2.5.1 + resolution: "classnames@npm:2.5.1" + checksum: 58eb394e8817021b153bb6e7d782cfb667e4ab390cb2e9dac2fc7c6b979d1cc2b2a733093955fc5c94aa79ef5c8c89f11ab77780894509be6afbb91dddd79d15 + languageName: node + linkType: hard + "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -16500,6 +16679,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^2.0.0, clsx@npm:^2.1.1": + version: 2.1.1 + resolution: "clsx@npm:2.1.1" + checksum: cdfb57fa6c7649bbff98d9028c2f0de2f91c86f551179541cf784b1cfdc1562dcb951955f46d54d930a3879931a980e32a46b598acaea274728dbe068deca919 + languageName: node + linkType: hard + "co@npm:^4.6.0": version: 4.6.0 resolution: "co@npm:4.6.0" @@ -26947,6 +27133,19 @@ __metadata: languageName: node linkType: hard +"react-tooltip@npm:^5.28.0": + version: 5.28.0 + resolution: "react-tooltip@npm:5.28.0" + dependencies: + "@floating-ui/dom": "npm:^1.6.1" + classnames: "npm:^2.3.0" + peerDependencies: + react: ">=16.14.0" + react-dom: ">=16.14.0" + checksum: ec13ad0fafcae51c9c1193c6f0bccba4e7047e9d02eaf77231474cefd1a3d05254e76f27229808e79dad4c0a8c47b8e5cafdad47920e34a11d7a2703adf5f998 + languageName: node + linkType: hard + "react@npm:^18.2.0": version: 18.3.1 resolution: "react@npm:18.3.1" @@ -29466,6 +29665,13 @@ __metadata: languageName: node linkType: hard +"tabbable@npm:^6.0.0": + version: 6.2.0 + resolution: "tabbable@npm:6.2.0" + checksum: 980fa73476026e99dcacfc0d6e000d41d42c8e670faf4682496d30c625495e412c4369694f2a15cf1e5252d22de3c396f2b62edbe8d60b5dadc40d09e3f2dde3 + languageName: node + linkType: hard + "table-layout@npm:^1.0.2": version: 1.0.2 resolution: "table-layout@npm:1.0.2" @@ -29504,9 +29710,9 @@ __metadata: languageName: node linkType: hard -"tailwindcss@npm:^3.2.4": - version: 3.4.7 - resolution: "tailwindcss@npm:3.4.7" +"tailwindcss@npm:^3.4.13": + version: 3.4.13 + resolution: "tailwindcss@npm:3.4.13" dependencies: "@alloc/quick-lru": "npm:^5.2.0" arg: "npm:^5.0.2" @@ -29533,7 +29739,7 @@ __metadata: bin: tailwind: lib/cli.js tailwindcss: lib/cli.js - checksum: bda3280905b05bb3e7e95a350e028a58a19336a854ebebe65816c7625ec49ba4d2af7ef82c169407f67cbf150fb6acbe1210e8ade7e0180fa8039e3607077304 + checksum: 01b8dd35a65a028474c632b9ea7fb38634060a2c70f1f3fdfa2fe6ec74dec8224e2ee1178a5428182849790dad324e7a810de7301a9126946528c59d37f455cf languageName: node linkType: hard From 6176c9861d5c58d93a4a84252d53b08a0033c961 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 9 Oct 2024 18:51:02 +0100 Subject: [PATCH 122/224] feat: add more options to ChainTechnicalStack enum (#4656) ### Description Adding more technical stack options to the `ChainTechnicalStack` enum, to be used to populate metadata in the registry. Including `zksync` pre-emptively. ### Drive-by changes n/a ### Related issues https://www.notion.so/hyperlanexyz/Adding-more-technical-stacks-to-chain-metadata-11a6d35200d68015a229da552928d4d9?pvs=4 ### Backward compatibility yes ### Testing na --- .changeset/gorgeous-rockets-walk.md | 5 +++++ typescript/sdk/src/metadata/chainMetadataTypes.ts | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 .changeset/gorgeous-rockets-walk.md diff --git a/.changeset/gorgeous-rockets-walk.md b/.changeset/gorgeous-rockets-walk.md new file mode 100644 index 000000000..e95acc681 --- /dev/null +++ b/.changeset/gorgeous-rockets-walk.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Add opstack, polygoncdk, polkadotsubstrate and zksync to ChainTechnicalStack enum diff --git a/typescript/sdk/src/metadata/chainMetadataTypes.ts b/typescript/sdk/src/metadata/chainMetadataTypes.ts index bdee44179..caf290ced 100644 --- a/typescript/sdk/src/metadata/chainMetadataTypes.ts +++ b/typescript/sdk/src/metadata/chainMetadataTypes.ts @@ -19,6 +19,10 @@ export enum ExplorerFamily { export enum ChainTechnicalStack { ArbitrumNitro = 'arbitrumnitro', + OpStack = 'opstack', + PolygonCDK = 'polygoncdk', + PolkadotSubstrate = 'polkadotsubstrate', + ZkSync = 'zksync', Other = 'other', } From 70bb863e34f67c0e8de78fa33c938d80c9968364 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 19:26:41 +0000 Subject: [PATCH 123/224] Version Packages (#4648) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/sdk@5.5.0 ### Minor Changes - 2afc484a2: Break out BlockExplorerSchema and export separately Migrate RPC + Explorer health tests back to SDK from registry - 3254472e0: Add deployments for chains: immutablezkevm, rari, rootstock, alephzeroevm, chiliz, lumia, and superposition - 6176c9861: Add opstack, polygoncdk, polkadotsubstrate and zksync to ChainTechnicalStack enum ### Patch Changes - fcfe91113: Reuse SDK transaction typings in tx submitters - Updated dependencies [92c86cca6] - Updated dependencies [2afc484a2] - @hyperlane-xyz/core@5.4.1 - @hyperlane-xyz/utils@5.5.0 ## @hyperlane-xyz/utils@5.5.0 ### Minor Changes - 2afc484a2: Migrate fetchWithTimeout from widgets to utils Add objSlice function and improve types for objMerge Add isUrl function ## @hyperlane-xyz/widgets@5.5.0 ### Minor Changes - 2afc484a2: Create ChainSearchMenu and ChainDetailsMenu components Add required icon and button components Add persisted zustand store and hooks Add clipboard utility functions ### Patch Changes - Updated dependencies [2afc484a2] - Updated dependencies [2afc484a2] - Updated dependencies [3254472e0] - Updated dependencies [fcfe91113] - Updated dependencies [6176c9861] - @hyperlane-xyz/sdk@5.5.0 - @hyperlane-xyz/utils@5.5.0 ## @hyperlane-xyz/core@5.4.1 ### Patch Changes - 92c86cca6: Forward value from ICA router to proxy for multicall - Updated dependencies [2afc484a2] - @hyperlane-xyz/utils@5.5.0 ## @hyperlane-xyz/cli@5.5.0 ### Patch Changes - fcfe91113: Reuse SDK transaction typings in tx submitters - Updated dependencies [2afc484a2] - Updated dependencies [2afc484a2] - Updated dependencies [3254472e0] - Updated dependencies [fcfe91113] - Updated dependencies [6176c9861] - @hyperlane-xyz/sdk@5.5.0 - @hyperlane-xyz/utils@5.5.0 ## @hyperlane-xyz/helloworld@5.5.0 ### Patch Changes - Updated dependencies [92c86cca6] - Updated dependencies [2afc484a2] - Updated dependencies [3254472e0] - Updated dependencies [fcfe91113] - Updated dependencies [6176c9861] - @hyperlane-xyz/core@5.4.1 - @hyperlane-xyz/sdk@5.5.0 ## @hyperlane-xyz/infra@5.5.0 ### Patch Changes - Updated dependencies [2afc484a2] - Updated dependencies [2afc484a2] - Updated dependencies [3254472e0] - Updated dependencies [fcfe91113] - Updated dependencies [6176c9861] - @hyperlane-xyz/sdk@5.5.0 - @hyperlane-xyz/utils@5.5.0 - @hyperlane-xyz/helloworld@5.5.0 ## @hyperlane-xyz/ccip-server@5.5.0 ## @hyperlane-xyz/github-proxy@5.5.0 --------- Co-authored-by: github-actions[bot] --- .changeset/bright-planets-march.md | 5 ---- .changeset/calm-pears-clean.md | 6 ----- .changeset/clean-frogs-chew.md | 7 ------ .changeset/early-dots-serve.md | 5 ---- .changeset/gorgeous-rivers-search.md | 6 ----- .changeset/gorgeous-rockets-walk.md | 5 ---- .changeset/shy-zebras-invent.md | 8 ------- solidity/CHANGELOG.md | 8 +++++++ solidity/contracts/PackageVersioned.sol | 2 +- solidity/package.json | 4 ++-- typescript/ccip-server/CHANGELOG.md | 2 ++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 13 ++++++++++ typescript/cli/package.json | 6 ++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 2 ++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 12 ++++++++++ typescript/helloworld/package.json | 6 ++--- typescript/infra/CHANGELOG.md | 13 ++++++++++ typescript/infra/package.json | 8 +++---- typescript/sdk/CHANGELOG.md | 17 +++++++++++++ typescript/sdk/package.json | 6 ++--- typescript/utils/CHANGELOG.md | 8 +++++++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 19 +++++++++++++++ typescript/widgets/package.json | 6 ++--- yarn.lock | 32 ++++++++++++------------- 28 files changed, 133 insertions(+), 81 deletions(-) delete mode 100644 .changeset/bright-planets-march.md delete mode 100644 .changeset/calm-pears-clean.md delete mode 100644 .changeset/clean-frogs-chew.md delete mode 100644 .changeset/early-dots-serve.md delete mode 100644 .changeset/gorgeous-rivers-search.md delete mode 100644 .changeset/gorgeous-rockets-walk.md delete mode 100644 .changeset/shy-zebras-invent.md diff --git a/.changeset/bright-planets-march.md b/.changeset/bright-planets-march.md deleted file mode 100644 index 6a2d2ab16..000000000 --- a/.changeset/bright-planets-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': patch ---- - -Forward value from ICA router to proxy for multicall diff --git a/.changeset/calm-pears-clean.md b/.changeset/calm-pears-clean.md deleted file mode 100644 index d04b6574d..000000000 --- a/.changeset/calm-pears-clean.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Break out BlockExplorerSchema and export separately -Migrate RPC + Explorer health tests back to SDK from registry diff --git a/.changeset/clean-frogs-chew.md b/.changeset/clean-frogs-chew.md deleted file mode 100644 index b918b1034..000000000 --- a/.changeset/clean-frogs-chew.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperlane-xyz/utils': minor ---- - -Migrate fetchWithTimeout from widgets to utils -Add objSlice function and improve types for objMerge -Add isUrl function diff --git a/.changeset/early-dots-serve.md b/.changeset/early-dots-serve.md deleted file mode 100644 index 24e3a51f5..000000000 --- a/.changeset/early-dots-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Add deployments for chains: immutablezkevm, rari, rootstock, alephzeroevm, chiliz, lumia, and superposition diff --git a/.changeset/gorgeous-rivers-search.md b/.changeset/gorgeous-rivers-search.md deleted file mode 100644 index a96034113..000000000 --- a/.changeset/gorgeous-rivers-search.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': patch -'@hyperlane-xyz/sdk': patch ---- - -Reuse SDK transaction typings in tx submitters diff --git a/.changeset/gorgeous-rockets-walk.md b/.changeset/gorgeous-rockets-walk.md deleted file mode 100644 index e95acc681..000000000 --- a/.changeset/gorgeous-rockets-walk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Add opstack, polygoncdk, polkadotsubstrate and zksync to ChainTechnicalStack enum diff --git a/.changeset/shy-zebras-invent.md b/.changeset/shy-zebras-invent.md deleted file mode 100644 index 87a8d94eb..000000000 --- a/.changeset/shy-zebras-invent.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@hyperlane-xyz/widgets': minor ---- - -Create ChainSearchMenu and ChainDetailsMenu components -Add required icon and button components -Add persisted zustand store and hooks -Add clipboard utility functions diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index fd020f14c..01d7e99ae 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/core +## 5.4.1 + +### Patch Changes + +- 92c86cca6: Forward value from ICA router to proxy for multicall +- Updated dependencies [2afc484a2] + - @hyperlane-xyz/utils@5.5.0 + ## 5.4.0 ### Minor Changes diff --git a/solidity/contracts/PackageVersioned.sol b/solidity/contracts/PackageVersioned.sol index 39f2a641b..f0d43b725 100644 --- a/solidity/contracts/PackageVersioned.sol +++ b/solidity/contracts/PackageVersioned.sol @@ -7,5 +7,5 @@ pragma solidity >=0.6.11; **/ abstract contract PackageVersioned { // GENERATED CODE - DO NOT EDIT - string public constant PACKAGE_VERSION = "5.4.0"; + string public constant PACKAGE_VERSION = "5.4.1"; } diff --git a/solidity/package.json b/solidity/package.json index f7416d10a..7fb78e878 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.4.0", + "version": "5.4.1", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.4.0", + "@hyperlane-xyz/utils": "5.5.0", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index 8ae8aab03..2f082f6b2 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/ccip-server +## 5.5.0 + ## 5.4.0 ## 5.3.0 diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index 53ce4f0ad..c58df422c 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.4.0", + "version": "5.5.0", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index 73fb8b050..517b7ebe1 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,18 @@ # @hyperlane-xyz/cli +## 5.5.0 + +### Patch Changes + +- fcfe91113: Reuse SDK transaction typings in tx submitters +- Updated dependencies [2afc484a2] +- Updated dependencies [2afc484a2] +- Updated dependencies [3254472e0] +- Updated dependencies [fcfe91113] +- Updated dependencies [6176c9861] + - @hyperlane-xyz/sdk@5.5.0 + - @hyperlane-xyz/utils@5.5.0 + ## 5.4.0 ### Minor Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index d2d617ae3..38d53b3cf 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.4.0", + "version": "5.5.0", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.4.0", - "@hyperlane-xyz/utils": "5.4.0", + "@hyperlane-xyz/sdk": "5.5.0", + "@hyperlane-xyz/utils": "5.5.0", "@inquirer/prompts": "^3.0.0", "asn1.js": "^5.4.1", "bignumber.js": "^9.1.1", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index 8559a97bf..ce5c04eb3 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.4.0'; +export const VERSION = '5.5.0'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md index 01b25aff9..a22fdc8ab 100644 --- a/typescript/github-proxy/CHANGELOG.md +++ b/typescript/github-proxy/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/github-proxy +## 5.5.0 + ## 5.4.0 ## 5.3.0 diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index 03c2af0e9..cefc3c0dc 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.4.0", + "version": "5.5.0", "private": true, "scripts": { "deploy": "wrangler deploy", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index bf074505c..aac142144 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,17 @@ # @hyperlane-xyz/helloworld +## 5.5.0 + +### Patch Changes + +- Updated dependencies [92c86cca6] +- Updated dependencies [2afc484a2] +- Updated dependencies [3254472e0] +- Updated dependencies [fcfe91113] +- Updated dependencies [6176c9861] + - @hyperlane-xyz/core@5.4.1 + - @hyperlane-xyz/sdk@5.5.0 + ## 5.4.0 ### Patch Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index 095b84239..4aba7b0bc 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.4.0", + "version": "5.5.0", "dependencies": { - "@hyperlane-xyz/core": "5.4.0", + "@hyperlane-xyz/core": "5.4.1", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.4.0", + "@hyperlane-xyz/sdk": "5.5.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index d45256a13..bd6476484 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,18 @@ # @hyperlane-xyz/infra +## 5.5.0 + +### Patch Changes + +- Updated dependencies [2afc484a2] +- Updated dependencies [2afc484a2] +- Updated dependencies [3254472e0] +- Updated dependencies [fcfe91113] +- Updated dependencies [6176c9861] + - @hyperlane-xyz/sdk@5.5.0 + - @hyperlane-xyz/utils@5.5.0 + - @hyperlane-xyz/helloworld@5.5.0 + ## 5.4.0 ### Patch Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 3a772cc3c..7fc56cfa9 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.4.0", + "version": "5.5.0", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.4.0", + "@hyperlane-xyz/helloworld": "5.5.0", "@hyperlane-xyz/registry": "4.3.6", - "@hyperlane-xyz/sdk": "5.4.0", - "@hyperlane-xyz/utils": "5.4.0", + "@hyperlane-xyz/sdk": "5.5.0", + "@hyperlane-xyz/utils": "5.5.0", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index 6c5fd41e8..058f6b817 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,22 @@ # @hyperlane-xyz/sdk +## 5.5.0 + +### Minor Changes + +- 2afc484a2: Break out BlockExplorerSchema and export separately + Migrate RPC + Explorer health tests back to SDK from registry +- 3254472e0: Add deployments for chains: immutablezkevm, rari, rootstock, alephzeroevm, chiliz, lumia, and superposition +- 6176c9861: Add opstack, polygoncdk, polkadotsubstrate and zksync to ChainTechnicalStack enum + +### Patch Changes + +- fcfe91113: Reuse SDK transaction typings in tx submitters +- Updated dependencies [92c86cca6] +- Updated dependencies [2afc484a2] + - @hyperlane-xyz/core@5.4.1 + - @hyperlane-xyz/utils@5.5.0 + ## 5.4.0 ### Minor Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 4b07bcb7c..6290277c8 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.4.0", + "version": "5.5.0", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.4.0", - "@hyperlane-xyz/utils": "5.4.0", + "@hyperlane-xyz/core": "5.4.1", + "@hyperlane-xyz/utils": "5.5.0", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index 81415beef..a9252e563 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/utils +## 5.5.0 + +### Minor Changes + +- 2afc484a2: Migrate fetchWithTimeout from widgets to utils + Add objSlice function and improve types for objMerge + Add isUrl function + ## 5.4.0 ### Minor Changes diff --git a/typescript/utils/package.json b/typescript/utils/package.json index bb4ba14dd..83c8ed9c3 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.4.0", + "version": "5.5.0", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index 0af96516b..8e5869427 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,24 @@ # @hyperlane-xyz/widgets +## 5.5.0 + +### Minor Changes + +- 2afc484a2: Create ChainSearchMenu and ChainDetailsMenu components + Add required icon and button components + Add persisted zustand store and hooks + Add clipboard utility functions + +### Patch Changes + +- Updated dependencies [2afc484a2] +- Updated dependencies [2afc484a2] +- Updated dependencies [3254472e0] +- Updated dependencies [fcfe91113] +- Updated dependencies [6176c9861] + - @hyperlane-xyz/sdk@5.5.0 + - @hyperlane-xyz/utils@5.5.0 + ## 5.4.0 ### Patch Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index cff1e46ac..8ec65492e 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,15 +1,15 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.4.0", + "version": "5.5.0", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@headlessui/react": "^2.1.8", - "@hyperlane-xyz/sdk": "5.4.0", - "@hyperlane-xyz/utils": "5.4.0", + "@hyperlane-xyz/sdk": "5.5.0", + "@hyperlane-xyz/utils": "5.5.0", "clsx": "^2.1.1", "react-tooltip": "^5.28.0" }, diff --git a/yarn.lock b/yarn.lock index 15930aeb7..258b5caf3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7824,8 +7824,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.4.0" - "@hyperlane-xyz/utils": "npm:5.4.0" + "@hyperlane-xyz/sdk": "npm:5.5.0" + "@hyperlane-xyz/utils": "npm:5.5.0" "@inquirer/prompts": "npm:^3.0.0" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:^18.14.5" @@ -7855,13 +7855,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.4.0, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.4.1, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.4.0" + "@hyperlane-xyz/utils": "npm:5.5.0" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7912,13 +7912,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.4.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.5.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.4.0" + "@hyperlane-xyz/core": "npm:5.4.1" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.4.0" + "@hyperlane-xyz/sdk": "npm:5.5.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7965,10 +7965,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.4.0" + "@hyperlane-xyz/helloworld": "npm:5.5.0" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.4.0" - "@hyperlane-xyz/utils": "npm:5.4.0" + "@hyperlane-xyz/sdk": "npm:5.5.0" + "@hyperlane-xyz/utils": "npm:5.5.0" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -8034,7 +8034,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.4.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.5.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -8042,8 +8042,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.4.0" - "@hyperlane-xyz/utils": "npm:5.4.0" + "@hyperlane-xyz/core": "npm:5.4.1" + "@hyperlane-xyz/utils": "npm:5.5.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -8084,7 +8084,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.4.0, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.5.0, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -8110,8 +8110,8 @@ __metadata: dependencies: "@headlessui/react": "npm:^2.1.8" "@hyperlane-xyz/registry": "npm:4.3.6" - "@hyperlane-xyz/sdk": "npm:5.4.0" - "@hyperlane-xyz/utils": "npm:5.4.0" + "@hyperlane-xyz/sdk": "npm:5.5.0" + "@hyperlane-xyz/utils": "npm:5.5.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From e89f9e35d4e4b758464a6d344962be336f3793f7 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:29:58 +0100 Subject: [PATCH 124/224] chore: update registry to v4.7.0 (#4662) ### Description chore: update registry to v4.7.0 ### Drive-by changes agent config updates, because they're derived from registry ### Related issues n/a ### Backward compatibility yes ### Testing n/a --------- Co-authored-by: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> --- .changeset/poor-coins-accept.md | 7 ++++ .registryrc | 2 +- rust/main/config/mainnet_config.json | 3 ++ rust/main/config/testnet_config.json | 38 +++++++++---------- typescript/cli/package.json | 2 +- typescript/helloworld/package.json | 2 +- .../config/environments/mainnet3/agent.ts | 4 +- typescript/infra/package.json | 2 +- typescript/widgets/package.json | 2 +- yarn.lock | 16 ++++---- 10 files changed, 44 insertions(+), 34 deletions(-) create mode 100644 .changeset/poor-coins-accept.md diff --git a/.changeset/poor-coins-accept.md b/.changeset/poor-coins-accept.md new file mode 100644 index 000000000..2c3c6a892 --- /dev/null +++ b/.changeset/poor-coins-accept.md @@ -0,0 +1,7 @@ +--- +'@hyperlane-xyz/helloworld': patch +'@hyperlane-xyz/widgets': patch +'@hyperlane-xyz/cli': patch +--- + +Update registry to v4.7.0 diff --git a/.registryrc b/.registryrc index 92dafe4b6..79214dce1 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -8afda069c23f8974a8679d666942be509ed64dad +v4.7.0 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index aef06b31a..e4866b036 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -4190,6 +4190,9 @@ "validatorAnnounce": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", "index": { "from": 17051552 + }, + "transactionOverrides": { + "maxPriorityFeePerGas": 1000000000 } }, "immutablezkevm": { diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index bec39173c..dfb698ed1 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -37,7 +37,7 @@ "interchainAccountIsm": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", "interchainAccountRouter": "0xEbA64c8a9b4a61a9210d5fe7E4375380999C821b", "interchainGasPaymaster": "0x44769b0f4a6f01339e131a691cc2eebbb519d297", - "interchainSecurityModule": "0x83D62A2cA5609bA703c2685c557d72A64CB52173", + "interchainSecurityModule": "0xeca406C12845153d2D1B8087b8195D6Be834E3c2", "isTestnet": true, "mailbox": "0xEf9F292fcEBC3848bF4bB92a96a04F9ECBb78E59", "merkleTreeHook": "0x221FA9CBaFcd6c1C3d206571Cf4427703e023FFa", @@ -100,7 +100,7 @@ "from": 49690504 }, "interchainGasPaymaster": "0xc756cFc1b7d0d4646589EDf10eD54b201237F5e8", - "interchainSecurityModule": "0xf6e44F2c394Bd4db6757a858BCF231BE8779D73D", + "interchainSecurityModule": "0xB8fD93251D9292191314E4625d9835a2952B6268", "isTestnet": true, "mailbox": "0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8", "merkleTreeHook": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", @@ -165,7 +165,7 @@ "from": 13851043 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x85f5aE8393c3051057444eEaB78bA9567C95BCD1", + "interchainSecurityModule": "0x6Cf48F7b26374a741EE5290ECB58b23cCA171baa", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -232,7 +232,7 @@ "interchainAccountIsm": "0xa9D8Ec959F34272B1a56D09AF00eeee58970d3AE", "interchainAccountRouter": "0x6d2B3e304E58c2a19f1492E7cf15CaF63Ce6e0d2", "interchainGasPaymaster": "0x0dD20e410bdB95404f71c5a4e7Fa67B892A5f949", - "interchainSecurityModule": "0x07c5B572D29A70C308Ef96fA98a635fA22dA44c9", + "interchainSecurityModule": "0xF97D14d7E3248665913A5037F82D06D63AB34786", "isTestnet": true, "mailbox": "0xF9F6F5646F478d5ab4e20B0F910C92F1CCC9Cc6D", "merkleTreeHook": "0xc6cbF39A747f5E28d1bDc8D9dfDAb2960Abd5A8f", @@ -301,7 +301,7 @@ "from": 4950 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0xc6B9CA04fDB54E63Aff6B3617C2E0A1228a19C67", + "interchainSecurityModule": "0xED455C8355682915288AeFad41b460cc800A71D5", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -399,7 +399,7 @@ "from": 1606754 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x6Cf48F7b26374a741EE5290ECB58b23cCA171baa", + "interchainSecurityModule": "0xcF1260Dfc276e5A45fdC2FFB1C3CED97B4a50B05", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -462,7 +462,7 @@ "interchainAccountIsm": "0xfaB4815BDC5c60c6bD625459C8577aFdD79D9311", "interchainAccountRouter": "0xeEF6933122894fF217a7dd07510b3D64b747e29b", "interchainGasPaymaster": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", - "interchainSecurityModule": "0xd0FBdaEC5b7Beba18E23492F1d3A8a15f8685E6E", + "interchainSecurityModule": "0xA34D60b4634711C6384EE039E7A04b444daDa6F1", "isTestnet": true, "mailbox": "0x5b6CFf85442B851A8e6eaBd2A4E4507B5135B3B0", "merkleTreeHook": "0x9ff6ac3dAf63103620BBf76136eA1AFf43c2F612", @@ -528,7 +528,7 @@ "from": 1543015 }, "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9", - "interchainSecurityModule": "0xa5A3004174cd16AB6C4e69a7558f4f84a51D2cfB", + "interchainSecurityModule": "0xDFEd7662f55F3115291244694B95FA7869195f7D", "isTestnet": true, "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc", "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE", @@ -590,7 +590,7 @@ "from": 15833917 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x6Cf48F7b26374a741EE5290ECB58b23cCA171baa", + "interchainSecurityModule": "0xcF1260Dfc276e5A45fdC2FFB1C3CED97B4a50B05", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -715,7 +715,7 @@ "from": 10634605 }, "interchainGasPaymaster": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", - "interchainSecurityModule": "0x782Dc499C9b9EE59e79D243322beC5b03e017819", + "interchainSecurityModule": "0x1aB93dF40998f4aFC4FbBdF1B81fa7333171fFe9", "isTestnet": true, "mailbox": "0x54148470292C24345fb828B003461a9444414517", "merkleTreeHook": "0xddf4C3e791caCaFd26D7fb275549739B38ae6e75", @@ -787,7 +787,7 @@ "interchainAccountIsm": "0xE023239c8dfc172FF008D8087E7442d3eBEd9350", "interchainAccountRouter": "0xe17c37212d785760E8331D4A4395B17b34Ba8cDF", "interchainGasPaymaster": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", - "interchainSecurityModule": "0xb0ED7B7CD2572D45f1439069a2B973d8Dc0C5970", + "interchainSecurityModule": "0x30Ae39e0EBd119ee9d6EBD4AF2bEe61F67A3cDb3", "isTestnet": true, "mailbox": "0x3C5154a193D6e2955650f9305c8d80c18C814A68", "merkleTreeHook": "0x863E8c26621c52ACa1849C53500606e73BA272F0", @@ -865,7 +865,7 @@ "interchainAccountIsm": "0x83a3068B719F764d413625dA77468ED74789ae02", "interchainAccountRouter": "0x8e131c8aE5BF1Ed38D05a00892b6001a7d37739d", "interchainGasPaymaster": "0x6f2756380FD49228ae25Aa7F2817993cB74Ecc56", - "interchainSecurityModule": "0x5E01E8FEc4733a8e113c21EF75f5bd793B7eE8fe", + "interchainSecurityModule": "0x3EcdB142F869313Dd80FA238370F0A910476aAA2", "isTestnet": true, "mailbox": "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766", "merkleTreeHook": "0x4917a9746A7B6E0A57159cCb7F5a6744247f2d0d", @@ -975,7 +975,7 @@ "from": 3111622 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0xc6B9CA04fDB54E63Aff6B3617C2E0A1228a19C67", + "interchainSecurityModule": "0xED455C8355682915288AeFad41b460cc800A71D5", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -1060,7 +1060,7 @@ "interchainAccountIsm": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", "interchainAccountRouter": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", "interchainGasPaymaster": "0x04438ef7622f5412f82915F59caD4f704C61eA48", - "interchainSecurityModule": "0x58B923EE9F79479E3cf226fCC32EdF42079A56b1", + "interchainSecurityModule": "0xe5993C6c42b581095b500Ea758fc0f4596BA2135", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", "pausableHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", @@ -1120,7 +1120,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", + "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1188,7 +1188,7 @@ "interchainAccountIsm": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", "interchainAccountRouter": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", "interchainGasPaymaster": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", - "interchainSecurityModule": "0xe51dbFbD86a345a818dc93ab8589ab8dB94ab593", + "interchainSecurityModule": "0xb7b7105E2ecb79453356E28dd8808FfA0AcF083d", "mailbox": "0xB08d78F439e55D02C398519eef61606A5926245F", "merkleTreeHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", "pausableHook": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c", @@ -1249,7 +1249,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", + "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1377,7 +1377,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", + "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1441,7 +1441,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0xc313b6C98D5CA1f9ee5beb4211BC87DA7ab7B5ED", + "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", diff --git a/typescript/cli/package.json b/typescript/cli/package.json index 38d53b3cf..19421e2e9 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -5,7 +5,7 @@ "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", - "@hyperlane-xyz/registry": "4.3.6", + "@hyperlane-xyz/registry": "4.7.0", "@hyperlane-xyz/sdk": "5.5.0", "@hyperlane-xyz/utils": "5.5.0", "@inquirer/prompts": "^3.0.0", diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index 4aba7b0bc..ca2d79f60 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -4,7 +4,7 @@ "version": "5.5.0", "dependencies": { "@hyperlane-xyz/core": "5.4.1", - "@hyperlane-xyz/registry": "4.3.6", + "@hyperlane-xyz/registry": "4.7.0", "@hyperlane-xyz/sdk": "5.5.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index b0fe723f7..683fc3977 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -409,7 +409,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '6f414af-20241004-131949', + tag: '70bb863-20241009-193832', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -418,7 +418,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: '6f414af-20241004-131949', + tag: '70bb863-20241009-193832', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 7fc56cfa9..d49058100 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -14,7 +14,7 @@ "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", "@hyperlane-xyz/helloworld": "5.5.0", - "@hyperlane-xyz/registry": "4.3.6", + "@hyperlane-xyz/registry": "4.7.0", "@hyperlane-xyz/sdk": "5.5.0", "@hyperlane-xyz/utils": "5.5.0", "@inquirer/prompts": "^5.3.8", diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 8ec65492e..2e0177246 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -14,7 +14,7 @@ "react-tooltip": "^5.28.0" }, "devDependencies": { - "@hyperlane-xyz/registry": "4.3.6", + "@hyperlane-xyz/registry": "4.7.0", "@storybook/addon-essentials": "^7.6.14", "@storybook/addon-interactions": "^7.6.14", "@storybook/addon-links": "^7.6.14", diff --git a/yarn.lock b/yarn.lock index 258b5caf3..bae817923 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7823,7 +7823,7 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.577.0" "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" - "@hyperlane-xyz/registry": "npm:4.3.6" + "@hyperlane-xyz/registry": "npm:4.7.0" "@hyperlane-xyz/sdk": "npm:5.5.0" "@hyperlane-xyz/utils": "npm:5.5.0" "@inquirer/prompts": "npm:^3.0.0" @@ -7917,7 +7917,7 @@ __metadata: resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: "@hyperlane-xyz/core": "npm:5.4.1" - "@hyperlane-xyz/registry": "npm:4.3.6" + "@hyperlane-xyz/registry": "npm:4.7.0" "@hyperlane-xyz/sdk": "npm:5.5.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" @@ -7966,7 +7966,7 @@ __metadata: "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" "@hyperlane-xyz/helloworld": "npm:5.5.0" - "@hyperlane-xyz/registry": "npm:4.3.6" + "@hyperlane-xyz/registry": "npm:4.7.0" "@hyperlane-xyz/sdk": "npm:5.5.0" "@hyperlane-xyz/utils": "npm:5.5.0" "@inquirer/prompts": "npm:^5.3.8" @@ -8024,13 +8024,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/registry@npm:4.3.6": - version: 4.3.6 - resolution: "@hyperlane-xyz/registry@npm:4.3.6" +"@hyperlane-xyz/registry@npm:4.7.0": + version: 4.7.0 + resolution: "@hyperlane-xyz/registry@npm:4.7.0" dependencies: yaml: "npm:2.4.5" zod: "npm:^3.21.2" - checksum: 7cc42813f4f8b8ef09266be249f3dcec0584832166419df2f48eec3cc43ba766e58845ecc16673bf6465a711f08ff6c4fc5216da2f704bc31ef8ade52af4b6e5 + checksum: d5b0090869417c3fc263c379791f439070113aee239990ffc20d9d90d74102b77008f3c630ce955a9b3f1f92f79b1df67d83a097b327cd5db2b01b382bf40f18 languageName: node linkType: hard @@ -8109,7 +8109,7 @@ __metadata: resolution: "@hyperlane-xyz/widgets@workspace:typescript/widgets" dependencies: "@headlessui/react": "npm:^2.1.8" - "@hyperlane-xyz/registry": "npm:4.3.6" + "@hyperlane-xyz/registry": "npm:4.7.0" "@hyperlane-xyz/sdk": "npm:5.5.0" "@hyperlane-xyz/utils": "npm:5.5.0" "@storybook/addon-essentials": "npm:^7.6.14" From bb82b1cc01fbf3a3909b391dc55d7be0c119622f Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Thu, 10 Oct 2024 14:35:32 +0100 Subject: [PATCH 125/224] feat: Store as much as possible from every range (#4660) ### Description Currently, if Scraper cannot fetch and parse a block or a transaction, it will fail the whole chunk of logs. It means that a transaction which can be fetched and parsed, but happens to be in the same chunk as unparseable transaction, won't be inserted into database. This PR fixes it. Scraper will do its best to insert as many as possible blocks and transactions into database from the chunk. ### Related issues https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4632 ### Backward compatibility Yes ### Testing Local run of E2E tests. Local run of Scraper --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../agents/scraper/src/chain_scraper/mod.rs | 157 ++++++++++-------- rust/main/agents/scraper/src/db/message.rs | 33 ++-- rust/main/agents/scraper/src/db/payment.rs | 16 +- 3 files changed, 117 insertions(+), 89 deletions(-) diff --git a/rust/main/agents/scraper/src/chain_scraper/mod.rs b/rust/main/agents/scraper/src/chain_scraper/mod.rs index 23997766c..71ddd84ef 100644 --- a/rust/main/agents/scraper/src/chain_scraper/mod.rs +++ b/rust/main/agents/scraper/src/chain_scraper/mod.rs @@ -14,7 +14,7 @@ use hyperlane_core::{ HyperlaneWatermarkedLogStore, Indexed, InterchainGasPayment, LogMeta, H256, }; use itertools::Itertools; -use tracing::trace; +use tracing::{trace, warn}; use crate::db::{ BasicBlock, BlockCursor, ScraperDb, StorableDelivery, StorableMessage, StorablePayment, @@ -98,18 +98,12 @@ impl HyperlaneSqlDb { .collect(); trace!(?blocks, "Ensured blocks"); - // all txns we care about - let txns_with_ids = - self.ensure_txns(block_hash_by_txn_hash.into_iter().map( - move |(txn_hash, block_hash)| { - let block_info = *blocks.get(&block_hash).as_ref().unwrap(); - TxnWithBlockId { - txn_hash, - block_id: block_info.id, - } - }, - )) - .await?; + // We ensure transactions only from blocks which are inserted into database + let txn_hash_with_block_ids = block_hash_by_txn_hash + .into_iter() + .filter_map(move |(txn, block)| blocks.get(&block).map(|b| (txn, b.id))) + .map(|(txn_hash, block_id)| TxnWithBlockId { txn_hash, block_id }); + let txns_with_ids = self.ensure_txns(txn_hash_with_block_ids).await?; Ok(txns_with_ids.map(move |TxnWithId { hash, id: txn_id }| TxnWithId { hash, id: txn_id })) } @@ -118,8 +112,10 @@ impl HyperlaneSqlDb { /// in. if it is in the database already: /// Fetches its associated database id /// if it is not in the database already: - /// Looks up its data with ethers and then returns the database id after + /// Looks up its data with the chain and then returns the database id after /// inserting it into the database. + /// if it cannot fetch and parse transaction, the transaction will be skipped and not returned + /// from this method. async fn ensure_txns( &self, txns: impl Iterator, @@ -153,7 +149,13 @@ impl HyperlaneSqlDb { for mut chunk in as_chunks::<(&H256, &mut (Option, i64))>(txns_to_fetch, CHUNK_SIZE) { for (hash, (_, block_id)) in chunk.iter() { - let info = self.provider.get_txn_by_hash(hash).await?; + let info = match self.provider.get_txn_by_hash(hash).await { + Ok(info) => info, + Err(e) => { + warn!(?hash, ?e, "error fetching and parsing transaction"); + continue; + } + }; hashes_to_insert.push(*hash); txns_to_insert.push(StorableTxn { info, @@ -161,35 +163,41 @@ impl HyperlaneSqlDb { }); } + // If we have no transactions to insert, we don't need to store them and update + // database transaction ids. + if txns_to_insert.is_empty() { + continue; + } + self.db.store_txns(txns_to_insert.drain(..)).await?; let ids = self.db.get_txn_ids(hashes_to_insert.drain(..)).await?; for (hash, (txn_id, _block_id)) in chunk.iter_mut() { - let _ = txn_id.insert(ids[hash]); + *txn_id = ids.get(hash).copied(); } } - Ok(txns + let ensured_txns = txns .into_iter() - .map(|(hash, (txn_id, _block_id))| TxnWithId { - hash, - id: txn_id.unwrap(), - })) + .filter_map(|(hash, (txn_id, _))| txn_id.map(|id| (hash, id))) + .map(|(hash, id)| TxnWithId { hash, id }); + + Ok(ensured_txns) } /// Takes a list of block hashes for each block /// if it is in the database already: /// Fetches its associated database id /// if it is not in the database already: - /// Looks up its data with ethers and then returns the database id after + /// Looks up its data with the chain and then returns the database id after /// inserting it into the database. + /// if it cannot fetch and parse block, the block will be skipped and not returned from + /// this method. async fn ensure_blocks( &self, block_hashes: impl Iterator, ) -> Result> { - // mapping of block hash to the database id and block timestamp. Optionals are - // in place because we will find the timestamp first if the block was not - // already in the db. + // Mapping of block hash to `BasicBlock` which contains database block id and block hash. let mut blocks: HashMap> = block_hashes.map(|b| (b, None)).collect(); @@ -222,7 +230,13 @@ impl HyperlaneSqlDb { for chunk in as_chunks(blocks_to_fetch, CHUNK_SIZE) { debug_assert!(!chunk.is_empty()); for (hash, block_info) in chunk { - let info = self.provider.get_block_by_hash(hash).await?; + let info = match self.provider.get_block_by_hash(hash).await { + Ok(info) => info, + Err(e) => { + warn!(?hash, ?e, "error fetching and parsing block"); + continue; + } + }; let basic_info_ref = block_info.insert(BasicBlock { id: -1, hash: *hash, @@ -231,6 +245,12 @@ impl HyperlaneSqlDb { hashes_to_insert.push(hash); } + // If we have no blocks to insert, we don't store them and we don't update + // database block ids. + if blocks_to_insert.is_empty() { + continue; + } + self.db .store_blocks( self.domain().id(), @@ -249,28 +269,25 @@ impl HyperlaneSqlDb { .collect::>(); for (block_ref, _) in blocks_to_insert.drain(..) { - block_ref.id = hashes[&block_ref.hash]; + if let Some(id) = hashes.get(&block_ref.hash) { + block_ref.id = *id; + } } } - // ensure we have updated all the block ids and that we have info for all of - // them. - #[cfg(debug_assertions)] - for (hash, block) in blocks.iter() { - let block = block.as_ref().unwrap(); - assert_eq!(hash, &block.hash); - assert!(block.id > 0); - } - - Ok(blocks + let ensured_blocks = blocks .into_iter() - .map(|(hash, block_info)| block_info.unwrap())) + .filter_map(|(hash, block_info)| block_info.filter(|b| b.id != -1)); + + Ok(ensured_blocks) } } #[async_trait] impl HyperlaneLogStore for HyperlaneSqlDb { - /// Store messages from the origin mailbox into the database. + /// Store dispatched messages from the origin mailbox into the database. + /// We store only messages from blocks and transaction which we could successfully insert + /// into database. async fn store_logs(&self, messages: &[(Indexed, LogMeta)]) -> Result { if messages.is_empty() { return Ok(0); @@ -280,20 +297,18 @@ impl HyperlaneLogStore for HyperlaneSqlDb { .await? .map(|t| (t.hash, t)) .collect(); - let storable = messages.iter().map(|m| { - let txn = txns - .get( - &m.1.transaction_id + let storable = messages + .iter() + .filter_map(|(message, meta)| { + txns.get( + &meta + .transaction_id .try_into() .expect("256-bit transaction ids are the maximum supported at this time"), ) - .unwrap(); - StorableMessage { - msg: m.0.inner().clone(), - meta: &m.1, - txn_id: txn.id, - } - }); + .map(|t| (message.inner().clone(), meta, t.id)) + }) + .map(|(msg, meta, txn_id)| StorableMessage { msg, meta, txn_id }); let stored = self .db .store_dispatched_messages(self.domain().id(), &self.mailbox_address, storable) @@ -304,6 +319,9 @@ impl HyperlaneLogStore for HyperlaneSqlDb { #[async_trait] impl HyperlaneLogStore for HyperlaneSqlDb { + /// Store delivered message ids from the destination mailbox into the database. + /// We store only delivered messages ids from blocks and transaction which we could successfully + /// insert into database. async fn store_logs(&self, deliveries: &[(Indexed, LogMeta)]) -> Result { if deliveries.is_empty() { return Ok(0); @@ -313,22 +331,22 @@ impl HyperlaneLogStore for HyperlaneSqlDb { .await? .map(|t| (t.hash, t)) .collect(); - let storable = deliveries.iter().map(|(message_id, meta)| { - let txn_id = txns - .get( + let storable = deliveries + .iter() + .filter_map(|(message_id, meta)| { + txns.get( &meta .transaction_id .try_into() .expect("256-bit transaction ids are the maximum supported at this time"), ) - .unwrap() - .id; - StorableDelivery { - message_id: *message_id.inner(), + .map(|txn| (*message_id.inner(), meta, txn.id)) + }) + .map(|(message_id, meta, txn_id)| StorableDelivery { + message_id, meta, txn_id, - } - }); + }); let stored = self .db @@ -340,6 +358,9 @@ impl HyperlaneLogStore for HyperlaneSqlDb { #[async_trait] impl HyperlaneLogStore for HyperlaneSqlDb { + /// Store interchain gas payments into the database. + /// We store only interchain gas payments from blocks and transaction which we could + /// successfully insert into database. async fn store_logs( &self, payments: &[(Indexed, LogMeta)], @@ -352,22 +373,22 @@ impl HyperlaneLogStore for HyperlaneSqlDb { .await? .map(|t| (t.hash, t)) .collect(); - let storable = payments.iter().map(|(payment, meta)| { - let txn_id = txns - .get( + let storable = payments + .iter() + .filter_map(|(payment, meta)| { + txns.get( &meta .transaction_id .try_into() .expect("256-bit transaction ids are the maximum supported at this time"), ) - .unwrap() - .id; - StorablePayment { - payment: payment.inner(), + .map(|txn| (payment.inner(), meta, txn.id)) + }) + .map(|(payment, meta, txn_id)| StorablePayment { + payment, meta, txn_id, - } - }); + }); let stored = self.db.store_payments(self.domain().id(), storable).await?; Ok(stored as u32) diff --git a/rust/main/agents/scraper/src/db/message.rs b/rust/main/agents/scraper/src/db/message.rs index 1f62c6fa0..f8b99fec5 100644 --- a/rust/main/agents/scraper/src/db/message.rs +++ b/rust/main/agents/scraper/src/db/message.rs @@ -13,6 +13,7 @@ use crate::date_time; use crate::db::ScraperDb; use super::generated::{delivered_message, message}; + #[derive(Debug, Clone)] pub struct StorableDelivery<'a> { pub message_id: H256, @@ -178,9 +179,13 @@ impl ScraperDb { }) .collect_vec(); - debug_assert!(!models.is_empty()); trace!(?models, "Writing delivered messages to database"); + if models.is_empty() { + debug!("Wrote zero new delivered messages to database"); + return Ok(0); + } + Insert::many(models) .on_conflict( OnConflict::columns([delivered_message::Column::MsgId]) @@ -197,12 +202,10 @@ impl ScraperDb { .deliveries_count_since_id(domain, destination_mailbox, latest_id_before) .await?; - if new_deliveries_count > 0 { - debug!( - messages = new_deliveries_count, - "Wrote new delivered messages to database" - ); - } + debug!( + messages = new_deliveries_count, + "Wrote new delivered messages to database" + ); Ok(new_deliveries_count) } @@ -272,9 +275,13 @@ impl ScraperDb { }) .collect_vec(); - debug_assert!(!models.is_empty()); trace!(?models, "Writing messages to database"); + if models.is_empty() { + debug!("Wrote zero new messages to database"); + return Ok(0); + } + Insert::many(models) .on_conflict( OnConflict::columns([ @@ -299,12 +306,10 @@ impl ScraperDb { .dispatch_count_since_id(domain, origin_mailbox, latest_id_before) .await?; - if new_dispatch_count > 0 { - debug!( - messages = new_dispatch_count, - "Wrote new messages to database" - ); - } + debug!( + messages = new_dispatch_count, + "Wrote new messages to database" + ); Ok(new_dispatch_count) } } diff --git a/rust/main/agents/scraper/src/db/payment.rs b/rust/main/agents/scraper/src/db/payment.rs index 57c63b3e3..250f4f3c6 100644 --- a/rust/main/agents/scraper/src/db/payment.rs +++ b/rust/main/agents/scraper/src/db/payment.rs @@ -42,9 +42,13 @@ impl ScraperDb { }) .collect_vec(); - debug_assert!(!models.is_empty()); trace!(?models, "Writing gas payments to database"); + if models.is_empty() { + debug!("Wrote zero new gas payments to database"); + return Ok(0); + } + Insert::many(models) .on_conflict( OnConflict::columns([ @@ -67,12 +71,10 @@ impl ScraperDb { .payments_count_since_id(domain, latest_id_before) .await?; - if new_payments_count > 0 { - debug!( - payments = new_payments_count, - "Wrote new gas payments to database" - ); - } + debug!( + payments = new_payments_count, + "Wrote new gas payments to database" + ); Ok(new_payments_count) } From 8001bbbd68ec9e15e7f9974e7d36e4e4769fddc1 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:14:19 -0400 Subject: [PATCH 126/224] fix: Add override to some transactions (#4658) ### Description This partially fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4657, specifically made to get warp apply to work on Sei ### Backward compatibility Yes ### Testing Manual - deployed --- .changeset/fluffy-ducks-buy.md | 5 +++++ typescript/sdk/src/ism/EvmIsmModule.ts | 1 + typescript/sdk/src/router/GasRouterDeployer.ts | 1 + typescript/sdk/src/router/ProxiedRouterDeployer.ts | 5 ++++- 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 .changeset/fluffy-ducks-buy.md diff --git a/.changeset/fluffy-ducks-buy.md b/.changeset/fluffy-ducks-buy.md new file mode 100644 index 000000000..1b5db5097 --- /dev/null +++ b/.changeset/fluffy-ducks-buy.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Add override to some transactions to fix warp apply diff --git a/typescript/sdk/src/ism/EvmIsmModule.ts b/typescript/sdk/src/ism/EvmIsmModule.ts index 7ab88b027..691ae1deb 100644 --- a/typescript/sdk/src/ism/EvmIsmModule.ts +++ b/typescript/sdk/src/ism/EvmIsmModule.ts @@ -496,6 +496,7 @@ export class EvmIsmModule extends HyperlaneModule< config.owner, availableDomainIds, submoduleAddresses, + this.multiProvider.getTransactionOverrides(this.args.chain), ); await this.multiProvider.handleTx(this.chain, tx); diff --git a/typescript/sdk/src/router/GasRouterDeployer.ts b/typescript/sdk/src/router/GasRouterDeployer.ts index 76aabb460..1c64251d1 100644 --- a/typescript/sdk/src/router/GasRouterDeployer.ts +++ b/typescript/sdk/src/router/GasRouterDeployer.ts @@ -52,6 +52,7 @@ export abstract class GasRouterDeployer< chain, this.router(contracts)['setDestinationGas((uint32,uint256)[])']( remoteConfigs, + this.multiProvider.getTransactionOverrides(chain), ), ); } diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index 8f4d03d2f..e938c096c 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -111,7 +111,10 @@ export abstract class ProxiedRouterDeployer< ); return this.multiProvider.handleTx( chain, - proxyAdmin.transferOwnership(adminOwner), + proxyAdmin.transferOwnership( + adminOwner, + this.multiProvider.getTransactionOverrides(chain), + ), ); } return; From 6b705d09e8e7865fa13291f0f40f6aec4425f1b3 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Thu, 10 Oct 2024 16:26:03 +0100 Subject: [PATCH 127/224] feat: Upgrade Scraper (#4664) ### Description Upgrade Scraper so that it gracefully handles blocks and transactions which cannot be fetched or parsed. ### Related issues https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4632 ### Backward compatibility Yes ### Testing Local E2E Tests Local testing of Scraper Image build after successful CI Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- typescript/infra/config/environments/mainnet3/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 683fc3977..b85a1152f 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -428,7 +428,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '3254472-20241009-111928', + tag: '8001bbb-20241010-143553', }, resources: scraperResources, }, From adedb3db8e993805309f248bdb800486a8b69413 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:56:12 +0100 Subject: [PATCH 128/224] feat: add arcadiatestnet, sonictestnet, unichaintestnet (#4665) ### Description feat: add arcadiatestnet, sonictestnet, unichaintestnet ### Drive-by changes testnet igp ### Related issues n/a ### Backward compatibility yes ### Testing manual --- .registryrc | 2 +- rust/main/config/testnet_config.json | 263 +++++++++-- .../config/environments/testnet4/agent.ts | 15 +- .../testnet4/aw-validators/hyperlane.json | 9 + .../testnet4/core/verification.json | 228 ++++++++++ .../config/environments/testnet4/funding.ts | 5 +- .../environments/testnet4/gasPrices.json | 36 +- .../testnet4/ism/verification.json | 414 ++++++++++++++++++ .../middleware/accounts/verification.json | 231 ++++++++++ .../testnet4/supportedChainNames.ts | 3 + .../environments/testnet4/tokenPrices.json | 5 +- .../environments/testnet4/validators.ts | 61 ++- typescript/sdk/src/consts/multisigIsm.ts | 15 + 13 files changed, 1223 insertions(+), 64 deletions(-) diff --git a/.registryrc b/.registryrc index 79214dce1..6ba08a96c 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -v4.7.0 +e3330d51ebad77e2aa62c34d5a74746ae5e83e64 diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index dfb698ed1..5239f11e9 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -3,12 +3,6 @@ "alfajores": { "aggregationHook": "0xdBabD76358897E68E4964647C1fb8Bf524f5EFdB", "blockExplorers": [ - { - "apiUrl": "https://api-alfajores.celoscan.io/api", - "family": "etherscan", - "name": "CeloScan", - "url": "https://alfajores.celoscan.io" - }, { "apiUrl": "https://explorer.celo.org/alfajores/api", "family": "blockscout", @@ -17,7 +11,7 @@ } ], "blocks": { - "confirmations": 1, + "confirmations": 3, "estimateBlockTime": 5, "reorgPeriod": 0 }, @@ -37,7 +31,7 @@ "interchainAccountIsm": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", "interchainAccountRouter": "0xEbA64c8a9b4a61a9210d5fe7E4375380999C821b", "interchainGasPaymaster": "0x44769b0f4a6f01339e131a691cc2eebbb519d297", - "interchainSecurityModule": "0xeca406C12845153d2D1B8087b8195D6Be834E3c2", + "interchainSecurityModule": "0xeb06b892C48332bc11287c2E73090a59751F7d85", "isTestnet": true, "mailbox": "0xEf9F292fcEBC3848bF4bB92a96a04F9ECBb78E59", "merkleTreeHook": "0x221FA9CBaFcd6c1C3d206571Cf4427703e023FFa", @@ -100,7 +94,7 @@ "from": 49690504 }, "interchainGasPaymaster": "0xc756cFc1b7d0d4646589EDf10eD54b201237F5e8", - "interchainSecurityModule": "0xB8fD93251D9292191314E4625d9835a2952B6268", + "interchainSecurityModule": "0x0bDe2dA99d7A0F0F3b1419e1f8E06Ad155906277", "isTestnet": true, "mailbox": "0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8", "merkleTreeHook": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", @@ -134,7 +128,10 @@ "validatorAnnounce": "0x1b33611fCc073aB0737011d5512EF673Bff74962", "staticMerkleRootWeightedMultisigIsmFactory": "0x1aFD5191738d365C8079e955E4cEdDfe7e01C62d", "staticMessageIdWeightedMultisigIsmFactory": "0xC81e6D1070aFA48DA4e4f35E744CC1aE43532a10", - "gasCurrencyCoinGeckoId": "ethereum" + "gasCurrencyCoinGeckoId": "ethereum", + "interchainAccountIsm": "0xaec6382e1e16Ee12DBEf0e7EA5ADa51217813Fc3", + "interchainAccountRouter": "0x20cC3a33C49fa13627303669edf2DcA7F1E76a50", + "timelockController": "0x0000000000000000000000000000000000000000" }, "basesepolia": { "aggregationHook": "0xccA408a6A9A6dc405C3278647421eb4317466943", @@ -165,7 +162,7 @@ "from": 13851043 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x6Cf48F7b26374a741EE5290ECB58b23cCA171baa", + "interchainSecurityModule": "0x705Bc62100E041779931517E6B300B770BB266a9", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -198,7 +195,10 @@ "validatorAnnounce": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", "staticMerkleRootWeightedMultisigIsmFactory": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", "staticMessageIdWeightedMultisigIsmFactory": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", - "gasCurrencyCoinGeckoId": "ethereum" + "gasCurrencyCoinGeckoId": "ethereum", + "interchainAccountIsm": "0xDa5177080f7fC5d9255eB32cC64B9b4e5136A716", + "interchainAccountRouter": "0xd876C01aB40e8cE42Db417fBC79c726d45504dE4", + "timelockController": "0x0000000000000000000000000000000000000000" }, "bsctestnet": { "aggregationHook": "0x3d675bB93250Ab7603F40cbb9194bae210784627", @@ -232,7 +232,7 @@ "interchainAccountIsm": "0xa9D8Ec959F34272B1a56D09AF00eeee58970d3AE", "interchainAccountRouter": "0x6d2B3e304E58c2a19f1492E7cf15CaF63Ce6e0d2", "interchainGasPaymaster": "0x0dD20e410bdB95404f71c5a4e7Fa67B892A5f949", - "interchainSecurityModule": "0xF97D14d7E3248665913A5037F82D06D63AB34786", + "interchainSecurityModule": "0x0d3f99da0366491a22DC49e0683489aA8108a616", "isTestnet": true, "mailbox": "0xF9F6F5646F478d5ab4e20B0F910C92F1CCC9Cc6D", "merkleTreeHook": "0xc6cbF39A747f5E28d1bDc8D9dfDAb2960Abd5A8f", @@ -301,7 +301,7 @@ "from": 4950 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0xED455C8355682915288AeFad41b460cc800A71D5", + "interchainSecurityModule": "0x427aFA9D1Bc6360Cb957FA7d51c84D9E516e3e11", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -332,7 +332,10 @@ "validatorAnnounce": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", "staticMerkleRootWeightedMultisigIsmFactory": "0x8584590ad637C61C7cDF72eFF3381Ee1c3D1bC8E", "staticMessageIdWeightedMultisigIsmFactory": "0xcCB305B1f21e5FbC85D1DD7Be5cd8d5bf5B7f863", - "gasCurrencyCoinGeckoId": "ethereum" + "gasCurrencyCoinGeckoId": "ethereum", + "interchainAccountIsm": "0xA30b2CbC14b97aa55bBC947f4AC6c4254971aFD1", + "interchainAccountRouter": "0xc9ab470A61571ac0c39B7E0923fbEaDdB58d98FE", + "timelockController": "0x0000000000000000000000000000000000000000" }, "eclipsetestnet": { "blocks": { @@ -399,7 +402,7 @@ "from": 1606754 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0xcF1260Dfc276e5A45fdC2FFB1C3CED97B4a50B05", + "interchainSecurityModule": "0x71Ff4b4D4C0743FA1f465ee297b52098086cF19B", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -429,7 +432,10 @@ "validatorAnnounce": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", "staticMerkleRootWeightedMultisigIsmFactory": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", "staticMessageIdWeightedMultisigIsmFactory": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", - "gasCurrencyCoinGeckoId": "ethereum" + "gasCurrencyCoinGeckoId": "ethereum", + "interchainAccountIsm": "0x0De2F539569Fb1e2e3C1d233f7A63a18B9A17110", + "interchainAccountRouter": "0x2C6dD6768E669EDB7b53f26067C1C4534862c3de", + "timelockController": "0x0000000000000000000000000000000000000000" }, "fuji": { "aggregationHook": "0x8E9b4006171c6B75111823e7545Ee5400CEce0B3", @@ -462,7 +468,7 @@ "interchainAccountIsm": "0xfaB4815BDC5c60c6bD625459C8577aFdD79D9311", "interchainAccountRouter": "0xeEF6933122894fF217a7dd07510b3D64b747e29b", "interchainGasPaymaster": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", - "interchainSecurityModule": "0xA34D60b4634711C6384EE039E7A04b444daDa6F1", + "interchainSecurityModule": "0x579bdf6729F7A0256d5f7eDa0a27403D622a6f8e", "isTestnet": true, "mailbox": "0x5b6CFf85442B851A8e6eaBd2A4E4507B5135B3B0", "merkleTreeHook": "0x9ff6ac3dAf63103620BBf76136eA1AFf43c2F612", @@ -528,7 +534,7 @@ "from": 1543015 }, "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9", - "interchainSecurityModule": "0xDFEd7662f55F3115291244694B95FA7869195f7D", + "interchainSecurityModule": "0x037DC058b1976A1331E8d446B00743861d16AF3C", "isTestnet": true, "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc", "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE", @@ -558,7 +564,10 @@ "validatorAnnounce": "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2", "staticMerkleRootWeightedMultisigIsmFactory": "0xFb55597F07417b08195Ba674f4dd58aeC9B89FBB", "staticMessageIdWeightedMultisigIsmFactory": "0x0E18b28D98C2efDb59252c021320F203305b1B66", - "gasCurrencyCoinGeckoId": "ethereum" + "gasCurrencyCoinGeckoId": "ethereum", + "interchainAccountIsm": "0xb04961F492f447A8bA10f6694Bd888C7619CD2D5", + "interchainAccountRouter": "0xD31eD5a3D26c9787Ab607B0c364B21218D0f8F7b", + "timelockController": "0x0000000000000000000000000000000000000000" }, "optimismsepolia": { "aggregationHook": "0xccA408a6A9A6dc405C3278647421eb4317466943", @@ -590,7 +599,7 @@ "from": 15833917 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0xcF1260Dfc276e5A45fdC2FFB1C3CED97B4a50B05", + "interchainSecurityModule": "0x71Ff4b4D4C0743FA1f465ee297b52098086cF19B", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -619,7 +628,10 @@ "testRecipient": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", "validatorAnnounce": "0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9", "staticMerkleRootWeightedMultisigIsmFactory": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", - "staticMessageIdWeightedMultisigIsmFactory": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F" + "staticMessageIdWeightedMultisigIsmFactory": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "interchainAccountIsm": "0xA7FA26ef3Ea88CD696779735AC9591E01146DA38", + "interchainAccountRouter": "0x3F100cBBE5FD5466BdB4B3a15Ac226957e7965Ad", + "timelockController": "0x0000000000000000000000000000000000000000" }, "plumetestnet": { "aggregationHook": "0x31dF0EEE7Dc7565665468698a0da221225619a1B", @@ -715,7 +727,7 @@ "from": 10634605 }, "interchainGasPaymaster": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", - "interchainSecurityModule": "0x1aB93dF40998f4aFC4FbBdF1B81fa7333171fFe9", + "interchainSecurityModule": "0xf509b027ad15886F3bc91704510c758036571204", "isTestnet": true, "mailbox": "0x54148470292C24345fb828B003461a9444414517", "merkleTreeHook": "0xddf4C3e791caCaFd26D7fb275549739B38ae6e75", @@ -754,7 +766,10 @@ "validatorAnnounce": "0x11918DC33E067C5DA83EEF58E50F856398b8Df4C", "staticMerkleRootWeightedMultisigIsmFactory": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", "staticMessageIdWeightedMultisigIsmFactory": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", - "gasCurrencyCoinGeckoId": "polygon-ecosystem-token" + "gasCurrencyCoinGeckoId": "polygon-ecosystem-token", + "interchainAccountIsm": "0xd876C01aB40e8cE42Db417fBC79c726d45504dE4", + "interchainAccountRouter": "0xC60C145f1e1904f9d6483A611BF1416697CCc1FE", + "timelockController": "0x0000000000000000000000000000000000000000" }, "scrollsepolia": { "aggregationHook": "0x7b63Aa270335F8896717c2A809205F4b650E4268", @@ -787,7 +802,7 @@ "interchainAccountIsm": "0xE023239c8dfc172FF008D8087E7442d3eBEd9350", "interchainAccountRouter": "0xe17c37212d785760E8331D4A4395B17b34Ba8cDF", "interchainGasPaymaster": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", - "interchainSecurityModule": "0x30Ae39e0EBd119ee9d6EBD4AF2bEe61F67A3cDb3", + "interchainSecurityModule": "0x8320d192d6aE2B8d054b8d022B8d4303C66E91d2", "isTestnet": true, "mailbox": "0x3C5154a193D6e2955650f9305c8d80c18C814A68", "merkleTreeHook": "0x863E8c26621c52ACa1849C53500606e73BA272F0", @@ -865,7 +880,7 @@ "interchainAccountIsm": "0x83a3068B719F764d413625dA77468ED74789ae02", "interchainAccountRouter": "0x8e131c8aE5BF1Ed38D05a00892b6001a7d37739d", "interchainGasPaymaster": "0x6f2756380FD49228ae25Aa7F2817993cB74Ecc56", - "interchainSecurityModule": "0x3EcdB142F869313Dd80FA238370F0A910476aAA2", + "interchainSecurityModule": "0xfE5d0Dab653B3e0Aafd96F1A2BA85B1A4979159C", "isTestnet": true, "mailbox": "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766", "merkleTreeHook": "0x4917a9746A7B6E0A57159cCb7F5a6744247f2d0d", @@ -975,7 +990,7 @@ "from": 3111622 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0xED455C8355682915288AeFad41b460cc800A71D5", + "interchainSecurityModule": "0x427aFA9D1Bc6360Cb957FA7d51c84D9E516e3e11", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -1010,7 +1025,10 @@ "deployer": { "name": "Abacus Works", "url": "https://www.hyperlane.xyz" - } + }, + "interchainAccountIsm": "0xd09D08a19C6609a1B51e1ca6a055861E7e7A4400", + "interchainAccountRouter": "0x3572a9d808738922194921b275B2A55414BcDA57", + "timelockController": "0x0000000000000000000000000000000000000000" }, "berabartio": { "blockExplorers": [ @@ -1060,7 +1078,7 @@ "interchainAccountIsm": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", "interchainAccountRouter": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", "interchainGasPaymaster": "0x04438ef7622f5412f82915F59caD4f704C61eA48", - "interchainSecurityModule": "0xe5993C6c42b581095b500Ea758fc0f4596BA2135", + "interchainSecurityModule": "0x71b7cAF9bBA8e6dA3f7Bf851DDb4E68dDe1F2E03", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", "pausableHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", @@ -1120,7 +1138,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", + "interchainSecurityModule": "0x31d510CadF82D7Ddeb45aF0f43D340C3A3bE7FEa", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1188,7 +1206,7 @@ "interchainAccountIsm": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", "interchainAccountRouter": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", "interchainGasPaymaster": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", - "interchainSecurityModule": "0xb7b7105E2ecb79453356E28dd8808FfA0AcF083d", + "interchainSecurityModule": "0x1f41d445C166d5FFBFfBa858259C6Ba96e7C44a2", "mailbox": "0xB08d78F439e55D02C398519eef61606A5926245F", "merkleTreeHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", "pausableHook": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c", @@ -1221,7 +1239,7 @@ } ], "blocks": { - "confirmations": 1, + "confirmations": 3, "estimateBlockTime": 2, "reorgPeriod": 1 }, @@ -1377,7 +1395,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", + "interchainSecurityModule": "0x31d510CadF82D7Ddeb45aF0f43D340C3A3bE7FEa", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1441,7 +1459,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", + "interchainSecurityModule": "0x31d510CadF82D7Ddeb45aF0f43D340C3A3bE7FEa", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1654,6 +1672,183 @@ "index": { "from": 111 } + }, + "arcadiatestnet": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.khalani.network/api", + "family": "blockscout", + "name": "Arcadia Testnet Explorer", + "url": "https://explorer.khalani.network" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 1 + }, + "chainId": 1098411886, + "displayName": "Arcadia Testnet", + "domainId": 1098411886, + "isTestnet": true, + "name": "arcadiatestnet", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.khalani.network" + } + ], + "aggregationHook": "0x862Ce2De59C13a0406c104d317CfaEf6B672D638", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "interchainAccountIsm": "0x54Bd02f0f20677e9846F8E9FdB1Abc7315C49C38", + "interchainAccountRouter": "0xBF2C366530C1269d531707154948494D3fF4AcA7", + "interchainGasPaymaster": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "interchainSecurityModule": "0x206789B0d838568eaFDcCa1e551FCF5c00bF99E2", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "pausableHook": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", + "pausableIsm": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "protocolFee": "0x01812D60958798695391dacF092BAc4a715B1718", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0x206789B0d838568eaFDcCa1e551FCF5c00bF99E2", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "testRecipient": "0xfBeaF07855181f8476B235Cf746A7DF3F9e386Fb", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "index": { + "from": 5243565 + } + }, + "sonictestnet": { + "blockExplorers": [ + { + "apiUrl": "https://testnet.soniclabs.com/api", + "family": "routescan", + "name": "Sonic Testnet Explorer", + "url": "https://testnet.soniclabs.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 1 + }, + "chainId": 64165, + "displayName": "Sonic Testnet", + "domainId": 64165, + "isTestnet": true, + "name": "sonictestnet", + "nativeToken": { + "decimals": 18, + "name": "Sonic", + "symbol": "S" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.testnet.soniclabs.com" + } + ], + "aggregationHook": "0x04B8A7B7BF29b269428c4976D6408BAf6fd42922", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "interchainAccountIsm": "0xc08675806BA844467E559E45E4bB59e66778bDcd", + "interchainAccountRouter": "0x39c85C84876479694A2470c0E8075e9d68049aFc", + "interchainGasPaymaster": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "interchainSecurityModule": "0x36c98C1909DC343270e8B898772646AC54B80abf", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "pausableHook": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "pausableIsm": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "protocolFee": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0xf0F828278DEfB0c703EE78E620D20BA72CD56D82", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "testRecipient": "0x01812D60958798695391dacF092BAc4a715B1718", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "index": { + "from": 78198240 + } + }, + "unichaintestnet": { + "blockExplorers": [ + { + "apiUrl": "https://unichain-sepolia.blockscout.com/api", + "family": "blockscout", + "name": "Unichain Sepolia Testnet Explorer", + "url": "https://unichain-sepolia.blockscout.com" + } + ], + "blocks": { + "confirmations": 3, + "estimateBlockTime": 1, + "reorgPeriod": 1 + }, + "chainId": 1301, + "displayName": "Unichain Testnet", + "domainId": 1301, + "isTestnet": true, + "name": "unichaintestnet", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://sepolia.unichain.org" + } + ], + "aggregationHook": "0x04B8A7B7BF29b269428c4976D6408BAf6fd42922", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "interchainAccountIsm": "0x3ca332A585FDB9d4FF51f2FA8999eA32184D3606", + "interchainAccountRouter": "0x4eC139a771eBdD3b0a0b67bb7E08960210882d44", + "interchainGasPaymaster": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "interchainSecurityModule": "0xbfb6EdE47bFa3d496a0B70BA11e61c4e25e9843F", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "pausableHook": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "pausableIsm": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "protocolFee": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0xf0F828278DEfB0c703EE78E620D20BA72CD56D82", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "testRecipient": "0x01812D60958798695391dacF092BAc4a715B1718", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "index": { + "from": 1721192 + } } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index d4a83d81a..e16f7849f 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -55,6 +55,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, // hyperliquidevmtestnet: false, + arcadiatestnet: true, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -63,8 +64,10 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< sepolia: true, solanatestnet: false, soneiumtestnet: true, + sonictestnet: true, suavetoliman: true, superpositiontestnet: true, + unichaintestnet: true, }, [Role.Relayer]: { alfajores: true, @@ -81,6 +84,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, // hyperliquidevmtestnet: false, + arcadiatestnet: true, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -89,8 +93,10 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< sepolia: true, solanatestnet: false, soneiumtestnet: true, + sonictestnet: true, suavetoliman: true, superpositiontestnet: true, + unichaintestnet: true, }, [Role.Scraper]: { alfajores: true, @@ -108,6 +114,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, // hyperliquidevmtestnet: false, + arcadiatestnet: true, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -117,8 +124,10 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< // Cannot scrape non-EVM chains solanatestnet: false, soneiumtestnet: true, + sonictestnet: true, suavetoliman: true, superpositiontestnet: false, + unichaintestnet: true, }, }; @@ -197,7 +206,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '6c45a05-20240927-172800', + tag: '1f80087-20241010-170348', }, blacklist: [...releaseCandidateHelloworldMatchingList, ...relayBlacklist], gasPaymentEnforcement, @@ -219,7 +228,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '6c45a05-20240927-172800', + tag: '1f80087-20241010-170348', }, chains: validatorChainConfig(Contexts.Hyperlane), resources: validatorResources, @@ -228,7 +237,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '6c45a05-20240927-172800', + tag: '1f80087-20241010-170348', }, resources: scraperResources, }, diff --git a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json index 2d78729bf..531d26084 100644 --- a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json @@ -47,6 +47,9 @@ "holesky": { "validators": ["0x7ab28ad88bb45867137ea823af88e2cb02359c03"] }, + "arcadiatestnet": { + "validators": ["0x7ce5973d3f22971546efb86f5a0417c1248e92f5"] + }, "optimismsepolia": { "validators": ["0x03efe4d0632ee15685d7e8f46dea0a874304aa29"] }, @@ -70,10 +73,16 @@ "soneiumtestnet": { "validators": ["0x2e2101020ccdbe76aeda1c27823b0150f43d0c63"] }, + "sonictestnet": { + "validators": ["0x62e6591d00daec3fb658c3d19403828b4e9ddbb3"] + }, "suavetoliman": { "validators": ["0xf58f6e30aabba34e8dd7f79b3168507192e2cc9b"] }, "superpositiontestnet": { "validators": ["0x1d3168504b23b73cdf9c27f13bb0a595d7f1a96a"] + }, + "unichaintestnet": { + "validators": ["0x5e99961cf71918308c3b17ef21b5f515a4f86fe5"] } } diff --git a/typescript/infra/config/environments/testnet4/core/verification.json b/typescript/infra/config/environments/testnet4/core/verification.json index 316cded26..c57b15308 100644 --- a/typescript/infra/config/environments/testnet4/core/verification.json +++ b/typescript/infra/config/environments/testnet4/core/verification.json @@ -1636,5 +1636,233 @@ "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", "isProxy": false } + ], + "sonictestnet": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000faa5", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000086e902d2f99bcceaa28b31747ec6dc5fd43b1be", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "constructorArguments": "000000000000000000000000628bc518ed1e0e8c6cbcd574eba0ee29e7f6943e00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E" + }, + { + "name": "ProtocolFee", + "address": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } + ], + "unichaintestnet": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000515", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000086e902d2f99bcceaa28b31747ec6dc5fd43b1be", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "constructorArguments": "000000000000000000000000628bc518ed1e0e8c6cbcd574eba0ee29e7f6943e00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E" + }, + { + "name": "ProtocolFee", + "address": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } + ], + "arcadiatestnet": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000041786f6e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c0000000000000000000000007c5b5bda7f1d1f70a6678abb4d894612fc76498f", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", + "constructorArguments": "000000000000000000000000c76e477437065093d353b7d56c81ff54d167b0ab00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xc76E477437065093D353b7d56c81ff54D167B0Ab" + }, + { + "name": "ProtocolFee", + "address": "0x01812D60958798695391dacF092BAc4a715B1718", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x867f2089D09903f208AeCac84E599B90E5a4A821", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/testnet4/funding.ts b/typescript/infra/config/environments/testnet4/funding.ts index 07821e157..72e9e1adc 100644 --- a/typescript/infra/config/environments/testnet4/funding.ts +++ b/typescript/infra/config/environments/testnet4/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '2bb7168-20240927-154029', + tag: '1f80087-20241010-170343', }, // We're currently using the same deployer key as testnet2. // To minimize nonce clobbering we offset the key funder cron @@ -41,6 +41,7 @@ export const keyFunderConfig: KeyFunderConfig< fuji: '5', holesky: '5', // hyperliquidevmtestnet: '0.1', + arcadiatestnet: '0.1', optimismsepolia: '0.1', // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: '0.2', @@ -50,8 +51,10 @@ export const keyFunderConfig: KeyFunderConfig< // no funding for solana solanatestnet: '0', soneiumtestnet: '0.1', + sonictestnet: '1', suavetoliman: '0.1', superpositiontestnet: '1', + unichaintestnet: '0.1', }, desiredKathyBalancePerChain: { alfajores: '1', diff --git a/typescript/infra/config/environments/testnet4/gasPrices.json b/typescript/infra/config/environments/testnet4/gasPrices.json index c61aed013..16721fec3 100644 --- a/typescript/infra/config/environments/testnet4/gasPrices.json +++ b/typescript/infra/config/environments/testnet4/gasPrices.json @@ -1,22 +1,22 @@ { "alfajores": { - "amount": "50.0", + "amount": "25.001", "decimals": 9 }, "arbitrumsepolia": { - "amount": "0.10127", + "amount": "0.1", "decimals": 9 }, "basesepolia": { - "amount": "0.001000266", + "amount": "0.848937045", "decimals": 9 }, "berabartio": { - "amount": "0.010488335", + "amount": "0.001002518", "decimals": 9 }, "bsctestnet": { - "amount": "5.0", + "amount": "6.24", "decimals": 9 }, "camptestnet": { @@ -44,27 +44,31 @@ "decimals": 9 }, "fuji": { - "amount": "25.0", + "amount": "25.000000001", "decimals": 9 }, "holesky": { - "amount": "0.858734023", + "amount": "5.303619742", + "decimals": 9 + }, + "arcadiatestnet": { + "amount": "0.000000008", "decimals": 9 }, "optimismsepolia": { - "amount": "0.001000262", + "amount": "0.001000352", "decimals": 9 }, "polygonamoy": { - "amount": "37.870000015", + "amount": "76.735824005", "decimals": 9 }, "scrollsepolia": { - "amount": "1", + "amount": "0.096714808", "decimals": 9 }, "sepolia": { - "amount": "277.866557179", + "amount": "17.754991636", "decimals": 9 }, "solanatestnet": { @@ -72,7 +76,11 @@ "decimals": 9 }, "soneiumtestnet": { - "amount": "0.001000252", + "amount": "0.001000259", + "decimals": 9 + }, + "sonictestnet": { + "amount": "1.025001", "decimals": 9 }, "suavetoliman": { @@ -82,5 +90,9 @@ "superpositiontestnet": { "amount": "0.01", "decimals": 9 + }, + "unichaintestnet": { + "amount": "0.001000252", + "decimals": 9 } } diff --git a/typescript/infra/config/environments/testnet4/ism/verification.json b/typescript/infra/config/environments/testnet4/ism/verification.json index 22e1df29d..63fb16463 100644 --- a/typescript/infra/config/environments/testnet4/ism/verification.json +++ b/typescript/infra/config/environments/testnet4/ism/verification.json @@ -103,6 +103,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x09B61c756B3b85BfE871157734e6460d66C8285b", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x5681fbf346EED083FD86b299c150c9701A65FE74", + "constructorArguments": "", + "isProxy": true } ], "arbitrumsepolia": [ @@ -147,6 +159,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0xF7FF9b4918484720439928399eeF3584a5f4eEF4", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xb64A0B363326BA2b2cD474987A739A0e3A04Fd8d", + "constructorArguments": "", + "isProxy": true } ], "basesepolia": [ @@ -221,6 +245,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x2ACC0D75aA6cC2829C0ABdA5e2C782E2b4792eB0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x5E9922718b01AD4C82dCFD699ceAC0cF5F89fBBc", + "constructorArguments": "", + "isProxy": true } ], "bsctestnet": [ @@ -327,6 +363,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x9BDeB5c75D786040eB91B29D0cF3aa3E911e47C0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xcf6C887DaE2b04CC8414D8eb5363EaE8eD964158", + "constructorArguments": "", + "isProxy": true } ], "connextsepolia": [ @@ -401,6 +449,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x385aE4e729d86Ac4983d01597c33dFAa8C35686A", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xE14B55637Cc5aF2A55024D2f281446b388D64874", + "constructorArguments": "", + "isProxy": true } ], "ecotestnet": [ @@ -475,6 +535,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x76743F08b266371dCC7840bD7A445D5A52b3a752", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x1A70D3cbC72eF4941Ee047FA1F1E0469B940EDda", + "constructorArguments": "", + "isProxy": true } ], "fuji": [ @@ -591,6 +663,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0xE55d19c15a8EFD8420f6E1b922cbd8C126Bc8582", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x470e03D0E844DC7D3f11cc3f299D2C48cd14Cf3E", + "constructorArguments": "", + "isProxy": true } ], "holesky": [ @@ -665,6 +749,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x6E2B21A88b70cd3Bc455174941753512fB8a981e", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xEFfa6907D9caB3680b1Be2AA2207B0Fb8900E27a", + "constructorArguments": "", + "isProxy": true } ], "moonbasealpha": [ @@ -833,6 +929,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x5E9922718b01AD4C82dCFD699ceAC0cF5F89fBBc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x9e762493C57b1aa7acCd22f67aaD072ADC88CB1e", + "constructorArguments": "", + "isProxy": true } ], "plumetestnet": [ @@ -981,6 +1089,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x5E9922718b01AD4C82dCFD699ceAC0cF5F89fBBc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x9e762493C57b1aa7acCd22f67aaD072ADC88CB1e", + "constructorArguments": "", + "isProxy": true } ], "scrollsepolia": [ @@ -1067,6 +1187,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x921B24e07f1Ba25f6f7B280DC025De6a135951A4", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xab731b6237B4C4E864dd713949011E32DD19A3a2", + "constructorArguments": "", + "isProxy": true } ], "sepolia": [ @@ -1173,6 +1305,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x1c6bD6893a3484D603035E1060ed37eaeC53873f", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x0540D3c8C7Ae44f3Eb70C4cb8eA38eF27248347C", + "constructorArguments": "", + "isProxy": true } ], "superpositiontestnet": [ @@ -1247,6 +1391,18 @@ "constructorArguments": "", "isProxy": false, "name": "StaticMessageIdWeightedMultisigIsmFactory" + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x689C320286d74406AA9A08170DAbB87aC67FF711", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xA2425897Fe6325162313CA7F0803078b3A20759F", + "constructorArguments": "", + "isProxy": true } ], "mevmdevnet": [ @@ -1936,5 +2092,263 @@ "constructorArguments": "", "isProxy": true } + ], + "sonictestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } + ], + "unichaintestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } + ], + "arcadiatestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json b/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json index ab0ed9c9b..74e8061c2 100644 --- a/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json @@ -262,5 +262,236 @@ "isProxy": true, "expectedimplementation": "0x01812D60958798695391dacF092BAc4a715B1718" } + ], + "connextsepolia": [ + { + "name": "InterchainAccountIsm", + "address": "0xA30b2CbC14b97aa55bBC947f4AC6c4254971aFD1", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x0FAc4476d5cE3C057141Ab4df47BFC2ceE2bB259", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xc9ab470A61571ac0c39B7E0923fbEaDdB58d98FE", + "constructorArguments": "0000000000000000000000000fac4476d5ce3c057141ab4df47bfc2cee2bb25900000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a30b2cbc14b97aa55bbc947f4ac6c4254971afd1000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x0FAc4476d5cE3C057141Ab4df47BFC2ceE2bB259" + } + ], + "arbitrumsepolia": [ + { + "name": "InterchainAccountIsm", + "address": "0xaec6382e1e16Ee12DBEf0e7EA5ADa51217813Fc3", + "constructorArguments": "000000000000000000000000598face78a4302f11e3de0bee1894da0b2cb71f8", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x52Fbf023eDA2610653daD5ACA0b84356e4979669", + "constructorArguments": "000000000000000000000000598face78a4302f11e3de0bee1894da0b2cb71f8", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x20cC3a33C49fa13627303669edf2DcA7F1E76a50", + "constructorArguments": "00000000000000000000000052fbf023eda2610653dad5aca0b84356e4979669000000000000000000000000666a24f62f7a97ba33c151776eb3d9441a059eb800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aec6382e1e16ee12dbef0e7ea5ada51217813fc3000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x52Fbf023eDA2610653daD5ACA0b84356e4979669" + } + ], + "superpositiontestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0xd09D08a19C6609a1B51e1ca6a055861E7e7A4400", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x56c09458cC7863fff1Cc6Bcb6652Dcc3412FcA86", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3572a9d808738922194921b275B2A55414BcDA57", + "constructorArguments": "00000000000000000000000056c09458cc7863fff1cc6bcb6652dcc3412fca8600000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d09d08a19c6609a1b51e1ca6a055861e7e7a4400000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x56c09458cC7863fff1Cc6Bcb6652Dcc3412FcA86" + } + ], + "sonictestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0xc08675806BA844467E559E45E4bB59e66778bDcd", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x3ca332A585FDB9d4FF51f2FA8999eA32184D3606", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x39c85C84876479694A2470c0E8075e9d68049aFc", + "constructorArguments": "0000000000000000000000003ca332a585fdb9d4ff51f2fa8999ea32184d360600000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c08675806ba844467e559e45e4bb59e66778bdcd000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3ca332A585FDB9d4FF51f2FA8999eA32184D3606" + } + ], + "ecotestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0x0De2F539569Fb1e2e3C1d233f7A63a18B9A17110", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x111F4f782B47881898755Bd2F67f12876893300E", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x2C6dD6768E669EDB7b53f26067C1C4534862c3de", + "constructorArguments": "000000000000000000000000111f4f782b47881898755bd2f67f12876893300e00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de2f539569fb1e2e3c1d233f7a63a18b9a17110000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x111F4f782B47881898755Bd2F67f12876893300E" + } + ], + "optimismsepolia": [ + { + "name": "InterchainAccountIsm", + "address": "0xA7FA26ef3Ea88CD696779735AC9591E01146DA38", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x2188512B68A5FF76431D538a613C0e2b15C7faf4", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3F100cBBE5FD5466BdB4B3a15Ac226957e7965Ad", + "constructorArguments": "0000000000000000000000002188512b68a5ff76431d538a613c0e2b15c7faf400000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7fa26ef3ea88cd696779735ac9591e01146da38000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x2188512B68A5FF76431D538a613C0e2b15C7faf4" + } + ], + "arcadiatestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0x54Bd02f0f20677e9846F8E9FdB1Abc7315C49C38", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x5e65279Fb7293a058776e37587398fcc3E9184b1", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xBF2C366530C1269d531707154948494D3fF4AcA7", + "constructorArguments": "0000000000000000000000005e65279fb7293a058776e37587398fcc3e9184b100000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054bd02f0f20677e9846f8e9fdb1abc7315c49c38000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x5e65279Fb7293a058776e37587398fcc3E9184b1" + } + ], + "basesepolia": [ + { + "name": "InterchainAccountIsm", + "address": "0xDa5177080f7fC5d9255eB32cC64B9b4e5136A716", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x14EE2f01907707Ce8d13C4F5DBC40778b5b664e0", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xd876C01aB40e8cE42Db417fBC79c726d45504dE4", + "constructorArguments": "00000000000000000000000014ee2f01907707ce8d13c4f5dbc40778b5b664e000000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000da5177080f7fc5d9255eb32cc64b9b4e5136a716000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x14EE2f01907707Ce8d13C4F5DBC40778b5b664e0" + } + ], + "unichaintestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0x3ca332A585FDB9d4FF51f2FA8999eA32184D3606", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x342B5630Ba1C1e4d3048E51Dad208201aF52692c", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x4eC139a771eBdD3b0a0b67bb7E08960210882d44", + "constructorArguments": "000000000000000000000000342b5630ba1c1e4d3048e51dad208201af52692c00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ca332a585fdb9d4ff51f2fa8999ea32184d3606000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x342B5630Ba1C1e4d3048E51Dad208201aF52692c" + } + ], + "holesky": [ + { + "name": "InterchainAccountIsm", + "address": "0xb04961F492f447A8bA10f6694Bd888C7619CD2D5", + "constructorArguments": "00000000000000000000000046f7c5d896bbec89be1b19e4485e59b4be49e9cc", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x81E1b2D45694581A22aa577A2210A3E0b1Af663D", + "constructorArguments": "00000000000000000000000046f7c5d896bbec89be1b19e4485e59b4be49e9cc", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xD31eD5a3D26c9787Ab607B0c364B21218D0f8F7b", + "constructorArguments": "00000000000000000000000081e1b2d45694581a22aa577a2210a3e0b1af663d00000000000000000000000033db966328ea213b0f76ef96ca368ab37779f06500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b04961f492f447a8ba10f6694bd888c7619cd2d5000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x81E1b2D45694581A22aa577A2210A3E0b1Af663D" + } + ], + "polygonamoy": [ + { + "name": "InterchainAccountIsm", + "address": "0xd876C01aB40e8cE42Db417fBC79c726d45504dE4", + "constructorArguments": "00000000000000000000000054148470292c24345fb828b003461a9444414517", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xF61322936D80cd87B49df48F3DE24fD5c02dE9D1", + "constructorArguments": "00000000000000000000000054148470292c24345fb828b003461a9444414517", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xC60C145f1e1904f9d6483A611BF1416697CCc1FE", + "constructorArguments": "000000000000000000000000f61322936d80cd87b49df48f3de24fd5c02de9d1000000000000000000000000c2e36cd6e32e194ee11f15d9273b64461a4d49a200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d876c01ab40e8ce42db417fbc79c726d45504de4000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xF61322936D80cd87B49df48F3DE24fD5c02dE9D1" + } ] } diff --git a/typescript/infra/config/environments/testnet4/supportedChainNames.ts b/typescript/infra/config/environments/testnet4/supportedChainNames.ts index ad4d18cb2..466906857 100644 --- a/typescript/infra/config/environments/testnet4/supportedChainNames.ts +++ b/typescript/infra/config/environments/testnet4/supportedChainNames.ts @@ -14,6 +14,7 @@ export const testnet4SupportedChainNames = [ 'fuji', 'holesky', // 'hyperliquidevmtestnet', + 'arcadiatestnet', 'optimismsepolia', // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // 'plumetestnet', @@ -22,8 +23,10 @@ export const testnet4SupportedChainNames = [ 'sepolia', 'solanatestnet', 'soneiumtestnet', + 'sonictestnet', 'suavetoliman', 'superpositiontestnet', + 'unichaintestnet', ] as const; export const supportedChainNames = [...testnet4SupportedChainNames]; diff --git a/typescript/infra/config/environments/testnet4/tokenPrices.json b/typescript/infra/config/environments/testnet4/tokenPrices.json index 234899427..92e5f4a70 100644 --- a/typescript/infra/config/environments/testnet4/tokenPrices.json +++ b/typescript/infra/config/environments/testnet4/tokenPrices.json @@ -12,12 +12,15 @@ "formtestnet": "10", "fuji": "10", "holesky": "10", + "arcadiatestnet": "10", "optimismsepolia": "10", "polygonamoy": "10", "scrollsepolia": "10", "sepolia": "10", "solanatestnet": "10", "soneiumtestnet": "10", + "sonictestnet": "10", "suavetoliman": "10", - "superpositiontestnet": "10" + "superpositiontestnet": "10", + "unichaintestnet": "10" } diff --git a/typescript/infra/config/environments/testnet4/validators.ts b/typescript/infra/config/environments/testnet4/validators.ts index ef74e8046..3c53b47da 100644 --- a/typescript/infra/config/environments/testnet4/validators.ts +++ b/typescript/infra/config/environments/testnet4/validators.ts @@ -209,18 +209,18 @@ export const validatorChainConfig = ( 'polygonamoy', ), }, - hyperliquidevmtestnet: { - interval: 5, - reorgPeriod: getReorgPeriod('hyperliquidevmtestnet'), - validators: validatorsConfig( - { - [Contexts.Hyperlane]: ['0xea673a92a23ca319b9d85cc16b248645cd5158da'], - [Contexts.ReleaseCandidate]: [], - [Contexts.Neutron]: [], - }, - 'hyperliquidevmtestnet', - ), - }, + // hyperliquidevmtestnet: { + // interval: 5, + // reorgPeriod: getReorgPeriod('hyperliquidevmtestnet'), + // validators: validatorsConfig( + // { + // [Contexts.Hyperlane]: ['0xea673a92a23ca319b9d85cc16b248645cd5158da'], + // [Contexts.ReleaseCandidate]: [], + // [Contexts.Neutron]: [], + // }, + // 'hyperliquidevmtestnet', + // ), + // }, berabartio: { interval: 5, reorgPeriod: getReorgPeriod('berabartio'), @@ -293,5 +293,42 @@ export const validatorChainConfig = ( 'suavetoliman', ), }, + + unichaintestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('unichaintestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x5e99961cf71918308c3b17ef21b5f515a4f86fe5'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'unichaintestnet', + ), + }, + sonictestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('sonictestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x62e6591d00daec3fb658c3d19403828b4e9ddbb3'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'sonictestnet', + ), + }, + arcadiatestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('arcadiatestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x7ce5973d3f22971546efb86f5a0417c1248e92f5'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'arcadiatestnet', + ), + }, }; }; diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index ac68c1f9e..f9a752fba 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -42,6 +42,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0x09fabfbca0b8bf042e2a1161ee5010d147b0f603'], }, + arcadiatestnet: { + threshold: 1, + validators: ['0x7ce5973d3f22971546efb86f5a0417c1248e92f5'], + }, + astar: { threshold: 2, validators: [ @@ -669,6 +674,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0x2e2101020ccdbe76aeda1c27823b0150f43d0c63'], }, + sonictestnet: { + threshold: 1, + validators: ['0x62e6591d00daec3fb658c3d19403828b4e9ddbb3'], + }, + stride: { threshold: 6, validators: [ @@ -719,6 +729,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + unichaintestnet: { + threshold: 1, + validators: ['0x5e99961cf71918308c3b17ef21b5f515a4f86fe5'], + }, + viction: { threshold: 2, validators: [ From 46044a2e98d34107017f5fed5d70bdae1ed21462 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Fri, 11 Oct 2024 18:05:22 +0100 Subject: [PATCH 129/224] feat: deploy to odysseytestnet (#4670) ### Description feat: deploy to odysseytestnet ### Drive-by changes na ### Related issues na ### Backward compatibility yes ### Testing manual --- .changeset/dirty-months-buy.md | 5 + .registryrc | 2 +- rust/main/config/mainnet_config.json | 4 +- rust/main/config/testnet_config.json | 119 ++++++++++++++---- .../config/environments/testnet4/agent.ts | 15 ++- .../testnet4/aw-validators/hyperlane.json | 7 +- .../testnet4/core/verification.json | 76 +++++++++++ .../config/environments/testnet4/funding.ts | 5 +- .../environments/testnet4/gasPrices.json | 28 +++-- .../testnet4/ism/verification.json | 86 +++++++++++++ .../middleware/accounts/verification.json | 21 ++++ .../testnet4/supportedChainNames.ts | 3 +- .../environments/testnet4/tokenPrices.json | 3 +- .../environments/testnet4/validators.ts | 13 ++ typescript/sdk/src/consts/multisigIsm.ts | 5 + 15 files changed, 343 insertions(+), 49 deletions(-) create mode 100644 .changeset/dirty-months-buy.md diff --git a/.changeset/dirty-months-buy.md b/.changeset/dirty-months-buy.md new file mode 100644 index 000000000..2b3f91e99 --- /dev/null +++ b/.changeset/dirty-months-buy.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Deploy to odysseytestnet diff --git a/.registryrc b/.registryrc index 6ba08a96c..770382734 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -e3330d51ebad77e2aa62c34d5a74746ae5e83e64 +3b9f67add3338f151154bc5db76bf4e296f018dd diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index e4866b036..47f9c94ef 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -564,10 +564,10 @@ "aggregationHook": "0x8007d1e60991fB9BE1be26f70A7cE284fdE7da97", "blockExplorers": [ { - "apiUrl": "https://fetascan.io/api", + "apiUrl": "https://fetascan.xyz/api", "family": "blockscout", "name": "Fetascan", - "url": "https://fetascan.io" + "url": "https://fetascan.xyz" } ], "blocks": { diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index 5239f11e9..a72250818 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -31,7 +31,7 @@ "interchainAccountIsm": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", "interchainAccountRouter": "0xEbA64c8a9b4a61a9210d5fe7E4375380999C821b", "interchainGasPaymaster": "0x44769b0f4a6f01339e131a691cc2eebbb519d297", - "interchainSecurityModule": "0xeb06b892C48332bc11287c2E73090a59751F7d85", + "interchainSecurityModule": "0xC8513429105955cf01669bfD1ac5396Faf0748a5", "isTestnet": true, "mailbox": "0xEf9F292fcEBC3848bF4bB92a96a04F9ECBb78E59", "merkleTreeHook": "0x221FA9CBaFcd6c1C3d206571Cf4427703e023FFa", @@ -94,7 +94,7 @@ "from": 49690504 }, "interchainGasPaymaster": "0xc756cFc1b7d0d4646589EDf10eD54b201237F5e8", - "interchainSecurityModule": "0x0bDe2dA99d7A0F0F3b1419e1f8E06Ad155906277", + "interchainSecurityModule": "0xA6D6d30c37434b142618eF97AB15a71871d721C6", "isTestnet": true, "mailbox": "0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8", "merkleTreeHook": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", @@ -162,7 +162,7 @@ "from": 13851043 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x705Bc62100E041779931517E6B300B770BB266a9", + "interchainSecurityModule": "0x3E857CB33b76f680F3dB557Ce3BBf2591A98d92d", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -232,7 +232,7 @@ "interchainAccountIsm": "0xa9D8Ec959F34272B1a56D09AF00eeee58970d3AE", "interchainAccountRouter": "0x6d2B3e304E58c2a19f1492E7cf15CaF63Ce6e0d2", "interchainGasPaymaster": "0x0dD20e410bdB95404f71c5a4e7Fa67B892A5f949", - "interchainSecurityModule": "0x0d3f99da0366491a22DC49e0683489aA8108a616", + "interchainSecurityModule": "0x2B3bEc44051C3A0c26360Ae513e98A947E9939b7", "isTestnet": true, "mailbox": "0xF9F6F5646F478d5ab4e20B0F910C92F1CCC9Cc6D", "merkleTreeHook": "0xc6cbF39A747f5E28d1bDc8D9dfDAb2960Abd5A8f", @@ -301,7 +301,7 @@ "from": 4950 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0x427aFA9D1Bc6360Cb957FA7d51c84D9E516e3e11", + "interchainSecurityModule": "0x1e58386A3f012D69568B3E1aB5f8E41169Ba69A9", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -402,7 +402,7 @@ "from": 1606754 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x71Ff4b4D4C0743FA1f465ee297b52098086cF19B", + "interchainSecurityModule": "0x4c8A96b43fD59a4171b7c79d657AD9FedFb2d7B5", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -468,7 +468,7 @@ "interchainAccountIsm": "0xfaB4815BDC5c60c6bD625459C8577aFdD79D9311", "interchainAccountRouter": "0xeEF6933122894fF217a7dd07510b3D64b747e29b", "interchainGasPaymaster": "0x6895d3916B94b386fAA6ec9276756e16dAe7480E", - "interchainSecurityModule": "0x579bdf6729F7A0256d5f7eDa0a27403D622a6f8e", + "interchainSecurityModule": "0xe412A2d273c02d6f837532946d1B05A6EAB72B04", "isTestnet": true, "mailbox": "0x5b6CFf85442B851A8e6eaBd2A4E4507B5135B3B0", "merkleTreeHook": "0x9ff6ac3dAf63103620BBf76136eA1AFf43c2F612", @@ -534,7 +534,7 @@ "from": 1543015 }, "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9", - "interchainSecurityModule": "0x037DC058b1976A1331E8d446B00743861d16AF3C", + "interchainSecurityModule": "0xA4bFAA24c14f0398903E59344F4a36334F47AA50", "isTestnet": true, "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc", "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE", @@ -599,7 +599,7 @@ "from": 15833917 }, "interchainGasPaymaster": "0x28B02B97a850872C4D33C3E024fab6499ad96564", - "interchainSecurityModule": "0x71Ff4b4D4C0743FA1f465ee297b52098086cF19B", + "interchainSecurityModule": "0x4c8A96b43fD59a4171b7c79d657AD9FedFb2d7B5", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", @@ -727,7 +727,7 @@ "from": 10634605 }, "interchainGasPaymaster": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", - "interchainSecurityModule": "0xf509b027ad15886F3bc91704510c758036571204", + "interchainSecurityModule": "0xC5117582A9b64B5b3071B7f11943b21A515A84C6", "isTestnet": true, "mailbox": "0x54148470292C24345fb828B003461a9444414517", "merkleTreeHook": "0xddf4C3e791caCaFd26D7fb275549739B38ae6e75", @@ -802,7 +802,7 @@ "interchainAccountIsm": "0xE023239c8dfc172FF008D8087E7442d3eBEd9350", "interchainAccountRouter": "0xe17c37212d785760E8331D4A4395B17b34Ba8cDF", "interchainGasPaymaster": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", - "interchainSecurityModule": "0x8320d192d6aE2B8d054b8d022B8d4303C66E91d2", + "interchainSecurityModule": "0x69873c153380149e901b4aD031025Bc195ee1CB8", "isTestnet": true, "mailbox": "0x3C5154a193D6e2955650f9305c8d80c18C814A68", "merkleTreeHook": "0x863E8c26621c52ACa1849C53500606e73BA272F0", @@ -880,7 +880,7 @@ "interchainAccountIsm": "0x83a3068B719F764d413625dA77468ED74789ae02", "interchainAccountRouter": "0x8e131c8aE5BF1Ed38D05a00892b6001a7d37739d", "interchainGasPaymaster": "0x6f2756380FD49228ae25Aa7F2817993cB74Ecc56", - "interchainSecurityModule": "0xfE5d0Dab653B3e0Aafd96F1A2BA85B1A4979159C", + "interchainSecurityModule": "0x43b6a311BF787241BB71b7aE2a29ef639932b9b8", "isTestnet": true, "mailbox": "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766", "merkleTreeHook": "0x4917a9746A7B6E0A57159cCb7F5a6744247f2d0d", @@ -990,7 +990,7 @@ "from": 3111622 }, "interchainGasPaymaster": "0xeC7eb4196Bd601DEa7585A744FbFB4CF11278450", - "interchainSecurityModule": "0x427aFA9D1Bc6360Cb957FA7d51c84D9E516e3e11", + "interchainSecurityModule": "0x1e58386A3f012D69568B3E1aB5f8E41169Ba69A9", "isTestnet": true, "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", "merkleTreeHook": "0x4926a10788306D84202A2aDbd290b7743146Cc17", @@ -1078,7 +1078,7 @@ "interchainAccountIsm": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", "interchainAccountRouter": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", "interchainGasPaymaster": "0x04438ef7622f5412f82915F59caD4f704C61eA48", - "interchainSecurityModule": "0x71b7cAF9bBA8e6dA3f7Bf851DDb4E68dDe1F2E03", + "interchainSecurityModule": "0xDabB212640f59026a861202ca82CDcD8181aD723", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C", "pausableHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", @@ -1138,7 +1138,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x31d510CadF82D7Ddeb45aF0f43D340C3A3bE7FEa", + "interchainSecurityModule": "0x8214144F223b550E5BFf6164F2136F0Ef30bB8b3", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1206,7 +1206,7 @@ "interchainAccountIsm": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", "interchainAccountRouter": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", "interchainGasPaymaster": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", - "interchainSecurityModule": "0x1f41d445C166d5FFBFfBa858259C6Ba96e7C44a2", + "interchainSecurityModule": "0x792F905736703DCb511066f2E0C4b97504CD2728", "mailbox": "0xB08d78F439e55D02C398519eef61606A5926245F", "merkleTreeHook": "0x783c4a0bB6663359281aD4a637D5af68F83ae213", "pausableHook": "0x66b71A4e18FbE09a6977A6520B47fEDdffA82a1c", @@ -1267,7 +1267,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x98F2B677415e9105F69d3323A2341127A370367C", + "interchainSecurityModule": "0x8214144F223b550E5BFf6164F2136F0Ef30bB8b3", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1395,7 +1395,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x31d510CadF82D7Ddeb45aF0f43D340C3A3bE7FEa", + "interchainSecurityModule": "0x8214144F223b550E5BFf6164F2136F0Ef30bB8b3", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1459,7 +1459,7 @@ "interchainAccountIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "interchainAccountRouter": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "interchainGasPaymaster": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", - "interchainSecurityModule": "0x31d510CadF82D7Ddeb45aF0f43D340C3A3bE7FEa", + "interchainSecurityModule": "0x8214144F223b550E5BFf6164F2136F0Ef30bB8b3", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A", "pausableHook": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011", @@ -1710,7 +1710,7 @@ "interchainAccountIsm": "0x54Bd02f0f20677e9846F8E9FdB1Abc7315C49C38", "interchainAccountRouter": "0xBF2C366530C1269d531707154948494D3fF4AcA7", "interchainGasPaymaster": "0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD", - "interchainSecurityModule": "0x206789B0d838568eaFDcCa1e551FCF5c00bF99E2", + "interchainSecurityModule": "0xd89063A7e8Eaee25dA8D3b7eBcbAeF9869702A80", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F", "pausableHook": "0x628BC518ED1e0E8C6cbcD574EbA0ee29e7F6943E", @@ -1730,6 +1730,10 @@ "validatorAnnounce": "0x867f2089D09903f208AeCac84E599B90E5a4A821", "index": { "from": 5243565 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" } }, "sonictestnet": { @@ -1769,7 +1773,7 @@ "interchainAccountIsm": "0xc08675806BA844467E559E45E4bB59e66778bDcd", "interchainAccountRouter": "0x39c85C84876479694A2470c0E8075e9d68049aFc", "interchainGasPaymaster": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", - "interchainSecurityModule": "0x36c98C1909DC343270e8B898772646AC54B80abf", + "interchainSecurityModule": "0x8a5D09753Ab5571fa78131EF839C70AFa3c45bFd", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", "pausableHook": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", @@ -1789,6 +1793,10 @@ "validatorAnnounce": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "index": { "from": 78198240 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" } }, "unichaintestnet": { @@ -1828,7 +1836,7 @@ "interchainAccountIsm": "0x3ca332A585FDB9d4FF51f2FA8999eA32184D3606", "interchainAccountRouter": "0x4eC139a771eBdD3b0a0b67bb7E08960210882d44", "interchainGasPaymaster": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", - "interchainSecurityModule": "0xbfb6EdE47bFa3d496a0B70BA11e61c4e25e9843F", + "interchainSecurityModule": "0x4B2e8f63E345Db18973E46cE70972cE3D76585Bf", "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", "merkleTreeHook": "0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE", "pausableHook": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", @@ -1848,6 +1856,73 @@ "validatorAnnounce": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "index": { "from": 1721192 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + } + }, + "odysseytestnet": { + "blockExplorers": [ + { + "apiUrl": "https://odyssey-explorer.ithaca.xyz/api", + "family": "blockscout", + "name": "Odyssey Explorer", + "url": "https://odyssey-explorer.ithaca.xyz" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 1 + }, + "chainId": 911867, + "displayName": "Odyssey Testnet", + "domainId": 911867, + "isTestnet": true, + "name": "odysseytestnet", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://odyssey.ithaca.xyz" + } + ], + "aggregationHook": "0xf96cF73BB4e57F90479cD8f74bb4C1f6a0c3da50", + "domainRoutingIsm": "0x2a2F4AAaf726abb4B969c2804D38e188555683b5", + "domainRoutingIsmFactory": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "fallbackRoutingHook": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "interchainAccountIsm": "0xBF2C366530C1269d531707154948494D3fF4AcA7", + "interchainAccountRouter": "0xBdf49bE2201A1c4B13023F0a407196C6Adb32680", + "interchainGasPaymaster": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "interchainSecurityModule": "0x9e71cC1A91E48CfFA2F7D2956eB5c3b730bD8605", + "mailbox": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "merkleTreeHook": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "pausableHook": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "pausableIsm": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "protocolFee": "0xfBeaF07855181f8476B235Cf746A7DF3F9e386Fb", + "proxyAdmin": "0x54148470292C24345fb828B003461a9444414517", + "staticAggregationHookFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "staticAggregationIsm": "0x9e71cC1A91E48CfFA2F7D2956eB5c3b730bD8605", + "staticAggregationIsmFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "staticMerkleRootMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "staticMerkleRootWeightedMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "staticMessageIdMultisigIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "staticMessageIdWeightedMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "storageGasOracle": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", + "testRecipient": "0x5e65279Fb7293a058776e37587398fcc3E9184b1", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x54Bd02f0f20677e9846F8E9FdB1Abc7315C49C38", + "index": { + "from": 67925 + }, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" } } }, diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index e16f7849f..18b4b7690 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -43,6 +43,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< [Role.Validator]: { alfajores: true, arbitrumsepolia: true, + arcadiatestnet: true, basesepolia: true, berabartio: true, bsctestnet: true, @@ -55,7 +56,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, // hyperliquidevmtestnet: false, - arcadiatestnet: true, + odysseytestnet: true, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -72,6 +73,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< [Role.Relayer]: { alfajores: true, arbitrumsepolia: true, + arcadiatestnet: true, basesepolia: true, berabartio: true, bsctestnet: true, @@ -84,7 +86,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, // hyperliquidevmtestnet: false, - arcadiatestnet: true, + odysseytestnet: true, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -101,6 +103,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< [Role.Scraper]: { alfajores: true, arbitrumsepolia: true, + arcadiatestnet: true, basesepolia: true, berabartio: true, bsctestnet: true, @@ -114,7 +117,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< fuji: true, holesky: true, // hyperliquidevmtestnet: false, - arcadiatestnet: true, + odysseytestnet: true, optimismsepolia: true, // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: true, @@ -206,7 +209,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '1f80087-20241010-170348', + tag: '463b35b-20241011-161150', }, blacklist: [...releaseCandidateHelloworldMatchingList, ...relayBlacklist], gasPaymentEnforcement, @@ -228,7 +231,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '1f80087-20241010-170348', + tag: '463b35b-20241011-161150', }, chains: validatorChainConfig(Contexts.Hyperlane), resources: validatorResources, @@ -237,7 +240,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '1f80087-20241010-170348', + tag: '463b35b-20241011-161150', }, resources: scraperResources, }, diff --git a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json index 531d26084..ce4a9509f 100644 --- a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json @@ -9,6 +9,9 @@ "arbitrumsepolia": { "validators": ["0x09fabfbca0b8bf042e2a1161ee5010d147b0f603"] }, + "arcadiatestnet": { + "validators": ["0x7ce5973d3f22971546efb86f5a0417c1248e92f5"] + }, "basesepolia": { "validators": ["0x82e3b437a2944e3ff00258c93e72cd1ba5e0e921"] }, @@ -47,8 +50,8 @@ "holesky": { "validators": ["0x7ab28ad88bb45867137ea823af88e2cb02359c03"] }, - "arcadiatestnet": { - "validators": ["0x7ce5973d3f22971546efb86f5a0417c1248e92f5"] + "odysseytestnet": { + "validators": ["0xcc0a6e2d6aa8560b45b384ced7aa049870b66ea3"] }, "optimismsepolia": { "validators": ["0x03efe4d0632ee15685d7e8f46dea0a874304aa29"] diff --git a/typescript/infra/config/environments/testnet4/core/verification.json b/typescript/infra/config/environments/testnet4/core/verification.json index c57b15308..f43da291e 100644 --- a/typescript/infra/config/environments/testnet4/core/verification.json +++ b/typescript/infra/config/environments/testnet4/core/verification.json @@ -1864,5 +1864,81 @@ "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", "isProxy": false } + ], + "odysseytestnet": [ + { + "name": "ProxyAdmin", + "address": "0x54148470292C24345fb828B003461a9444414517", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x589C201a07c26b4725A4A829d772f24423da480B", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000de9fb", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD", + "constructorArguments": "000000000000000000000000589c201a07c26b4725a4a829d772f24423da480b00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x589C201a07c26b4725A4A829d772f24423da480B" + }, + { + "name": "PausableIsm", + "address": "0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8", + "constructorArguments": "000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000ffa913705484c9baea32ffe9945bea099a1dff72", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xc76E477437065093D353b7d56c81ff54D167B0Ab", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xB5fB1F5410a2c2b7deD462d018541383968cB01c", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", + "constructorArguments": "0000000000000000000000007483fad0bc297667664a43a064ba7c9911659f5700000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x7483faD0Bc297667664A43A064bA7c9911659f57" + }, + { + "name": "ProtocolFee", + "address": "0xfBeaF07855181f8476B235Cf746A7DF3F9e386Fb", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x54Bd02f0f20677e9846F8E9FdB1Abc7315C49C38", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/testnet4/funding.ts b/typescript/infra/config/environments/testnet4/funding.ts index 72e9e1adc..938dd880f 100644 --- a/typescript/infra/config/environments/testnet4/funding.ts +++ b/typescript/infra/config/environments/testnet4/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '1f80087-20241010-170343', + tag: '463b35b-20241011-161139', }, // We're currently using the same deployer key as testnet2. // To minimize nonce clobbering we offset the key funder cron @@ -28,6 +28,7 @@ export const keyFunderConfig: KeyFunderConfig< desiredBalancePerChain: { alfajores: '5', arbitrumsepolia: '0.1', + arcadiatestnet: '0.1', basesepolia: '0.1', berabartio: '0.1', bsctestnet: '5', @@ -41,7 +42,7 @@ export const keyFunderConfig: KeyFunderConfig< fuji: '5', holesky: '5', // hyperliquidevmtestnet: '0.1', - arcadiatestnet: '0.1', + odysseytestnet: '0.1', optimismsepolia: '0.1', // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // plumetestnet: '0.2', diff --git a/typescript/infra/config/environments/testnet4/gasPrices.json b/typescript/infra/config/environments/testnet4/gasPrices.json index 16721fec3..d3a14a854 100644 --- a/typescript/infra/config/environments/testnet4/gasPrices.json +++ b/typescript/infra/config/environments/testnet4/gasPrices.json @@ -4,19 +4,23 @@ "decimals": 9 }, "arbitrumsepolia": { - "amount": "0.1", + "amount": "0.11832", + "decimals": 9 + }, + "arcadiatestnet": { + "amount": "0.000000008", "decimals": 9 }, "basesepolia": { - "amount": "0.848937045", + "amount": "0.418699218", "decimals": 9 }, "berabartio": { - "amount": "0.001002518", + "amount": "0.005844801", "decimals": 9 }, "bsctestnet": { - "amount": "6.24", + "amount": "5.0", "decimals": 9 }, "camptestnet": { @@ -48,27 +52,27 @@ "decimals": 9 }, "holesky": { - "amount": "5.303619742", + "amount": "5.827232784", "decimals": 9 }, - "arcadiatestnet": { - "amount": "0.000000008", + "odysseytestnet": { + "amount": "1.000000252", "decimals": 9 }, "optimismsepolia": { - "amount": "0.001000352", + "amount": "0.001000268", "decimals": 9 }, "polygonamoy": { - "amount": "76.735824005", + "amount": "112.53", "decimals": 9 }, "scrollsepolia": { - "amount": "0.096714808", + "amount": "0.167584424", "decimals": 9 }, "sepolia": { - "amount": "17.754991636", + "amount": "37.999464941", "decimals": 9 }, "solanatestnet": { @@ -76,7 +80,7 @@ "decimals": 9 }, "soneiumtestnet": { - "amount": "0.001000259", + "amount": "0.001000261", "decimals": 9 }, "sonictestnet": { diff --git a/typescript/infra/config/environments/testnet4/ism/verification.json b/typescript/infra/config/environments/testnet4/ism/verification.json index 63fb16463..8fb1bf91e 100644 --- a/typescript/infra/config/environments/testnet4/ism/verification.json +++ b/typescript/infra/config/environments/testnet4/ism/verification.json @@ -2350,5 +2350,91 @@ "constructorArguments": "", "isProxy": true } + ], + "odysseytestnet": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xE5cA56294dA5Bd490D5Bc489B177B002ad16AF83", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7fFe8C9c17F46F94D784E148FbadD4bF66477722", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x4863236F3a05A1A1F0850fF8cd09afeBAE82d953", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json b/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json index 74e8061c2..efe1a13ea 100644 --- a/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/testnet4/middleware/accounts/verification.json @@ -493,5 +493,26 @@ "isProxy": true, "expectedimplementation": "0xF61322936D80cd87B49df48F3DE24fD5c02dE9D1" } + ], + "odysseytestnet": [ + { + "name": "InterchainAccountIsm", + "address": "0xBF2C366530C1269d531707154948494D3fF4AcA7", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x843908541D24d9F6Fa30C8Bb1c39038C947D08fC", + "constructorArguments": "000000000000000000000000ddcfecf17586d08a5740b7d91735fcce3dfe3eed", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xBdf49bE2201A1c4B13023F0a407196C6Adb32680", + "constructorArguments": "000000000000000000000000843908541d24d9f6fa30c8bb1c39038c947d08fc00000000000000000000000054148470292c24345fb828b003461a944441451700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf2c366530c1269d531707154948494d3ff4aca7000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x843908541D24d9F6Fa30C8Bb1c39038C947D08fC" + } ] } diff --git a/typescript/infra/config/environments/testnet4/supportedChainNames.ts b/typescript/infra/config/environments/testnet4/supportedChainNames.ts index 466906857..3643ff89a 100644 --- a/typescript/infra/config/environments/testnet4/supportedChainNames.ts +++ b/typescript/infra/config/environments/testnet4/supportedChainNames.ts @@ -2,6 +2,7 @@ export const testnet4SupportedChainNames = [ 'alfajores', 'arbitrumsepolia', + 'arcadiatestnet', 'basesepolia', 'berabartio', 'bsctestnet', @@ -14,7 +15,7 @@ export const testnet4SupportedChainNames = [ 'fuji', 'holesky', // 'hyperliquidevmtestnet', - 'arcadiatestnet', + 'odysseytestnet', 'optimismsepolia', // Disabling plumetestnet on Sept 16, 2024: chain is paused for "airplane mode" // 'plumetestnet', diff --git a/typescript/infra/config/environments/testnet4/tokenPrices.json b/typescript/infra/config/environments/testnet4/tokenPrices.json index 92e5f4a70..79c1811b2 100644 --- a/typescript/infra/config/environments/testnet4/tokenPrices.json +++ b/typescript/infra/config/environments/testnet4/tokenPrices.json @@ -1,6 +1,7 @@ { "alfajores": "10", "arbitrumsepolia": "10", + "arcadiatestnet": "10", "basesepolia": "10", "berabartio": "10", "bsctestnet": "10", @@ -12,7 +13,7 @@ "formtestnet": "10", "fuji": "10", "holesky": "10", - "arcadiatestnet": "10", + "odysseytestnet": "10", "optimismsepolia": "10", "polygonamoy": "10", "scrollsepolia": "10", diff --git a/typescript/infra/config/environments/testnet4/validators.ts b/typescript/infra/config/environments/testnet4/validators.ts index 3c53b47da..5db953450 100644 --- a/typescript/infra/config/environments/testnet4/validators.ts +++ b/typescript/infra/config/environments/testnet4/validators.ts @@ -330,5 +330,18 @@ export const validatorChainConfig = ( 'arcadiatestnet', ), }, + + odysseytestnet: { + interval: 5, + reorgPeriod: getReorgPeriod('odysseytestnet'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xcc0a6e2d6aa8560b45b384ced7aa049870b66ea3'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'odysseytestnet', + ), + }, }; }; diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index f9a752fba..5258e68c0 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -492,6 +492,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + odysseytestnet: { + threshold: 1, + validators: ['0xcc0a6e2d6aa8560b45b384ced7aa049870b66ea3'], + }, + oortmainnet: { threshold: 2, validators: [ From a4d5d692f3e8230cfbf2b87ac5e2775fe3da8bb9 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Sat, 12 Oct 2024 09:14:37 -0400 Subject: [PATCH 130/224] fix(cli): Update warp apply to apply changes in single command (#4672) ### Description This PR fixes a limitation in `warp apply` such that it can only extend _or_ update an existing warp route. This means that for configs with both changes require `warp apply` to be called multiple times. An example is when Renzo deploys to new chain, and it needs to update the existing ISMs. ### Related issues - Fixes #4671 ### Backward compatibility Yes ### Testing Manual/Unit Tests --- .changeset/tender-spiders-deny.md | 5 + typescript/cli/src/deploy/warp.ts | 256 ++++++++++-------- typescript/cli/src/tests/commands/helpers.ts | 2 +- .../cli/src/tests/warp-apply.e2e-test.ts | 67 ++++- 4 files changed, 211 insertions(+), 119 deletions(-) create mode 100644 .changeset/tender-spiders-deny.md diff --git a/.changeset/tender-spiders-deny.md b/.changeset/tender-spiders-deny.md new file mode 100644 index 000000000..99a6cede4 --- /dev/null +++ b/.changeset/tender-spiders-deny.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +Update `warp apply` such that it updates in place AND extends in a single call diff --git a/typescript/cli/src/deploy/warp.ts b/typescript/cli/src/deploy/warp.ts index 1fc13c1ec..872edb400 100644 --- a/typescript/cli/src/deploy/warp.ts +++ b/typescript/cli/src/deploy/warp.ts @@ -1,4 +1,5 @@ import { confirm } from '@inquirer/prompts'; +import { groupBy } from 'lodash-es'; import { stringify as yamlStringify } from 'yaml'; import { buildArtifact as coreBuildArtifact } from '@hyperlane-xyz/core/buildArtifact.js'; @@ -53,6 +54,7 @@ import { Address, ProtocolType, assert, + isObjEmpty, objFilter, objKeys, objMap, @@ -64,14 +66,7 @@ import { readWarpRouteDeployConfig } from '../config/warp.js'; import { MINIMUM_WARP_DEPLOY_GAS } from '../consts.js'; import { getOrRequestApiKeys } from '../context/context.js'; import { WriteCommandContext } from '../context/types.js'; -import { - log, - logBlue, - logGray, - logGreen, - logRed, - logTable, -} from '../logger.js'; +import { log, logBlue, logGray, logGreen, logTable } from '../logger.js'; import { getSubmitterBuilder } from '../submit/submit.js'; import { indentYamlOrJson, @@ -438,17 +433,13 @@ export async function runWarpRouteApply( params: WarpApplyParams, ): Promise { const { warpDeployConfig, warpCoreConfig, context } = params; - const { registry, multiProvider, chainMetadata, skipConfirmation } = context; + const { chainMetadata, skipConfirmation } = context; WarpRouteDeployConfigSchema.parse(warpDeployConfig); WarpCoreConfigSchema.parse(warpCoreConfig); - const addresses = await registry.getAddresses(); const warpCoreConfigByChain = Object.fromEntries( - warpCoreConfig.tokens.map((token) => [ - token.chainName, - token, - ]) /* Necessary for O(1) reads below */, + warpCoreConfig.tokens.map((token) => [token.chainName, token]), ); const chains = Object.keys(warpDeployConfig); @@ -457,94 +448,119 @@ export async function runWarpRouteApply( if (!skipConfirmation) apiKeys = await getOrRequestApiKeys(chains, chainMetadata); - const contractVerifier = new ContractVerifier( - multiProvider, - apiKeys, - coreBuildArtifact, - ExplorerLicenseType.MIT, - ); + const transactions: AnnotatedEV5Transaction[] = [ + ...(await extendWarpRoute( + params, + apiKeys, + warpDeployConfig, + warpCoreConfigByChain, + )), + ...(await updateExistingWarpRoute( + params, + apiKeys, + warpDeployConfig, + warpCoreConfigByChain, + )), + ]; + if (transactions.length == 0) + return logGreen(`Warp config is the same as target. No updates needed.`); - const warpDeployChains = Object.keys(warpDeployConfig); + await submitWarpApplyTransactions(params, groupBy(transactions, 'chainId')); +} + +async function extendWarpRoute( + params: WarpApplyParams, + apiKeys: ChainMap, + warpDeployConfig: WarpRouteDeployConfig, + warpCoreConfigByChain: ChainMap, +) { + logBlue('Extending Warp Route'); + const { multiProvider } = params.context; const warpCoreChains = Object.keys(warpCoreConfigByChain); - if (warpDeployChains.length === warpCoreChains.length) { - logGray('Updating deployed Warp Routes'); - await promiseObjAll( - objMap(warpDeployConfig, async (chain, config) => { - try { - config.ismFactoryAddresses = addresses[ - chain - ] as ProxyFactoryFactoriesAddresses; - const evmERC20WarpModule = new EvmERC20WarpModule( - multiProvider, - { - config, - chain, - addresses: { - deployedTokenRoute: - warpCoreConfigByChain[chain].addressOrDenom!, - }, - }, - contractVerifier, - ); - const transactions = await evmERC20WarpModule.update(config); - - if (transactions.length == 0) - return logGreen( - `Warp config on ${chain} is the same as target. No updates needed.`, - ); - await submitWarpApplyTransactions(chain, params, transactions); - } catch (e) { - logRed(`Warp config on ${chain} failed to update.`, e); - } - }), - ); - } else if (warpDeployChains.length > warpCoreChains.length) { - logGray('Extending deployed Warp configs'); - // Split between the existing and additional config - const existingConfigs: WarpRouteDeployConfig = objFilter( - warpDeployConfig, - (chain, _config): _config is any => warpCoreChains.includes(chain), - ); + // Split between the existing and additional config + const existingConfigs: WarpRouteDeployConfig = objFilter( + warpDeployConfig, + (chain, _config): _config is any => warpCoreChains.includes(chain), + ); - let extendedConfigs: WarpRouteDeployConfig = objFilter( - warpDeployConfig, - (chain, _config): _config is any => !warpCoreChains.includes(chain), - ); + let extendedConfigs: WarpRouteDeployConfig = objFilter( + warpDeployConfig, + (chain, _config): _config is any => !warpCoreChains.includes(chain), + ); - extendedConfigs = await deriveMetadataFromExisting( - multiProvider, - existingConfigs, - extendedConfigs, - ); + if (isObjEmpty(extendedConfigs)) return []; - const newDeployedContracts = await executeDeploy( - { - // TODO: use EvmERC20WarpModule when it's ready - context, - warpDeployConfig: extendedConfigs, - }, - apiKeys, - ); + extendedConfigs = await deriveMetadataFromExisting( + multiProvider, + existingConfigs, + extendedConfigs, + ); - const mergedRouters = mergeAllRouters( - multiProvider, - existingConfigs, - newDeployedContracts, - warpCoreConfigByChain, - ); + const newDeployedContracts = await executeDeploy( + { + // TODO: use EvmERC20WarpModule when it's ready + context: params.context, + warpDeployConfig: extendedConfigs, + }, + apiKeys, + ); - await enrollRemoteRouters(params, mergedRouters); + const mergedRouters = mergeAllRouters( + multiProvider, + existingConfigs, + newDeployedContracts, + warpCoreConfigByChain, + ); - const updatedWarpCoreConfig = await getWarpCoreConfig( - params, - mergedRouters, - ); - WarpCoreConfigSchema.parse(updatedWarpCoreConfig); - await writeDeploymentArtifacts(updatedWarpCoreConfig, context); - } else { - throw new Error('Unenrolling warp routes is currently not supported'); - } + const updatedWarpCoreConfig = await getWarpCoreConfig(params, mergedRouters); + WarpCoreConfigSchema.parse(updatedWarpCoreConfig); + await writeDeploymentArtifacts(updatedWarpCoreConfig, params.context); + + return enrollRemoteRouters(params, mergedRouters); +} + +async function updateExistingWarpRoute( + params: WarpApplyParams, + apiKeys: ChainMap, + warpDeployConfig: WarpRouteDeployConfig, + warpCoreConfigByChain: ChainMap, +) { + logBlue('Updating deployed Warp Routes'); + const { multiProvider, registry } = params.context; + const addresses = await registry.getAddresses(); + const contractVerifier = new ContractVerifier( + multiProvider, + apiKeys, + coreBuildArtifact, + ExplorerLicenseType.MIT, + ); + const transactions: AnnotatedEV5Transaction[] = []; + await promiseObjAll( + objMap(warpDeployConfig, async (chain, config) => { + const deployedConfig = warpCoreConfigByChain[chain]; + if (!deployedConfig) + return logGray( + `Missing artifacts for ${chain}. Probably new deployment. Skipping update...`, + ); + config.ismFactoryAddresses = addresses[ + chain + ] as ProxyFactoryFactoriesAddresses; + const evmERC20WarpModule = new EvmERC20WarpModule( + multiProvider, + { + config, + chain, + addresses: { + deployedTokenRoute: deployedConfig.addressOrDenom!, + }, + }, + contractVerifier, + ); + transactions.push(...(await evmERC20WarpModule.update(config))); + }), + ); + return transactions; } /** @@ -617,7 +633,7 @@ function mergeAllRouters( async function enrollRemoteRouters( params: WarpApplyParams, deployedContractsMap: HyperlaneContractsMap, -): Promise { +): Promise { logBlue(`Enrolling deployed routers with each other...`); const { multiProvider } = params.context; const deployedRouters: ChainMap
= objMap( @@ -625,6 +641,7 @@ async function enrollRemoteRouters( (_, contracts) => getRouter(contracts).address, ); const allChains = Object.keys(deployedRouters); + const transactions: AnnotatedEV5Transaction[] = []; await promiseObjAll( objMap(deployedContractsMap, async (chain, contracts) => { await retryAsync(async () => { @@ -660,10 +677,12 @@ async function enrollRemoteRouters( return logGreen( `Warp config on ${chain} is the same as target. No updates needed.`, ); - await submitWarpApplyTransactions(chain, params, mutatedConfigTxs); + transactions.push(...mutatedConfigTxs); }); }), ); + + return transactions; } function getRouter(contracts: HyperlaneContracts) { @@ -805,29 +824,36 @@ function transformIsmConfigForDisplay(ismConfig: IsmConfig): any[] { * Submits a set of transactions to the specified chain and outputs transaction receipts */ async function submitWarpApplyTransactions( - chain: string, params: WarpApplyParams, - transactions: AnnotatedEV5Transaction[], -) { - const submitter: TxSubmitterBuilder = - await getWarpApplySubmitter({ - chain, - context: params.context, - strategyUrl: params.strategyUrl, - }); + chainTransactions: Record, +): Promise { + const { multiProvider } = params.context; + await promiseObjAll( + objMap(chainTransactions, async (chainId, transactions) => { + const chain = multiProvider.getChainName(chainId); + const submitter: TxSubmitterBuilder = + await getWarpApplySubmitter({ + chain, + context: params.context, + strategyUrl: params.strategyUrl, + }); - const transactionReceipts = await submitter.submit(...transactions); - if (transactionReceipts) { - const receiptPath = `${params.receiptsDir}/${chain}-${ - submitter.txSubmitterType - }-${Date.now()}-receipts.json`; - writeYamlOrJson(receiptPath, transactionReceipts); - logGreen(`Transactions receipts successfully written to ${receiptPath}`); - } + const transactionReceipts = await submitter.submit(...transactions); + if (transactionReceipts) { + const receiptPath = `${params.receiptsDir}/${chain}-${ + submitter.txSubmitterType + }-${Date.now()}-receipts.json`; + writeYamlOrJson(receiptPath, transactionReceipts); + logGreen( + `Transactions receipts successfully written to ${receiptPath}`, + ); + } - return logGreen( - `✅ Warp route update success with ${submitter.txSubmitterType} on ${chain}:\n\n`, - indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 0), + logGreen( + `✅ Warp route update success with ${submitter.txSubmitterType} on ${chain}:\n\n`, + indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 0), + ); + }), ); } diff --git a/typescript/cli/src/tests/commands/helpers.ts b/typescript/cli/src/tests/commands/helpers.ts index e4f43e894..2d2be7a6e 100644 --- a/typescript/cli/src/tests/commands/helpers.ts +++ b/typescript/cli/src/tests/commands/helpers.ts @@ -43,7 +43,7 @@ export async function updateWarpOwnerConfig( warpDeployPath, ); warpDeployConfig[chain].owner = owner; - writeYamlOrJson(warpDeployPath, warpDeployConfig); + await writeYamlOrJson(warpDeployPath, warpDeployConfig); return warpDeployPath; } diff --git a/typescript/cli/src/tests/warp-apply.e2e-test.ts b/typescript/cli/src/tests/warp-apply.e2e-test.ts index 791726861..7b0c20d91 100644 --- a/typescript/cli/src/tests/warp-apply.e2e-test.ts +++ b/typescript/cli/src/tests/warp-apply.e2e-test.ts @@ -18,7 +18,11 @@ import { getChainId, updateOwner, } from './commands/helpers.js'; -import { hyperlaneWarpDeploy, readWarpConfig } from './commands/warp.js'; +import { + hyperlaneWarpApply, + hyperlaneWarpDeploy, + readWarpConfig, +} from './commands/warp.js'; const CHAIN_NAME_2 = 'anvil2'; const CHAIN_NAME_3 = 'anvil3'; @@ -86,9 +90,8 @@ describe('WarpApply e2e tests', async function () { warpConfigPath, WARP_CORE_CONFIG_PATH_2, ); - expect(stdout).to.include( - 'Warp config on anvil2 is the same as target. No updates needed.', + 'Warp config is the same as target. No updates needed.', ); }); @@ -198,4 +201,62 @@ describe('WarpApply e2e tests', async function () { ); expect(remoteRouterKeys2).to.include(chain1Id); }); + + it('should extend an existing warp route and update the owner', async () => { + const warpDeployPath = `${TEMP_PATH}/warp-route-deployment-2.yaml`; + // Burn anvil2 owner in config + const warpDeployConfig = await readWarpConfig( + CHAIN_NAME_2, + WARP_CORE_CONFIG_PATH_2, + warpDeployPath, + ); + warpDeployConfig[CHAIN_NAME_2].owner = BURN_ADDRESS; + + // Extend with new config + const randomOwner = new Wallet(ANVIL_KEY).address; + const extendedConfig: TokenRouterConfig = { + decimals: 18, + mailbox: chain2Addresses!.mailbox, + name: 'Ether', + owner: randomOwner, + symbol: 'ETH', + totalSupply: 0, + type: TokenType.native, + }; + + warpDeployConfig[CHAIN_NAME_3] = extendedConfig; + writeYamlOrJson(warpDeployPath, warpDeployConfig); + await hyperlaneWarpApply(warpDeployPath, WARP_CORE_CONFIG_PATH_2); + + const COMBINED_WARP_CORE_CONFIG_PATH = `${REGISTRY_PATH}/deployments/warp_routes/ETH/anvil2-anvil3-config.yaml`; + + const updatedWarpDeployConfig_2 = await readWarpConfig( + CHAIN_NAME_2, + COMBINED_WARP_CORE_CONFIG_PATH, + warpDeployPath, + ); + const updatedWarpDeployConfig_3 = await readWarpConfig( + CHAIN_NAME_3, + COMBINED_WARP_CORE_CONFIG_PATH, + warpDeployPath, + ); + // Check that anvil2 owner is burned + expect(updatedWarpDeployConfig_2.anvil2.owner).to.equal(BURN_ADDRESS); + + // Also, anvil3 owner is not burned + 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 remoteRouterKeys2 = Object.keys( + updatedWarpDeployConfig_2[CHAIN_NAME_2].remoteRouters!, + ); + const remoteRouterKeys3 = Object.keys( + updatedWarpDeployConfig_3[CHAIN_NAME_3].remoteRouters!, + ); + expect(remoteRouterKeys2).to.include(chain3Id); + expect(remoteRouterKeys3).to.include(chain2Id); + }); }); From 470e53bb76834ea1390edf28800bdd02a5d5a7c0 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Mon, 14 Oct 2024 11:00:06 +0100 Subject: [PATCH 131/224] feat: Add support for flow from Celestia (#4668) ### Description Add support for flow from Celestia ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4646 ### Backward compatibility Yes ### Testing Local run of Scraper Check that transaction and messages can be parsed --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../main/chains/hyperlane-cosmos/src/error.rs | 15 ++ .../hyperlane-cosmos/src/libs/account.rs | 7 +- .../hyperlane-cosmos/src/libs/address.rs | 3 +- .../src/providers/cosmos/provider.rs | 62 ++++++- .../src/providers/cosmos/provider/parse.rs | 163 ++++++++++++++++++ 5 files changed, 239 insertions(+), 11 deletions(-) create mode 100644 rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs diff --git a/rust/main/chains/hyperlane-cosmos/src/error.rs b/rust/main/chains/hyperlane-cosmos/src/error.rs index 8ceacd601..de5e2f019 100644 --- a/rust/main/chains/hyperlane-cosmos/src/error.rs +++ b/rust/main/chains/hyperlane-cosmos/src/error.rs @@ -53,9 +53,24 @@ pub enum HyperlaneCosmosError { /// Public key error #[error("{0}")] PublicKeyError(String), + /// Address error + #[error("{0}")] + AddressError(String), /// Signer info error #[error("{0}")] SignerInfoError(String), + /// Serde error + #[error("{0}")] + SerdeError(#[from] serde_json::Error), + /// Empty error + #[error("{0}")] + UnparsableEmptyField(String), + /// Parsing error + #[error("{0}")] + ParsingFailed(String), + /// Parsing attempt failed + #[error("Parsing attempt failed. (Errors: {0:?})")] + ParsingAttemptsFailed(Vec), } impl From for ChainCommunicationError { diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs index 092a1f45b..d29afd1d0 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/account.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/account.rs @@ -63,7 +63,7 @@ impl<'a> CosmosAccountId<'a> { } impl TryFrom<&CosmosAccountId<'_>> for H256 { - type Error = ChainCommunicationError; + type Error = HyperlaneCosmosError; /// Builds a H256 digest from a cosmos AccountId (Bech32 encoding) fn try_from(account_id: &CosmosAccountId) -> Result { @@ -71,7 +71,8 @@ impl TryFrom<&CosmosAccountId<'_>> for H256 { let h256_len = H256::len_bytes(); let Some(start_point) = h256_len.checked_sub(bytes.len()) else { // input is too large to fit in a H256 - return Err(Overflow.into()); + let msg = "account address is too large to fit it a H256"; + return Err(HyperlaneCosmosError::AddressError(msg.to_owned())); }; let mut empty_hash = H256::default(); let result = empty_hash.as_bytes_mut(); @@ -81,7 +82,7 @@ impl TryFrom<&CosmosAccountId<'_>> for H256 { } impl TryFrom> for H256 { - type Error = ChainCommunicationError; + type Error = HyperlaneCosmosError; /// Builds a H256 digest from a cosmos AccountId (Bech32 encoding) fn try_from(account_id: CosmosAccountId) -> Result { diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs index 4fa08ac9f..e538e1c3b 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/address.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/address.rs @@ -91,7 +91,8 @@ impl TryFrom<&CosmosAddress> for H256 { type Error = ChainCommunicationError; fn try_from(cosmos_address: &CosmosAddress) -> Result { - CosmosAccountId::new(&cosmos_address.account_id).try_into() + H256::try_from(CosmosAccountId::new(&cosmos_address.account_id)) + .map_err(Into::::into) } } diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index 6b3e52863..c3e6cb114 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -3,10 +3,12 @@ use std::str::FromStr; use async_trait::async_trait; use cosmrs::cosmwasm::MsgExecuteContract; use cosmrs::crypto::PublicKey; +use cosmrs::proto::traits::Message; use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo, SignerPublicKey}; use cosmrs::{proto, AccountId, Any, Coin, Tx}; -use itertools::Itertools; +use itertools::{any, cloned, Itertools}; use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; use tendermint::hash::Algorithm; use tendermint::Hash; use tendermint_rpc::{client::CompatMode, Client, HttpClient}; @@ -21,11 +23,14 @@ use hyperlane_core::{ }; use crate::grpc::{WasmGrpcProvider, WasmProvider}; +use crate::providers::cosmos::provider::parse::PacketData; use crate::providers::rpc::CosmosRpcClient; use crate::{ ConnectionConf, CosmosAccountId, CosmosAddress, CosmosAmount, HyperlaneCosmosError, Signer, }; +mod parse; + /// Exponent value for atto units (10^-18). const ATTO_EXPONENT: u32 = 18; @@ -197,8 +202,29 @@ impl CosmosProvider { } /// Extract contract address from transaction. - /// Assumes that there is only one `MsgExecuteContract` message in the transaction fn contract(tx: &Tx, tx_hash: &H256) -> ChainResult { + // We merge two error messages together so that both of them are reported + match Self::contract_address_from_msg_execute_contract(tx, tx_hash) { + Ok(contract) => Ok(contract), + Err(msg_execute_contract_error) => { + match Self::contract_address_from_msg_recv_packet(tx, tx_hash) { + Ok(contract) => Ok(contract), + Err(msg_recv_packet_error) => { + let errors = vec![msg_execute_contract_error, msg_recv_packet_error]; + let error = HyperlaneCosmosError::ParsingAttemptsFailed(errors); + warn!(?tx_hash, ?error); + Err(ChainCommunicationError::from_other(error))? + } + } + } + } + } + + /// Assumes that there is only one `MsgExecuteContract` message in the transaction + fn contract_address_from_msg_execute_contract( + tx: &Tx, + tx_hash: &H256, + ) -> Result { use cosmrs::proto::cosmwasm::wasm::v1::MsgExecuteContract as ProtoMsgExecuteContract; let contract_execution_messages = tx @@ -211,23 +237,45 @@ impl CosmosProvider { let contract_execution_messages_len = contract_execution_messages.len(); if contract_execution_messages_len > 1 { - let msg = "transaction contains multiple contract execution messages, we are indexing the first entry only"; - warn!(?tx_hash, ?contract_execution_messages, msg); - Err(ChainCommunicationError::CustomError(msg.to_owned()))? + let msg = "transaction contains multiple contract execution messages"; + Err(HyperlaneCosmosError::ParsingFailed(msg.to_owned()))? } let any = contract_execution_messages.first().ok_or_else(|| { let msg = "could not find contract execution message"; - warn!(?tx_hash, msg); - ChainCommunicationError::from_other_str(msg) + HyperlaneCosmosError::ParsingFailed(msg.to_owned()) })?; let proto = ProtoMsgExecuteContract::from_any(any).map_err(Into::::into)?; let msg = MsgExecuteContract::try_from(proto)?; let contract = H256::try_from(CosmosAccountId::new(&msg.contract))?; + Ok(contract) } + fn contract_address_from_msg_recv_packet( + tx: &Tx, + tx_hash: &H256, + ) -> Result { + let packet_data = tx + .body + .messages + .iter() + .filter(|a| a.type_url == "/ibc.core.channel.v1.MsgRecvPacket") + .map(PacketData::try_from) + .flat_map(|r| r.ok()) + .next() + .ok_or_else(|| { + let msg = "could not find IBC receive packets message containing receiver address"; + HyperlaneCosmosError::ParsingFailed(msg.to_owned()) + })?; + + let account_id = AccountId::from_str(&packet_data.receiver)?; + let address = H256::try_from(CosmosAccountId::new(&account_id))?; + + Ok(address) + } + /// Reports if transaction contains fees expressed in unsupported denominations /// The only denomination we support at the moment is the one we express gas minimum price /// in the configuration of a chain. If fees contain an entry in a different denomination, diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs new file mode 100644 index 000000000..aac9b7ce5 --- /dev/null +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs @@ -0,0 +1,163 @@ +use cosmrs::proto::ibc::core::channel::v1::MsgRecvPacket; +use cosmrs::proto::prost::Message; +use cosmrs::Any; +use serde::{Deserialize, Serialize}; + +use crate::HyperlaneCosmosError; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct PacketData { + pub amount: String, + pub denom: String, + pub memo: String, + pub receiver: String, + pub sender: String, +} + +impl TryFrom<&Any> for PacketData { + type Error = HyperlaneCosmosError; + + fn try_from(any: &Any) -> Result { + let vec = any.value.as_slice(); + let msg = MsgRecvPacket::decode(vec).map_err(Into::::into)?; + let packet = msg + .packet + .ok_or(HyperlaneCosmosError::UnparsableEmptyField( + "MsgRecvPacket packet is empty".to_owned(), + ))?; + let data = serde_json::from_slice::(&packet.data)?; + Ok(data) + } +} + +impl TryFrom for PacketData { + type Error = HyperlaneCosmosError; + + fn try_from(any: Any) -> Result { + Self::try_from(&any) + } +} + +#[cfg(test)] +mod tests { + use cosmrs::proto::ibc::core::channel::v1::MsgRecvPacket; + use cosmrs::proto::ibc::core::channel::v1::Packet; + use cosmrs::proto::prost::Message; + use cosmrs::Any; + + use crate::providers::cosmos::provider::parse::PacketData; + use crate::HyperlaneCosmosError; + + #[test] + fn success() { + // given + let json = r#"{"amount":"59743800","denom":"utia","memo":"{\"wasm\":{\"contract\":\"neutron1jyyjd3x0jhgswgm6nnctxvzla8ypx50tew3ayxxwkrjfxhvje6kqzvzudq\",\"msg\":{\"transfer_remote\":{\"dest_domain\":42161,\"recipient\":\"0000000000000000000000008784aca75a95696fec93184b1c7b2d3bf5838df9\",\"amount\":\"59473800\"}},\"funds\":[{\"amount\":\"59743800\",\"denom\":\"ibc/773B4D0A3CD667B2275D5A4A7A2F0909C0BA0F4059C0B9181E680DDF4965DCC7\"}]}}","receiver":"neutron1jyyjd3x0jhgswgm6nnctxvzla8ypx50tew3ayxxwkrjfxhvje6kqzvzudq","sender":"celestia19ns7dd07g5vvrueyqlkvn4dmxt957zcdzemvj6"}"#; + let any = any(json); + + // when + let data = PacketData::try_from(&any); + + // then + assert!(data.is_ok()); + } + + #[test] + fn fail_json() { + // given + let json = r#"{"amount":"27000000","denom":"utia","receiver":"neutron13uuq6vgenxan43ngscjlew8lc2z32znx9qfk0n","sender":"celestia1rh4gplea4gzvaaejew8jfvp9r0qkdmfgkf55qy"}"#; + let any = any(json); + + // when + let data = PacketData::try_from(&any); + + // then + assert!(data.is_err()); + assert!(matches!( + data.err().unwrap(), + HyperlaneCosmosError::SerdeError(_), + )); + } + + #[test] + fn fail_empty() { + // given + let any = empty(); + + // when + let data = PacketData::try_from(&any); + + // then + assert!(data.is_err()); + assert!(matches!( + data.err().unwrap(), + HyperlaneCosmosError::UnparsableEmptyField(_), + )); + } + + #[test] + fn fail_decode() { + // given + let any = wrong_encoding(); + + // when + let data = PacketData::try_from(&any); + + // then + assert!(data.is_err()); + assert!(matches!( + data.err().unwrap(), + HyperlaneCosmosError::Prost(_), + )); + } + + fn any(json: &str) -> Any { + let packet = Packet { + sequence: 0, + source_port: "".to_string(), + source_channel: "".to_string(), + destination_port: "".to_string(), + destination_channel: "".to_string(), + data: json.as_bytes().to_vec(), + timeout_height: None, + timeout_timestamp: 0, + }; + + let msg = MsgRecvPacket { + packet: Option::from(packet), + proof_commitment: vec![], + proof_height: None, + signer: "".to_string(), + }; + + encode_proto(&msg) + } + + fn empty() -> Any { + let msg = MsgRecvPacket { + packet: None, + proof_commitment: vec![], + proof_height: None, + signer: "".to_string(), + }; + + encode_proto(&msg) + } + + fn wrong_encoding() -> Any { + let buf = vec![1, 2, 3]; + Any { + type_url: "".to_string(), + value: buf, + } + } + + fn encode_proto(msg: &MsgRecvPacket) -> Any { + let mut buf = Vec::with_capacity(msg.encoded_len()); + MsgRecvPacket::encode(&msg, &mut buf).unwrap(); + + Any { + type_url: "".to_string(), + value: buf, + } + } +} From 0301055abc612590539b43a985364cd7ba5d596a Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Mon, 14 Oct 2024 14:51:07 +0100 Subject: [PATCH 132/224] feat: Upgrade scraper (#4676) ### Description Upgrade Scraper so that it can process incoming transaction for flow Celestia->Neutron->Arbitrum ### Related issues - Releases https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4646 ### Backward compatibility Yes ### Testing Local run of Scraper Check that transaction and messages can be parsed Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- typescript/infra/config/environments/mainnet3/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index b85a1152f..6dd4e1df1 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -428,7 +428,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '8001bbb-20241010-143553', + tag: '470e53b-20241014-101250', }, resources: scraperResources, }, From 5f4540ed4e239e463fbb5eefb0435be17552dad7 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:42:56 +0100 Subject: [PATCH 133/224] fix: sort out codespell (#4679) ### Description fix: sort out codespell. Try using the official setup python action ### Drive-by changes na ### Related issues na ### Backward compatibility yes? ### Testing ci Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .github/workflows/codespell.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 461ccd3d7..aacb0bac5 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -21,15 +21,13 @@ jobs: - name: Checkout the repository uses: actions/checkout@v4 - - name: pip cache - uses: buildjet/cache@v4 + - name: Setup python + uses: actions/setup-python@v5 with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: ${{ runner.os }}-pip- + python-version: '3.x' - - name: Install prerequisites - run: sudo pip install -r ./.codespell/requirements.txt + - name: Install codespell requirements + run: pip install -r ./.codespell/requirements.txt - name: Spell check run: codespell --config=./.codespell/.codespellrc From 2317eca3cd43a3b3e3ea63d46cda25077818870a Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:51:57 +0100 Subject: [PATCH 134/224] fix: add gas buffer when sending message through HyperlaneCore (#4677) ### Description estimates gas + adds gas limit buffer when sending a message through HyperlaneCore ### Drive-by changes also sets tx overrides ### Related issues > incremental merkle tree insertions have inconsistent gas usage so if there are multiple dispatch transactions in the mempool the gas estimation can become too low depending on the tx ordering bumping up the gas limit helps [more context](https://discord.com/channels/935678348330434570/1295388159407947859/1295393090181267558) ### Backward compatibility yes ### Testing manual --- .changeset/wise-camels-repair.md | 5 ++++ typescript/sdk/src/core/HyperlaneCore.ts | 30 +++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 .changeset/wise-camels-repair.md diff --git a/.changeset/wise-camels-repair.md b/.changeset/wise-camels-repair.md new file mode 100644 index 000000000..7cde52ed6 --- /dev/null +++ b/.changeset/wise-camels-repair.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Set transaction overrides and add 10% gas limit buffer when sending message through HyperlaneCore. diff --git a/typescript/sdk/src/core/HyperlaneCore.ts b/typescript/sdk/src/core/HyperlaneCore.ts index 4dc133bc8..93f232a44 100644 --- a/typescript/sdk/src/core/HyperlaneCore.ts +++ b/typescript/sdk/src/core/HyperlaneCore.ts @@ -12,6 +12,7 @@ import { Address, AddressBytes32, ProtocolType, + addBufferToGasLimit, addressToBytes32, bytes32ToAddress, isZeroishAddress, @@ -153,17 +154,31 @@ export class HyperlaneCore extends HyperlaneApp { metadata, hook, ); + + const dispatchParams = [ + destinationDomain, + recipientBytes32, + body, + metadata || '0x', + hook || ethers.constants.AddressZero, + ] as const; + + const estimateGas = await mailbox.estimateGas[ + 'dispatch(uint32,bytes32,bytes,bytes,address)' + ](...dispatchParams, { value: quote }); + const dispatchTx = await this.multiProvider.handleTx( origin, mailbox['dispatch(uint32,bytes32,bytes,bytes,address)']( - destinationDomain, - recipientBytes32, - body, - metadata || '0x', - hook || ethers.constants.AddressZero, - { value: quote }, + ...dispatchParams, + { + ...this.multiProvider.getTransactionOverrides(origin), + value: quote, + gasLimit: addBufferToGasLimit(estimateGas), + }, ), ); + return { dispatchTx, message: this.getDispatchedMessages(dispatchTx)[0], @@ -241,11 +256,14 @@ export class HyperlaneCore extends HyperlaneApp { ismMetadata: string, ): Promise { const destinationChain = this.getDestination(message); + const txOverrides = + this.multiProvider.getTransactionOverrides(destinationChain); return this.multiProvider.handleTx( destinationChain, this.getContracts(destinationChain).mailbox.process( ismMetadata, message.message, + { ...txOverrides }, ), ); } From 7d7bcc1a304c7f1c19ef4d8657db4f1bbcc5ddc5 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:09:19 +0100 Subject: [PATCH 135/224] feat: deploy to flow, metall2, polynomial (#4669) ### Description - deploy to flow, metall2, polynomial ### Drive-by changes na ### Related issues na ### Backward compatibility yes ### Testing manual ![image](https://github.com/user-attachments/assets/1d94e332-a64a-472d-878b-140865423a5a) --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/tidy-hornets-beam.md | 5 + .registryrc | 2 +- rust/main/config/mainnet_config.json | 246 +++++++++++++++-- .../config/environments/mainnet3/agent.ts | 15 +- .../mainnet3/aw-validators/hyperlane.json | 9 + .../config/environments/mainnet3/chains.ts | 8 + .../mainnet3/core/verification.json | 228 ++++++++++++++++ .../config/environments/mainnet3/funding.ts | 5 +- .../environments/mainnet3/gasPrices.json | 40 ++- .../mainnet3/ism/verification.json | 172 ++++++++++++ .../middleware/accounts/verification.json | 253 ++++++++++++++++++ .../mainnet3/supportedChainNames.ts | 3 + .../environments/mainnet3/tokenPrices.json | 133 ++++----- .../environments/mainnet3/validators.ts | 31 +++ typescript/sdk/src/consts/multisigIsm.ts | 15 ++ 15 files changed, 1056 insertions(+), 109 deletions(-) create mode 100644 .changeset/tidy-hornets-beam.md diff --git a/.changeset/tidy-hornets-beam.md b/.changeset/tidy-hornets-beam.md new file mode 100644 index 000000000..b4cff7c2f --- /dev/null +++ b/.changeset/tidy-hornets-beam.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Add deployments for mainnets: flow, metall2, polynomial diff --git a/.registryrc b/.registryrc index 770382734..f9d1c257f 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -3b9f67add3338f151154bc5db76bf4e296f018dd +3cd5d816549b1ae391e6a3c68acc07d439175888 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index 47f9c94ef..fe61ef2ff 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -4104,10 +4104,10 @@ "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", - "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", - "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainAccountIsm": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "interchainAccountRouter": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4167,10 +4167,10 @@ "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", - "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", - "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainAccountIsm": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47", + "interchainAccountRouter": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4192,7 +4192,8 @@ "from": 17051552 }, "transactionOverrides": { - "maxPriorityFeePerGas": 1000000000 + "maxPriorityFeePerGas": 1000000000, + "maxFeePerGas": 100000000000000 } }, "immutablezkevm": { @@ -4236,10 +4237,10 @@ "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", - "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", - "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainAccountIsm": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainAccountRouter": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4306,10 +4307,10 @@ "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", "fallbackRoutingHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", - "interchainAccountIsm": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", - "interchainAccountRouter": "0xC9c1A8E0d7A389ff4E3A5ab1C3F9555c50BaD325", + "interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719", + "interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64", "interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", - "interchainSecurityModule": "0x68ec44d6aB0dE138eaA159D74C5A2b473919f3df", + "interchainSecurityModule": "0x8750ac24C3bE28b406fBCD664AbabF676d3aCB29", "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", "merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", "pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", @@ -4343,7 +4344,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 0 }, "chainId": 1380012617, "deployer": { @@ -4373,10 +4374,10 @@ "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", - "interchainAccountIsm": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", - "interchainAccountRouter": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "interchainAccountIsm": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8", + "interchainAccountRouter": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0x221b3527B08aD096dDCc74B170a23c59B031DC14", + "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4436,16 +4437,17 @@ } ], "transactionOverrides": { - "gasPrice": 70000000 + "gasPrice": 70000000, + "gasLimit": 6800000 }, "aggregationHook": "0xA530b21B2c1517ceFcAAE890c7f8A167e4C0f51E", "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", - "interchainAccountIsm": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", - "interchainAccountRouter": "0xC9c1A8E0d7A389ff4E3A5ab1C3F9555c50BaD325", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", "interchainGasPaymaster": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", - "interchainSecurityModule": "0x3D409C61721f9D5558A3AdfA45A215C795533377", + "interchainSecurityModule": "0x01031eCa87184c84938016E1444150472Da35b3a", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", "pausableHook": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", @@ -4479,7 +4481,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 0 }, "chainId": 55244, "deployer": { @@ -4509,10 +4511,10 @@ "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", "fallbackRoutingHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", - "interchainAccountIsm": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", - "interchainAccountRouter": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d", + "interchainAccountIsm": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666", + "interchainAccountRouter": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de", "interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", - "interchainSecurityModule": "0x68ec44d6aB0dE138eaA159D74C5A2b473919f3df", + "interchainSecurityModule": "0x8750ac24C3bE28b406fBCD664AbabF676d3aCB29", "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", "merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", "pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", @@ -4530,6 +4532,200 @@ "testRecipient": "0x71388C9E25BE7b229B5d17Df7D4DB3F7DA7C962d", "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x989B7307d266151BE763935C856493D968b2affF" + }, + "metall2": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.metall2.com/api", + "family": "blockscout", + "name": "Metal L2 Explorer", + "url": "https://explorer.metall2.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 0 + }, + "chainId": 1750, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Metal L2", + "domainId": 1750, + "gasCurrencyCoinGeckoId": "ethereum", + "isTestnet": false, + "name": "metall2", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.metall2.com" + } + ], + "aggregationHook": "0x5C6a12730a0dF828289f26D4abFdCC80FC74896C", + "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", + "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "fallbackRoutingHook": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "interchainAccountIsm": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", + "interchainAccountRouter": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "interchainGasPaymaster": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "interchainSecurityModule": "0xE89fF24e1979F6AbD6b71b733cc62d1289d193c4", + "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "merkleTreeHook": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918", + "pausableHook": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "pausableIsm": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "protocolFee": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticAggregationIsm": "0x21BAaDf623448DE682235998E1332eC481011b89", + "staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "storageGasOracle": "0x749848D7b783A328638C3ea74AcFcfb73c977CbE", + "testRecipient": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "index": { + "from": 8547390 + } + }, + "polynomial": { + "blockExplorers": [ + { + "apiUrl": "https://polynomialscan.io/api", + "family": "routescan", + "name": "Polynomial Explorer", + "url": "https://polynomialscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 0 + }, + "chainId": 8008, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Polynomial", + "domainId": 8008, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "polynomial", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.polynomial.fi" + } + ], + "aggregationHook": "0x38ca4cfB82E2799c0b9CE94113679825F5fb2cf7", + "domainRoutingIsm": "0xF1B7ba7382D73D228cdcfB26A28B6a61e14Fa432", + "domainRoutingIsmFactory": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "fallbackRoutingHook": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "interchainSecurityModule": "0xFF16628ff85F145Ce6d1712014D46DcFB52da75A", + "mailbox": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9", + "merkleTreeHook": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", + "pausableHook": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "pausableIsm": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "protocolFee": "0xfdefdDc8E153d5E0463d7E193F79A3714be16021", + "proxyAdmin": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", + "staticAggregationHookFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationIsm": "0xEA00eE6AFDEeC7453b6AFCadEC34d0F29dCdB16b", + "staticAggregationIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMerkleRootMultisigIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticMerkleRootWeightedMultisigIsmFactory": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "staticMessageIdMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdWeightedMultisigIsmFactory": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "storageGasOracle": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "testRecipient": "0xf7D882A816D4845BB221Ceb03CE531d1e7645F60", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c", + "index": { + "from": 5310074 + } + }, + "flow": { + "blockExplorers": [ + { + "apiUrl": "https://evm.flowscan.io/api", + "family": "blockscout", + "name": "EVM on Flow Explorer", + "url": "https://evm.flowscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 1 + }, + "chainId": 747, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "EVM on Flow", + "domainId": 747, + "gasCurrencyCoinGeckoId": "flow", + "isTestnet": false, + "name": "flow", + "nativeToken": { + "decimals": 18, + "name": "Flow", + "symbol": "FLOW" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet.evm.nodes.onflow.org" + } + ], + "transactionOverrides": { + "gasPrice": 100000000 + }, + "aggregationHook": "0x24A681D6B1B7Fb6208938be982Efd512E842867a", + "domainRoutingIsm": "0x85804e2ae21273F6539CFa1A688FE6154004D4dF", + "domainRoutingIsmFactory": "0x8C3e1794018a589c9E9226b8543105fCb6cC88C4", + "fallbackRoutingHook": "0x549F241472FccdA169E3202048aE2241231A7772", + "interchainAccountIsm": "0xb5668713E9BA8bC96f97D691663E70b54CE90b0A", + "interchainAccountRouter": "0xc5068BB6803ADbe5600DE5189fe27A4dAcE31170", + "interchainGasPaymaster": "0xA1Df6B70044029a2D1eDDC50EfDE2813e478140a", + "interchainSecurityModule": "0x729E790E70902429873c23BaA73eE39aCEEfc461", + "mailbox": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "merkleTreeHook": "0x25d668D37f20E6f396cB5DF1DFf5A3f2F568e707", + "pausableHook": "0xC9ab9Dc82F05eA118F266611f4c474529d43b599", + "pausableIsm": "0x14C586824E6d04F0761BF9fCa6983F7282002299", + "protocolFee": "0x3AdCBc94ab8C48EC52D06dc65Bb787fD1981E3d5", + "proxyAdmin": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "staticAggregationHookFactory": "0xfBc08389224d23b79cb21cDc16c5d42F0ad0F57f", + "staticAggregationIsm": "0x729E790E70902429873c23BaA73eE39aCEEfc461", + "staticAggregationIsmFactory": "0x18B0688990720103dB63559a3563f7E8d0f63EDb", + "staticMerkleRootMultisigIsmFactory": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a", + "staticMerkleRootWeightedMultisigIsmFactory": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "staticMessageIdMultisigIsmFactory": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "staticMessageIdWeightedMultisigIsmFactory": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", + "storageGasOracle": "0x59973ae98D340cA0577ed92502402E82E987Ba2E", + "testRecipient": "0xC1eC2f9BB21148a58ea571770c5F1FAa01cDFF11", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xE2B36A37bD98ba81658dC5454F2dB2F98438d140", + "index": { + "from": 4240431 + } } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 6dd4e1df1..40464a562 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -77,6 +77,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< ethereum: true, everclear: true, flare: true, + flow: true, fraxtal: true, fusemainnet: true, gnosis: true, @@ -91,6 +92,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< mantapacific: true, mantle: true, merlin: true, + metall2: true, metis: true, mint: true, mode: true, @@ -102,6 +104,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< osmosis: true, polygon: true, polygonzkevm: true, + polynomial: true, proofofplay: true, rari: true, real: true, @@ -147,6 +150,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< ethereum: true, everclear: true, flare: true, + flow: true, fraxtal: true, fusemainnet: true, gnosis: true, @@ -161,6 +165,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< mantapacific: true, mantle: true, merlin: true, + metall2: true, metis: true, mint: true, mode: true, @@ -173,6 +178,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< osmosis: true, polygon: true, polygonzkevm: true, + polynomial: true, proofofplay: true, rari: true, real: true, @@ -219,6 +225,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< ethereum: true, everclear: true, flare: true, + flow: true, fraxtal: true, fusemainnet: true, gnosis: true, @@ -233,6 +240,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< mantapacific: true, mantle: true, merlin: true, + metall2: true, metis: true, mint: true, mode: true, @@ -244,6 +252,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< osmosis: true, polygon: true, polygonzkevm: true, + polynomial: true, proofofplay: true, rari: true, real: true, @@ -409,7 +418,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '70bb863-20241009-193832', + tag: '18c29c8-20241014-133718', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -418,7 +427,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: '70bb863-20241009-193832', + tag: '18c29c8-20241014-133718', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -428,7 +437,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '470e53b-20241014-101250', + tag: '18c29c8-20241014-133718', }, resources: scraperResources, }, diff --git a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json index 5f6881882..a63b630da 100644 --- a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json @@ -92,6 +92,9 @@ "flare": { "validators": ["0xb65e52be342dba3ab2c088ceeb4290c744809134"] }, + "flow": { + "validators": ["0x3aee1090318e9c54d1d23194dcd0f2bee00ddc97"] + }, "fraxtal": { "validators": ["0x4bce180dac6da60d0f3a2bdf036ffe9004f944c1"] }, @@ -146,6 +149,9 @@ "merlin": { "validators": ["0xc1d6600cb9326ed2198cc8c4ba8d6668e8671247"] }, + "metall2": { + "validators": ["0x1b000e1e1f0a032ed382c6d69a2d58f6fe773c09"] + }, "metis": { "validators": ["0xc4a3d25107060e800a43842964546db508092260"] }, @@ -199,6 +205,9 @@ "0x6a1da2e0b7ae26aaece1377c0a4dbe25b85fa3ca" ] }, + "polynomial": { + "validators": ["0xa63ad0891e921ad5947d57e05831fabb9816eca7"] + }, "proofofplay": { "validators": ["0xcda40baa71970a06e5f55e306474de5ca4e21c3b"] }, diff --git a/typescript/infra/config/environments/mainnet3/chains.ts b/typescript/infra/config/environments/mainnet3/chains.ts index b9a8976f7..206114ae3 100644 --- a/typescript/infra/config/environments/mainnet3/chains.ts +++ b/typescript/infra/config/environments/mainnet3/chains.ts @@ -68,8 +68,16 @@ export const chainMetadataOverrides: ChainMap> = { rootstock: { transactionOverrides: { gasPrice: 7 * 10 ** 7, // 0.07 gwei + // gasLimit: 6800000, // set when deploying contracts }, }, + // set when deploying contracts + // chiliz: { + // transactionOverrides: { + // maxFeePerGas: 100000 * 10 ** 9, // 100,000 gwei + // maxPriorityFeePerGas: 1 * 10 ** 9, // 1 gwei + // }, + // }, }; export const getRegistry = async (useSecrets = true): Promise => diff --git a/typescript/infra/config/environments/mainnet3/core/verification.json b/typescript/infra/config/environments/mainnet3/core/verification.json index 0336137d8..371e68403 100644 --- a/typescript/infra/config/environments/mainnet3/core/verification.json +++ b/typescript/infra/config/environments/mainnet3/core/verification.json @@ -4167,5 +4167,233 @@ "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", "isProxy": false } + ], + "metall2": [ + { + "name": "ProxyAdmin", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000006d6", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D" + }, + { + "name": "PausableIsm", + "address": "0x089DdA086dCbfA0C2cCa69B45F2eB6DE7Fd71F38", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000004757bdd68bba8a6d901cec82e61e184ff2986918", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x749848D7b783A328638C3ea74AcFcfb73c977CbE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "constructorArguments": "000000000000000000000000cd849e612aaa138f03698c3edb42a34117bff6310000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631" + }, + { + "name": "ProtocolFee", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + } + ], + "polynomial": [ + { + "name": "ProxyAdmin", + "address": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000001f48", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9", + "constructorArguments": "0000000000000000000000002f9db5616fa3fad1ab06cb2c906830ba63d135e30000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b3900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3" + }, + { + "name": "PausableIsm", + "address": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", + "constructorArguments": "00000000000000000000000002d16bc51af6bfd153d67ca61754cf912e82c4d9", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", + "constructorArguments": "00000000000000000000000002d16bc51af6bfd153d67ca61754cf912e82c4d9000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000148cf67b8a242c1360bb2c93fce203ec4d4f9b56", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x71388C9E25BE7b229B5d17Df7D4DB3F7DA7C962d", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", + "constructorArguments": "00000000000000000000000071388c9e25be7b229b5d17df7d4db3f7da7c962d0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b3900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x71388C9E25BE7b229B5d17Df7D4DB3F7DA7C962d" + }, + { + "name": "ProtocolFee", + "address": "0xfdefdDc8E153d5E0463d7E193F79A3714be16021", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c", + "constructorArguments": "00000000000000000000000002d16bc51af6bfd153d67ca61754cf912e82c4d9", + "isProxy": false + } + ], + "flow": [ + { + "name": "ProxyAdmin", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000002eb", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "constructorArguments": "000000000000000000000000cda455dfd9c938451bfafc6ff0d497c8c0469c9600000000000000000000000060b8d195f1b2ecac26d54b95c69e6399cfd64b5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96" + }, + { + "name": "PausableIsm", + "address": "0x14C586824E6d04F0761BF9fCa6983F7282002299", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x25d668D37f20E6f396cB5DF1DFf5A3f2F568e707", + "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x549F241472FccdA169E3202048aE2241231A7772", + "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000025d668d37f20e6f396cb5df1dff5a3f2f568e707", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xC9ab9Dc82F05eA118F266611f4c474529d43b599", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x59973ae98D340cA0577ed92502402E82E987Ba2E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xf9609bB22847e0DB5F6fB8f95b84D25A19b46ac5", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xA1Df6B70044029a2D1eDDC50EfDE2813e478140a", + "constructorArguments": "000000000000000000000000f9609bb22847e0db5f6fb8f95b84d25a19b46ac500000000000000000000000060b8d195f1b2ecac26d54b95c69e6399cfd64b5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xf9609bB22847e0DB5F6fB8f95b84D25A19b46ac5" + }, + { + "name": "ProtocolFee", + "address": "0x3AdCBc94ab8C48EC52D06dc65Bb787fD1981E3d5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xE2B36A37bD98ba81658dC5454F2dB2F98438d140", + "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index c3dda72d2..2dcd8d134 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '422876d-20241003-134157', + tag: '18c29c8-20241014-133714', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron @@ -48,6 +48,7 @@ export const keyFunderConfig: KeyFunderConfig< ethereum: '0.5', everclear: '0.05', flare: '500', + flow: '5', fraxtal: '0.2', fusemainnet: '20', gnosis: '5', @@ -61,6 +62,7 @@ export const keyFunderConfig: KeyFunderConfig< mantapacific: '0.2', mantle: '20', merlin: '0.002', + metall2: '0.05', metis: '3', mint: '0.05', mode: '0.2', @@ -70,6 +72,7 @@ export const keyFunderConfig: KeyFunderConfig< optimism: '0.5', polygon: '20', polygonzkevm: '0.5', + polynomial: '0.05', proofofplay: '0.05', rari: '0.05', real: '0.1', diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 93651372e..81e8ae1ef 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -16,7 +16,7 @@ "decimals": 9 }, "astarzkevm": { - "amount": "0.0357", + "amount": "0.399", "decimals": 9 }, "avalanche": { @@ -24,7 +24,7 @@ "decimals": 9 }, "base": { - "amount": "0.003185677", + "amount": "0.008669818", "decimals": 9 }, "bitlayer": { @@ -32,7 +32,7 @@ "decimals": 9 }, "blast": { - "amount": "0.003481616", + "amount": "0.004707204", "decimals": 9 }, "bob": { @@ -52,7 +52,7 @@ "decimals": 9 }, "chiliz": { - "amount": "2600.0", + "amount": "5000.0", "decimals": 9 }, "coredao": { @@ -80,7 +80,7 @@ "decimals": 9 }, "ethereum": { - "amount": "12.537447318", + "amount": "21.610477208", "decimals": 9 }, "everclear": { @@ -88,7 +88,11 @@ "decimals": 9 }, "flare": { - "amount": "25.0", + "amount": "29.55878872", + "decimals": 9 + }, + "flow": { + "amount": "0.0000001", "decimals": 9 }, "fraxtal": { @@ -120,7 +124,7 @@ "decimals": 9 }, "linea": { - "amount": "0.148525014", + "amount": "0.240000007", "decimals": 9 }, "lisk": { @@ -147,6 +151,10 @@ "amount": "0.095", "decimals": 9 }, + "metall2": { + "amount": "0.001000252", + "decimals": 9 + }, "metis": { "amount": "1.247735823", "decimals": 9 @@ -176,7 +184,7 @@ "decimals": 9 }, "optimism": { - "amount": "0.051272957", + "amount": "0.02163419", "decimals": 9 }, "osmosis": { @@ -184,11 +192,15 @@ "decimals": 1 }, "polygon": { - "amount": "30.004451589", + "amount": "61.134765243", "decimals": 9 }, "polygonzkevm": { - "amount": "0.183", + "amount": "0.726", + "decimals": 9 + }, + "polynomial": { + "amount": "0.001000252", "decimals": 9 }, "proofofplay": { @@ -216,7 +228,7 @@ "decimals": 9 }, "scroll": { - "amount": "0.042025013", + "amount": "0.048755492", "decimals": 9 }, "sei": { @@ -224,7 +236,7 @@ "decimals": 9 }, "shibarium": { - "amount": "8.558763474", + "amount": "28.138673121", "decimals": 9 }, "solanamainnet": { @@ -256,7 +268,7 @@ "decimals": 9 }, "xlayer": { - "amount": "7.52", + "amount": "14.54921875", "decimals": 9 }, "zetachain": { @@ -268,7 +280,7 @@ "decimals": 9 }, "zoramainnet": { - "amount": "0.001000259", + "amount": "0.001000274", "decimals": 9 } } diff --git a/typescript/infra/config/environments/mainnet3/ism/verification.json b/typescript/infra/config/environments/mainnet3/ism/verification.json index c789ad542..965505539 100644 --- a/typescript/infra/config/environments/mainnet3/ism/verification.json +++ b/typescript/infra/config/environments/mainnet3/ism/verification.json @@ -5626,5 +5626,177 @@ "constructorArguments": "", "isProxy": true } + ], + "polynomial": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0xDFF18Bf286c9cDd0fC653a28616460Cf7443F8EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x3a49EcAC1031612D66fa20D6F40f214aCeAc2B4B", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xfb288565DBa8489e745Fb814584d06331809d16F", + "constructorArguments": "", + "isProxy": true + } + ], + "metall2": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json index 63e698e48..62bda474a 100644 --- a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json @@ -1219,6 +1219,25 @@ "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", "isProxy": true, "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + }, + { + "name": "InterchainAccountIsm", + "address": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563", + "constructorArguments": "000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed" } ], "rari": [ @@ -1240,6 +1259,25 @@ "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", "isProxy": true, "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + }, + { + "name": "InterchainAccountIsm", + "address": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xCDeb368Db32ecCefaf7018e152DA9120565cb572", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE", + "constructorArguments": "000000000000000000000000cdeb368db32eccefaf7018e152da9120565cb5720000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099fefc1119e86ee0153eb887cf8e8ab2d92a16e8000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xCDeb368Db32ecCefaf7018e152DA9120565cb572" } ], "superposition": [ @@ -1261,6 +1299,25 @@ "constructorArguments": "0000000000000000000000006fb36672365c7c797028c400a61c58c0ecc53cd2000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f4000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", "isProxy": true, "expectedimplementation": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2" + }, + { + "name": "InterchainAccountIsm", + "address": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de", + "constructorArguments": "000000000000000000000000bb0ae51bca526cf313b6a95bfab020794af6c394000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009eb56085ddbda60adf7d2b533afed90e38fc9666000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394" } ], "chiliz": [ @@ -1282,6 +1339,25 @@ "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", "isProxy": true, "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + }, + { + "name": "InterchainAccountIsm", + "address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394", + "constructorArguments": "0000000000000000000000000d3bd9f1bcda82bd1682b2c895a907d7aae458490000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009eaac366bfd70430cfee6e70265fefff1cfc9e47000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849" } ], "immutablezkevm": [ @@ -1303,6 +1379,25 @@ "constructorArguments": "000000000000000000000000168dff0ad2b180f3801883fe5ae56d7e7d91d5f40000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e969ba938e6a993eecd6f65b0dd8712b07dfe59000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", "isProxy": true, "expectedimplementation": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4" + }, + { + "name": "InterchainAccountIsm", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666", + "constructorArguments": "0000000000000000000000009eaac366bfd70430cfee6e70265fefff1cfc9e470000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ee8c0e1eebffcc451a013336386ea53e42a44451000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47" } ], "lumia": [ @@ -1324,6 +1419,25 @@ "constructorArguments": "000000000000000000000000504236da6344e5e144def5653c2b1d0ffd18cb7d000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d569fb1753167312ec5b78526743f2bea027e5d8000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", "isProxy": true, "expectedimplementation": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d" + }, + { + "name": "InterchainAccountIsm", + "address": "0x25EAC2007b0D40E3f0AF112FD346412321038719", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64", + "constructorArguments": "0000000000000000000000000f9d4704e1fb25e416042524e594f1ceac6ff597000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025eac2007b0d40e3f0af112fd346412321038719000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597" } ], "rootstock": [ @@ -1345,6 +1459,145 @@ "constructorArguments": "000000000000000000000000504236da6344e5e144def5653c2b1d0ffd18cb7d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d569fb1753167312ec5b78526743f2bea027e5d8000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", "isProxy": true, "expectedimplementation": "0x504236Da6344e5E144def5653C2b1d0fFd18cB7d" + }, + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e10000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "polynomial": [ + { + "name": "InterchainAccountIsm", + "address": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319", + "constructorArguments": "00000000000000000000000002d16bc51af6bfd153d67ca61754cf912e82c4d9", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x376aD181E8cd45eAd5403F78d5A871D08c3c4D77", + "constructorArguments": "00000000000000000000000002d16bc51af6bfd153d67ca61754cf912e82c4d9", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE", + "constructorArguments": "000000000000000000000000376ad181e8cd45ead5403f78d5a871d08c3c4d770000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b3900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c23baf5eb5848d19701bbe7f139645e6bd58a319000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x376aD181E8cd45eAd5403F78d5A871D08c3c4D77" + }, + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "00000000000000000000000002d16bc51af6bfd153d67ca61754cf912e82c4d9", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "00000000000000000000000002d16bc51af6bfd153d67ca61754cf912e82c4d9", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e10000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b3900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "metall2": [ + { + "name": "InterchainAccountIsm", + "address": "0xC9c1A8E0d7A389ff4E3A5ab1C3F9555c50BaD325", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x5c12ADC734699C07b095fe30B8312F1A7bbaA788", + "constructorArguments": "0000000000000000000000006f77d5ef273c38cc19d1d02352785f52565a1a6c0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9c1a8e0d7a389ff4e3a5ab1c3f9555c50bad325000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c" + }, + { + "name": "InterchainAccountIsm", + "address": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "constructorArguments": "00000000000000000000000060b8d195f1b2ecac26d54b95c69e6399cfd64b530000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061374178e45f65ff9d6252d017cd580fc60b7654000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53" + } + ], + "flow": [ + { + "name": "InterchainAccountIsm", + "address": "0x587463AF636f527783c584F4DdbF8188e09EC213", + "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xDd2059c375C81638DaB52AF4145d2671C446c5e9", + "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x6F9eC4f83ef69b923Fa1Dc00189e591728DF0ac0", + "constructorArguments": "000000000000000000000000dd2059c375c81638dab52af4145d2671c446c5e900000000000000000000000060b8d195f1b2ecac26d54b95c69e6399cfd64b5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000587463af636f527783c584f4ddbf8188e09ec213000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xDd2059c375C81638DaB52AF4145d2671C446c5e9" + }, + { + "name": "InterchainAccountIsm", + "address": "0xb5668713E9BA8bC96f97D691663E70b54CE90b0A", + "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x3E12271EbD523d0886D0D51A4FF8D8e046CF2E1D", + "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xc5068BB6803ADbe5600DE5189fe27A4dAcE31170", + "constructorArguments": "0000000000000000000000003e12271ebd523d0886d0d51a4ff8d8e046cf2e1d00000000000000000000000060b8d195f1b2ecac26d54b95c69e6399cfd64b5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5668713e9ba8bc96f97d691663e70b54ce90b0a000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3E12271EbD523d0886D0D51A4FF8D8e046CF2E1D" } ] } diff --git a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts index 71e08134b..c5eabc80c 100644 --- a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts +++ b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts @@ -24,6 +24,7 @@ export const mainnet3SupportedChainNames = [ 'ethereum', 'everclear', 'flare', + 'flow', 'fraxtal', 'fusemainnet', 'gnosis', @@ -38,6 +39,7 @@ export const mainnet3SupportedChainNames = [ 'mantapacific', 'mantle', 'merlin', + 'metall2', 'metis', 'mint', 'mode', @@ -49,6 +51,7 @@ export const mainnet3SupportedChainNames = [ 'osmosis', 'polygon', 'polygonzkevm', + 'polynomial', 'proofofplay', 'rari', 'real', diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index ec0d19a46..5cbf8f157 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -1,70 +1,73 @@ { - "ancient8": "2311.16", - "alephzeroevm": "0.388993", - "arbitrum": "2311.16", - "astar": "0.057834", - "astarzkevm": "2311.16", - "avalanche": "24.01", - "base": "2311.16", - "bitlayer": "60074", - "blast": "2311.16", - "bob": "2311.16", - "bsc": "535.48", - "celo": "0.62334", - "cheesechain": "0.00302691", - "chiliz": "0.057695", - "coredao": "0.842108", - "cyber": "2311.16", - "degenchain": "0.00679235", - "dogechain": "0.101709", - "eclipsemainnet": "2311.16", - "endurance": "1.91", - "ethereum": "2311.16", - "everclear": "2311.16", - "flare": "0.01584458", - "fraxtal": "2308.24", - "fusemainnet": "0.02806214", - "gnosis": "1.003", + "ancient8": "2437.96", + "alephzeroevm": "0.36741", + "arbitrum": "2437.96", + "astar": "0.059165", + "astarzkevm": "2437.96", + "avalanche": "26.77", + "base": "2437.96", + "bitlayer": "62244", + "blast": "2437.96", + "bob": "2437.96", + "bsc": "572.12", + "celo": "0.764821", + "cheesechain": "0.00448064", + "chiliz": "0.069844", + "coredao": "0.912209", + "cyber": "2437.96", + "degenchain": "0.00934571", + "dogechain": "0.110085", + "eclipsemainnet": "2437.96", + "endurance": "2.11", + "ethereum": "2437.96", + "everclear": "2437.96", + "flare": "0.01456139", + "flow": "0.533589", + "fraxtal": "2434.37", + "fusemainnet": "0.02952521", + "gnosis": "1.009", "immutablezkevm": "1.48", - "inevm": "18.76", - "injective": "18.76", - "kroma": "2311.16", - "linea": "2311.16", - "lisk": "2311.16", - "lukso": "1.53", - "lumia": "1.074", - "mantapacific": "2311.16", - "mantle": "0.558701", - "merlin": "59977", - "metis": "32.07", - "mint": "2311.16", - "mode": "2311.16", - "molten": "0.754836", - "moonbeam": "0.155475", - "neutron": "0.364817", - "oortmainnet": "0.122189", - "optimism": "2311.16", - "osmosis": "0.513827", - "polygon": "0.366532", - "polygonzkevm": "2311.16", - "proofofplay": "2311.16", - "rari": "2311.16", + "inevm": "20.24", + "injective": "20.24", + "kroma": "2437.96", + "linea": "2437.96", + "lisk": "2437.96", + "lukso": "1.51", + "lumia": "0.954153", + "mantapacific": "2437.96", + "mantle": "0.59813", + "merlin": "62293", + "metall2": "2437.96", + "metis": "34.53", + "mint": "2437.96", + "mode": "2437.96", + "molten": "0.632429", + "moonbeam": "0.163919", + "neutron": "0.390086", + "oortmainnet": "0.11645", + "optimism": "2437.96", + "osmosis": "0.521323", + "polygon": "0.371959", + "polygonzkevm": "2437.96", + "polynomial": "2437.96", + "proofofplay": "2437.96", + "rari": "2437.96", "real": "1", - "redstone": "2311.16", - "rootstock": "60206", - "sanko": "41.68", - "scroll": "2311.16", - "sei": "0.387949", - "shibarium": "0.398162", - "solanamainnet": "134.05", - "superposition": "2311.16", - "taiko": "2311.16", + "redstone": "2437.96", + "rootstock": "61812", + "sanko": "41.59", + "scroll": "2437.96", + "sei": "0.444401", + "shibarium": "0.404651", + "solanamainnet": "144.84", + "superposition": "2437.96", + "taiko": "2437.96", "tangle": "1", - "viction": "0.352221", - "worldchain": "2311.16", - "xai": "0.176832", - "xlayer": "39.69", - "zetachain": "0.53849", - "zircuit": "2311.16", - "zoramainnet": "2311.16" + "viction": "0.359062", + "worldchain": "2437.96", + "xai": "0.215315", + "xlayer": "42.29", + "zetachain": "0.581304", + "zircuit": "2437.96", + "zoramainnet": "2437.96" } diff --git a/typescript/infra/config/environments/mainnet3/validators.ts b/typescript/infra/config/environments/mainnet3/validators.ts index 0e0fd209d..0c0904744 100644 --- a/typescript/infra/config/environments/mainnet3/validators.ts +++ b/typescript/infra/config/environments/mainnet3/validators.ts @@ -967,5 +967,36 @@ export const validatorChainConfig = ( 'superposition', ), }, + + metall2: { + interval: 5, + reorgPeriod: getReorgPeriod('metall2'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x1b000e1e1f0a032ed382c6d69a2d58f6fe773c09'], + }, + 'metall2', + ), + }, + polynomial: { + interval: 5, + reorgPeriod: getReorgPeriod('polynomial'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xa63ad0891e921ad5947d57e05831fabb9816eca7'], + }, + 'polynomial', + ), + }, + flow: { + interval: 5, + reorgPeriod: getReorgPeriod('flow'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x3aee1090318e9c54d1d23194dcd0f2bee00ddc97'], + }, + 'flow', + ), + }, }; }; diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index 5258e68c0..0a8806bde 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -285,6 +285,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + flow: { + threshold: 1, + validators: ['0x3aee1090318e9c54d1d23194dcd0f2bee00ddc97'], + }, + formtestnet: { threshold: 1, validators: ['0x72ad7fddf16d17ff902d788441151982fa31a7bc'], @@ -432,6 +437,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + metall2: { + threshold: 1, + validators: ['0x1b000e1e1f0a032ed382c6d69a2d58f6fe773c09'], + }, + metis: { threshold: 2, validators: [ @@ -556,6 +566,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + polynomial: { + threshold: 1, + validators: ['0xa63ad0891e921ad5947d57e05831fabb9816eca7'], + }, + proofofplay: { threshold: 2, validators: [ From f1712deb7f5acbbcfb669cbc205d29a2efcda932 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:16:15 +0100 Subject: [PATCH 136/224] fix: update objMerge implementation (#4678) ### Description Updating the `objMerge` implementation A bug in the original implementation meant that the `update-agent-config` script did _not_ overwrite the `blocks.reorgPeriod` if there was a change, this new version does. ### Drive-by changes - gracefully handle missing startBlock data when generating agent config - fix objMerge calls that had the wrong order ### Related issues definitely want to fix this bug before attempting to update our agent configs with changes in https://github.com/hyperlane-xyz/hyperlane-registry/pull/276 ### Backward compatibility should be, yes ### Testing ci, manual testing when generating agent config files --- .changeset/dirty-clocks-repeat.md | 5 +++ typescript/cli/src/config/agent.ts | 3 +- .../scripts/agents/update-agent-config.ts | 2 +- typescript/sdk/src/metadata/agentConfig.ts | 10 +++-- typescript/utils/src/objects.test.ts | 7 ++++ typescript/utils/src/objects.ts | 42 +++++++++++-------- 6 files changed, 46 insertions(+), 23 deletions(-) create mode 100644 .changeset/dirty-clocks-repeat.md diff --git a/.changeset/dirty-clocks-repeat.md b/.changeset/dirty-clocks-repeat.md new file mode 100644 index 000000000..d9159825a --- /dev/null +++ b/.changeset/dirty-clocks-repeat.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/utils': patch +--- + +Fix objMerge implementation diff --git a/typescript/cli/src/config/agent.ts b/typescript/cli/src/config/agent.ts index dff8f2255..05fa16559 100644 --- a/typescript/cli/src/config/agent.ts +++ b/typescript/cli/src/config/agent.ts @@ -87,7 +87,7 @@ async function getStartBlocks( chainAddresses: ChainMap, core: HyperlaneCore, chainMetadata: any, -) { +): Promise> { return promiseObjAll( objMap(chainAddresses, async (chain, _) => { const indexFrom = chainMetadata[chain].index?.from; @@ -103,6 +103,7 @@ async function getStartBlocks( errorRed( `❌ Failed to get deployed block to set an index for ${chain}, this is potentially an issue with rpc provider or a misconfiguration`, ); + return undefined; } }), ); diff --git a/typescript/infra/scripts/agents/update-agent-config.ts b/typescript/infra/scripts/agents/update-agent-config.ts index 4584348cf..30d64a9d9 100644 --- a/typescript/infra/scripts/agents/update-agent-config.ts +++ b/typescript/infra/scripts/agents/update-agent-config.ts @@ -101,7 +101,7 @@ export async function writeAgentConfig( 'Error:', err, ); - return 0; + return undefined; } }, ), diff --git a/typescript/sdk/src/metadata/agentConfig.ts b/typescript/sdk/src/metadata/agentConfig.ts index f8c162f86..cb570e29e 100644 --- a/typescript/sdk/src/metadata/agentConfig.ts +++ b/typescript/sdk/src/metadata/agentConfig.ts @@ -418,7 +418,7 @@ export function buildAgentConfig( chains: ChainName[], multiProvider: MultiProvider, addresses: ChainMap, - startBlocks: ChainMap, + startBlocks: ChainMap, additionalConfig?: ChainMap, ): AgentConfig { const chainConfigs: ChainMap = {}; @@ -438,9 +438,11 @@ export function buildAgentConfig( ...metadata, ...addresses[chain], ...(additionalConfig ? additionalConfig[chain] : {}), - index: { - from: startBlocks[chain], - }, + ...(startBlocks[chain] !== undefined && { + index: { + from: startBlocks[chain], + }, + }), }; chainConfigs[chain] = chainConfig; } diff --git a/typescript/utils/src/objects.test.ts b/typescript/utils/src/objects.test.ts index e454a2b17..b6fd1d012 100644 --- a/typescript/utils/src/objects.test.ts +++ b/typescript/utils/src/objects.test.ts @@ -35,6 +35,13 @@ describe('Object utilities', () => { expect(merged).to.eql({ a: 2, b: { c: ['arr2'] } }); }); + it('objMerge overwrites nested values', () => { + const obj1 = { a: { b: 10 }, c: 'value' }; + const obj2 = { a: { b: 20 } }; + const merged = objMerge(obj1, obj2); + expect(merged).to.eql({ a: { b: 20 }, c: 'value' }); + }); + it('objOmit', () => { const obj1 = { a: 1, b: { c: ['arr1'], d: 'string' } }; const obj2 = { a: true, b: { c: true } }; diff --git a/typescript/utils/src/objects.ts b/typescript/utils/src/objects.ts index b97d4e662..680c5d579 100644 --- a/typescript/utils/src/objects.ts +++ b/typescript/utils/src/objects.ts @@ -99,8 +99,11 @@ export function pick(obj: Record, keys: K[]) { } /** - * Returns a new object that recursively merges b into a - * Where there are conflicts, b takes priority over a + * Returns a new object that recursively merges B into A + * Where there are conflicts, B takes priority over A + * If B has a value for a key that A does not have, B's value is used + * If B has a value for a key that A has, and both are objects, the merge recurses into those objects + * If B has a value for a key that A has, and both are arrays, the merge concatenates them with B's values taking priority * @param a - The first object * @param b - The second object * @param max_depth - The maximum depth to recurse @@ -112,29 +115,34 @@ export function objMerge( max_depth = 10, mergeArrays = false, ): T { + // If we've reached the max depth, throw an error if (max_depth === 0) { throw new Error('objMerge tried to go too deep'); } + // If either A or B is not an object, return the other value if (!isObject(a) || !isObject(b)) { - return (b ? b : a) as T; + return (b ?? a) as T; } - const ret: Record = {}; - const aKeys = new Set(Object.keys(a)); - const bKeys = new Set(Object.keys(b)); - const allKeys = new Set([...aKeys, ...bKeys]); - for (const key of allKeys.values()) { - if (aKeys.has(key) && bKeys.has(key)) { - if (mergeArrays && Array.isArray(a[key]) && Array.isArray(b[key])) { - ret[key] = [...b[key], ...a[key]]; - } else { - ret[key] = objMerge(a[key], b[key], max_depth - 1, mergeArrays); - } - } else if (aKeys.has(key)) { - ret[key] = a[key]; - } else { + // Initialize returned object with values from A + const ret: Record = { ...a }; + // Iterate over keys in B + for (const key in b) { + // If both A and B have the same key, recursively merge the values from B into A + if (isObject(a[key]) && isObject(b[key])) { + ret[key] = objMerge(a[key], b[key], max_depth - 1, mergeArrays); + } + // If A & B are both arrays, and we're merging them, concatenate them with B's values taking priority before A + else if (mergeArrays && Array.isArray(a[key]) && Array.isArray(b[key])) { + ret[key] = [...b[key], ...a[key]]; + } + // If B has a value for the key, set the value to B's value + // This better handles the case where A has a value for the key, but B does not + // In which case we want to keep A's value + else if (b[key] !== undefined) { ret[key] = b[key]; } } + // Return the merged object return ret as T; } From 110d9d88770115c16aa34500261e28e3aa177cc3 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Tue, 15 Oct 2024 16:37:53 +0100 Subject: [PATCH 137/224] feat: Record transaction with non-native fees (#4683) ### Description Record transaction with non-native fees. Fees will be recorded as a huge number: max value of unsigned 256-bit long integer. ### Backward compatibility Yes ### Testing Manual testing of Scraper Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../src/providers/cosmos/provider.rs | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index c3e6cb114..491f19776 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -330,6 +330,29 @@ impl CosmosProvider { amount_in_native_denom * coefficient } + + fn calculate_gas_price(&self, hash: &H256, tx: &Tx) -> U256 { + // TODO support multiple denominations for amount + let supported = self.report_unsupported_denominations(tx, hash); + if supported.is_err() { + return U256::max_value(); + } + + let gas_limit = U256::from(tx.auth_info.fee.gas_limit); + let fee = tx + .auth_info + .fee + .amount + .iter() + .map(|c| self.convert_fee(c)) + .fold(U256::zero(), |acc, v| acc + v); + + if fee < gas_limit { + warn!(tx_hash = ?hash, ?fee, ?gas_limit, "calculated fee is less than gas limit. it will result in zero gas price"); + } + + fee / gas_limit + } } impl HyperlaneChain for CosmosProvider { @@ -395,26 +418,7 @@ impl HyperlaneProvider for CosmosProvider { let contract = Self::contract(&tx, hash)?; let (sender, nonce) = self.sender_and_nonce(&tx)?; - - // TODO support multiple denominations for amount - self.report_unsupported_denominations(&tx, hash)?; - - let gas_limit = U256::from(tx.auth_info.fee.gas_limit); - let fee = tx - .auth_info - .fee - .amount - .iter() - .map(|c| self.convert_fee(c)) - .fold(U256::zero(), |acc, v| acc + v); - - let gas_price = fee / gas_limit; - let gas_price = if gas_price == U256::zero() { - warn!(?fee, ?gas_limit, "calculated zero gas price"); - U256::one() - } else { - gas_price - }; + let gas_price = self.calculate_gas_price(hash, &tx); let tx_info = TxnInfo { hash: hash.to_owned(), From c08d842adf5f54f77d4468b68253dfafc695d139 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:00:09 +0100 Subject: [PATCH 138/224] feat: implement reorg audit remediations (#4682) ### Description Bump up .registryrc and update agent configs with updated chain metadata including: - reorg periods - technical stack Updates originally made in https://github.com/hyperlane-xyz/hyperlane-registry/pull/276 Relies on `objMerge` to be fixed https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4678 ### Drive-by changes - remove extraneous overrides + bring exiting relayer env vars into config - so it's in the image build directly, and we minimise break-glass-in-case-of-emergency overrides to the stateful set - ensure txOverrides are only included if defined in infra or registry - ensure we delete txo verrides from the read-in config, before merging with the generated config ### Related issues na ### Backward compatibility yes ### Testing na --- .registryrc | 2 +- rust/main/config/mainnet_config.json | 342 ++++++++++-------- rust/main/config/testnet_config.json | 8 +- .../config/environments/mainnet3/chains.ts | 23 +- .../scripts/agents/update-agent-config.ts | 24 +- 5 files changed, 217 insertions(+), 182 deletions(-) diff --git a/.registryrc b/.registryrc index f9d1c257f..44edec0c4 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -3cd5d816549b1ae391e6a3c68acc07d439175888 +8583d0841615313c8c880e765eba760378e061cd diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index fe61ef2ff..c460fe308 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -14,7 +14,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 888888888, "deployer": { @@ -60,7 +60,7 @@ "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", "storageGasOracle": "0x59Bf7c7b458375b1A7c453aE70EaCb376E65CDAF", - "technicalStack": "other", + "technicalStack": "opstack", "testRecipient": "0x2Fa570E83009eaEef3a1cbd496a9a30F05266634", "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d", @@ -80,7 +80,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 42161, "deployer": { @@ -209,7 +209,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x9Cad0eC82328CEE2386Ec14a12E81d070a27712f", "staticMerkleRootWeightedMultisigIsmFactory": "0xEdF170Da58598955e9a63DA43885842108969129", - "staticMessageIdWeightedMultisigIsmFactory": "0xf44bae1e60bD5B895B2c5bAfF26C49B7e324E36C" + "staticMessageIdWeightedMultisigIsmFactory": "0xf44bae1e60bD5B895B2c5bAfF26C49B7e324E36C", + "technicalStack": "other" }, "base": { "aggregationHook": "0x13f3d4B0Ee0a713430fded9E18f7fb6c91A6E41F", @@ -224,7 +225,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 10 }, "chainId": 8453, "deployer": { @@ -279,7 +280,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x182E8d7c5F1B06201b102123FC7dF0EaeB445a7B", "staticMerkleRootWeightedMultisigIsmFactory": "0x414B67F62b143d6db6E9b633168Dd6fd4DA20642", - "staticMessageIdWeightedMultisigIsmFactory": "0xcfacC141f090E5441D8F274659D43ec20F748b19" + "staticMessageIdWeightedMultisigIsmFactory": "0xcfacC141f090E5441D8F274659D43ec20F748b19", + "technicalStack": "opstack" }, "blast": { "aggregationHook": "0x012278333Ce0A845AE9bD7302867a59Bd5D3635d", @@ -294,7 +296,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 81457, "deployer": { @@ -342,7 +344,7 @@ "staticMerkleRootMultisigIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", "staticMessageIdMultisigIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "storageGasOracle": "0xBDa330Ea8F3005C421C8088e638fBB64fA71b9e0", - "technicalStack": "other", + "technicalStack": "opstack", "testRecipient": "0x17E216fBb22dF4ef8A6640ae9Cb147C92710ac84", "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72", @@ -362,7 +364,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 60808, "deployer": { @@ -407,7 +409,7 @@ "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", "storageGasOracle": "0x2Fca7f6eC3d4A0408900f2BB30004d4616eE985E", - "technicalStack": "other", + "technicalStack": "opstack", "testRecipient": "0xe03dad16074BC5EEA9A9311257BF02Eb0B6AAA2b", "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503", @@ -482,12 +484,13 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "testTokenRecipient": "0x85ac1164878e017b67660a74ff1f41f3D05C02Bb", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "gasPrice": 3000000000 - }, "validatorAnnounce": "0x7024078130D9c2100fEA474DAD009C2d1703aCcd", "staticMerkleRootWeightedMultisigIsmFactory": "0x6f72BF0018a93689D9CD6BF59C7AAeA66F578Fc1", - "staticMessageIdWeightedMultisigIsmFactory": "0x058C7458193f1b28e2bF7547E3f7a6A719Fc0f59" + "staticMessageIdWeightedMultisigIsmFactory": "0x058C7458193f1b28e2bF7547E3f7a6A719Fc0f59", + "technicalStack": "other", + "transactionOverrides": { + "gasPrice": 3000000000 + } }, "celo": { "aggregationHook": "0xc65890329066FB20c339Bc5C22f1756e9D3a4fF5", @@ -558,7 +561,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0xCeF677b65FDaA6804d4403083bb12B8dB3991FE1", "staticMerkleRootWeightedMultisigIsmFactory": "0x0f05deB9c5931c3F87209674B6d4c6df74F6DCBc", - "staticMessageIdWeightedMultisigIsmFactory": "0x58924b11A3B03D533192Dd5a92bc358F5a970E34" + "staticMessageIdWeightedMultisigIsmFactory": "0x58924b11A3B03D533192Dd5a92bc358F5a970E34", + "technicalStack": "other" }, "cheesechain": { "aggregationHook": "0x8007d1e60991fB9BE1be26f70A7cE284fdE7da97", @@ -572,8 +576,8 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 90, - "reorgPeriod": 0 + "estimateBlockTime": 30, + "reorgPeriod": 1 }, "chainId": 383353, "deployer": { @@ -638,7 +642,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 7560, "deployer": { @@ -689,7 +693,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0x71388C9E25BE7b229B5d17Df7D4DB3F7DA7C962d", "interchainAccountIsm": "0x67F36550b73B731e5b2FC44E4F8f250d89c87bD6", "interchainAccountRouter": "0x7B032cBB00AD7438E802A66D8b64761A06E5df22", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "opstack" }, "degenchain": { "aggregationHook": "0xDC995884ec53b6Bc809ed614f5E92084600002ed", @@ -704,7 +709,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 10, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 666666666, "deployer": { @@ -797,7 +802,8 @@ } ], "validatorAnnounce": "Hqnn593pqDZWLy6bKZ4NbY767wFhUNBShDrLktuQa3Q2", - "interchainSecurityModule": "BgG35GxoaMgmiam3EJzcwivwQ2DTYGPTLfUCg7bhiH6V" + "interchainSecurityModule": "BgG35GxoaMgmiam3EJzcwivwQ2DTYGPTLfUCg7bhiH6V", + "technicalStack": "other" }, "endurance": { "aggregationHook": "0x62c39B0500760c46Ae9Ae312A30f63445dc24C3a", @@ -812,7 +818,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 12, - "reorgPeriod": 14 + "reorgPeriod": 15 }, "chainId": 648, "deployer": { @@ -861,7 +867,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x3c7653dD0Ec21A833f99293CDC17495CE249532c", "staticMerkleRootWeightedMultisigIsmFactory": "0xc441521bA37EaCd9af4f319CcdA27E9D48f74281", - "staticMessageIdWeightedMultisigIsmFactory": "0x730f8a4128Fa8c53C777B62Baa1abeF94cAd34a9" + "staticMessageIdWeightedMultisigIsmFactory": "0x730f8a4128Fa8c53C777B62Baa1abeF94cAd34a9", + "technicalStack": "other" }, "ethereum": { "aggregationHook": "0xb87AC8EA4533AE017604E44470F7c1E550AC6F10", @@ -880,9 +887,9 @@ } ], "blocks": { - "confirmations": 3, + "confirmations": 2, "estimateBlockTime": 13, - "reorgPeriod": 14 + "reorgPeriod": 15 }, "chainId": 1, "deployer": { @@ -933,13 +940,10 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "testTokenRecipient": "0x85ac1164878e017b67660a74ff1f41f3D05C02Bb", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "maxFeePerGas": 150000000000, - "maxPriorityFeePerGas": 5000000000 - }, "validatorAnnounce": "0xCe74905e51497b4adD3639366708b821dcBcff96", "staticMerkleRootWeightedMultisigIsmFactory": "0xA2502bF73e5313c1bf48E47C887cdcbf2640FA41", - "staticMessageIdWeightedMultisigIsmFactory": "0x4272124Fba59CbA076D85375895f94B6a3485c3E" + "staticMessageIdWeightedMultisigIsmFactory": "0x4272124Fba59CbA076D85375895f94B6a3485c3E", + "technicalStack": "other" }, "fraxtal": { "aggregationHook": "0xD7ff06cDd83642D648baF0d36f77e79349120dA4", @@ -954,7 +958,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 252, "deployer": { @@ -1006,7 +1010,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x1956848601549de5aa0c887892061fA5aB4f6fC4", "staticMerkleRootWeightedMultisigIsmFactory": "0x7947b7Fe737B4bd1D3387153f32148974066E591", - "staticMessageIdWeightedMultisigIsmFactory": "0x1A41a365A693b6A7aED1a46316097d290f569F22" + "staticMessageIdWeightedMultisigIsmFactory": "0x1A41a365A693b6A7aED1a46316097d290f569F22", + "technicalStack": "opstack" }, "fusemainnet": { "aggregationHook": "0xF4135554ED2c60dB9c1166933797164C43ABb6E2", @@ -1021,7 +1026,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 1 + "reorgPeriod": 19 }, "chainId": 122, "deployer": { @@ -1079,7 +1084,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x60bB6D060393D3C206719A7bD61844cC82891cfB", "staticMerkleRootWeightedMultisigIsmFactory": "0xe522A5DcA58e3ab7fEd2bf25DA3E8d90c14083a8", - "staticMessageIdWeightedMultisigIsmFactory": "0x53642476e24E28c3218E8Da44eDEBB4adB9DE13e" + "staticMessageIdWeightedMultisigIsmFactory": "0x53642476e24E28c3218E8Da44eDEBB4adB9DE13e", + "technicalStack": "other" }, "gnosis": { "aggregationHook": "0xdD1FA1C12496474c1dDC67a658Ba81437F818861", @@ -1094,7 +1100,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 14 + "reorgPeriod": 5 }, "chainId": 100, "deployer": { @@ -1148,7 +1154,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x87ED6926abc9E38b9C7C19f835B41943b622663c", "staticMerkleRootWeightedMultisigIsmFactory": "0xA37ce588515668632D9025272859D2E5bD3210BB", - "staticMessageIdWeightedMultisigIsmFactory": "0x5B7365640c82F402C43A3961F3fD34Ae31f52931" + "staticMessageIdWeightedMultisigIsmFactory": "0x5B7365640c82F402C43A3961F3fD34Ae31f52931", + "technicalStack": "other" }, "inevm": { "aggregationHook": "0xe0dDb5dE7D52918237cC1Ae131F29dcAbcb0F62B", @@ -1163,7 +1170,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 3 }, "chainId": 2525, "customHook": "0xA376b27212D608324808923Add679A2c9FAFe9Da", @@ -1247,7 +1254,7 @@ } ], "index": { - "chunk": 5, + "chunk": 25, "from": 58419500 }, "interchainGasPaymaster": "0x27ae52298e5b53b34b7ae0ca63e05845c31e1f59", @@ -1272,7 +1279,8 @@ } ], "slip44": 118, - "validatorAnnounce": "0x1fb225b2fcfbe75e614a1d627de97ff372242eed" + "validatorAnnounce": "0x1fb225b2fcfbe75e614a1d627de97ff372242eed", + "technicalStack": "other" }, "kroma": { "aggregationHook": "0xF6C1769d5390Be0f77080eF7791fBbA7eF4D5659", @@ -1287,7 +1295,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 255, "deployer": { @@ -1341,7 +1349,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0x749848D7b783A328638C3ea74AcFcfb73c977CbE", "interchainAccountIsm": "0xd64d126941EaC2Cf53e0E4E8146cC70449b60D73", "interchainAccountRouter": "0x1A4F09A615aA4a35E5a146DC2fa19975bebF21A5", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "opstack" }, "linea": { "aggregationHook": "0x43fF73dF1E170D076D9Ed30d4C6922A9D34322dE", @@ -1356,7 +1365,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 59144, "deployer": { @@ -1414,7 +1423,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x62B7592C1B6D1E43f4630B8e37f4377097840C05", "staticMerkleRootWeightedMultisigIsmFactory": "0x11df2f96bC60DfE5A2ab193AD0FCC0a0336F22d0", - "staticMessageIdWeightedMultisigIsmFactory": "0xb0772086edF20278501bb2aF8D8efDe4B71C73Ce" + "staticMessageIdWeightedMultisigIsmFactory": "0xb0772086edF20278501bb2aF8D8efDe4B71C73Ce", + "technicalStack": "other" }, "lisk": { "aggregationHook": "0xDC995884ec53b6Bc809ed614f5E92084600002ed", @@ -1429,7 +1439,7 @@ "blocks": { "confirmations": 3, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 1135, "deployer": { @@ -1477,7 +1487,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", "interchainAccountIsm": "0xD8aF449f8fEFbA2064863DCE5aC248F8B232635F", "interchainAccountRouter": "0x3881c3e945CBB89ae67c43E82f570baDF1c6EA94", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "opstack" }, "lukso": { "aggregationHook": "0xeCBe91B90ab862aa26E5a241D13d1746D24C74A1", @@ -1492,7 +1503,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 12, - "reorgPeriod": 14 + "reorgPeriod": 15 }, "chainId": 42, "deployer": { @@ -1546,7 +1557,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", "interchainAccountIsm": "0xd64d126941EaC2Cf53e0E4E8146cC70449b60D73", "interchainAccountRouter": "0x1A4F09A615aA4a35E5a146DC2fa19975bebF21A5", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "other" }, "mantapacific": { "aggregationHook": "0x8464aF853363B8d6844070F68b0AB34Cb6523d0F", @@ -1561,7 +1573,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 169, "deployer": { @@ -1616,7 +1628,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x2fa5F5C96419C222cDbCeC797D696e6cE428A7A9", "staticMerkleRootWeightedMultisigIsmFactory": "0x0A5d831c09204888B8791BF4E9c49445aD54f2C5", - "staticMessageIdWeightedMultisigIsmFactory": "0xc11f8Cf2343d3788405582F65B8af6A4F7a6FfC8" + "staticMessageIdWeightedMultisigIsmFactory": "0xc11f8Cf2343d3788405582F65B8af6A4F7a6FfC8", + "technicalStack": "opstack" }, "mantle": { "aggregationHook": "0x76b396EaCBF3580B80Ee34C94e780a1Dee76EC72", @@ -1631,7 +1644,7 @@ "blocks": { "confirmations": 3, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 2 }, "chainId": 5000, "deployer": { @@ -1676,7 +1689,7 @@ "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", "storageGasOracle": "0xf9DbC8776Bc2812c4DBEc45383A1783Ac758Fb55", - "technicalStack": "other", + "technicalStack": "opstack", "testRecipient": "0x62B7592C1B6D1E43f4630B8e37f4377097840C05", "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x1956848601549de5aa0c887892061fA5aB4f6fC4", @@ -1696,7 +1709,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 4200, "deployer": { @@ -1747,7 +1760,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0xD7EcB0396406682a27E87F7946c25Ac531140959", "interchainAccountIsm": "0xA8A311B69f688c1D9928259D872C31ca0d473642", "interchainAccountRouter": "0x9e8b689e83d929cb8c2d9166E55319a4e6aA83B7", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "polygoncdk" }, "metis": { "aggregationHook": "0xDC995884ec53b6Bc809ed614f5E92084600002ed", @@ -1762,7 +1776,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 1088, "deployer": { @@ -1804,7 +1818,7 @@ "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", "storageGasOracle": "0x7b2e996742fA42d223652A344252B725D1bC428C", - "technicalStack": "arbitrumnitro", + "technicalStack": "opstack", "testRecipient": "0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67", "validatorAnnounce": "0x062200d92dF6bB7bA89Ce4D6800110450f94784e", "staticMerkleRootWeightedMultisigIsmFactory": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", @@ -1826,7 +1840,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 185, "deployer": { @@ -1875,7 +1889,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", "interchainAccountIsm": "0x1A4F09A615aA4a35E5a146DC2fa19975bebF21A5", "interchainAccountRouter": "0xb2674E213019972f937CCFc5e23BF963D915809e", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "opstack" }, "mode": { "aggregationHook": "0x80D80cfBa98dD2d456ECd43Dcc1f852D5C4EeD7a", @@ -1890,7 +1905,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 34443, "deployer": { @@ -1938,7 +1953,7 @@ "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", "storageGasOracle": "0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465", - "technicalStack": "other", + "technicalStack": "opstack", "testRecipient": "0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0", "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x48083C69f5a42c6B69ABbAd48AE195BD36770ee2", @@ -1958,7 +1973,7 @@ "blocks": { "confirmations": 2, "estimateBlockTime": 12, - "reorgPeriod": 2 + "reorgPeriod": 10 }, "chainId": 1284, "deployer": { @@ -2006,13 +2021,14 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "testTokenRecipient": "0x85ac1164878e017b67660a74ff1f41f3D05C02Bb", "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x8c1001eBee6F25b31863A55EadfF149aF88B356F", + "staticMerkleRootWeightedMultisigIsmFactory": "0x13B09a1d80e93E03221e1F393B588C28a5dE9B69", + "staticMessageIdWeightedMultisigIsmFactory": "0x1E14479A04786900F32c916c11eE1EEf81B5a6bA", + "technicalStack": "polkadotsubstrate", "transactionOverrides": { "maxFeePerGas": 350000000000, "maxPriorityFeePerGas": 50000000000 - }, - "validatorAnnounce": "0x8c1001eBee6F25b31863A55EadfF149aF88B356F", - "staticMerkleRootWeightedMultisigIsmFactory": "0x13B09a1d80e93E03221e1F393B588C28a5dE9B69", - "staticMessageIdWeightedMultisigIsmFactory": "0x1E14479A04786900F32c916c11eE1EEf81B5a6bA" + } }, "neutron": { "bech32Prefix": "neutron", @@ -2083,7 +2099,8 @@ "type": "cosmosKey" }, "slip44": 118, - "validatorAnnounce": "0xf3aa0d652226e21ae35cd9035c492ae41725edc9036edf0d6a48701b153b90a0" + "validatorAnnounce": "0xf3aa0d652226e21ae35cd9035c492ae41725edc9036edf0d6a48701b153b90a0", + "technicalStack": "other" }, "optimism": { "aggregationHook": "0x4ccC6d8eB79f2a1EC9bcb0f211fef7907631F91f", @@ -2098,7 +2115,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 10 }, "chainId": 10, "deployer": { @@ -2148,7 +2165,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x30f5b08e01808643221528BB2f7953bf2830Ef38", "staticMerkleRootWeightedMultisigIsmFactory": "0x313b18228236bf89fc67cca152c62f1896eEa362", - "staticMessageIdWeightedMultisigIsmFactory": "0x3A2e96403d076e9f953166A9E4c61bcD9D164CFe" + "staticMessageIdWeightedMultisigIsmFactory": "0x3A2e96403d076e9f953166A9E4c61bcD9D164CFe", + "technicalStack": "opstack" }, "osmosis": { "bech32Prefix": "osmo", @@ -2185,7 +2203,7 @@ } ], "index": { - "chunk": 5, + "chunk": 10, "from": 14389169 }, "interchainGasPaymaster": "0xd20a9dcf61939fc2fe6ad501b9457b1029b3cc7ab12ed72675ea2e10d831ee5d", @@ -2216,7 +2234,8 @@ "type": "cosmosKey" }, "slip44": 118, - "validatorAnnounce": "0xaf867da5b09a20ee49161d57f99477c0c42d100f34eb53da0d2eb7fc6c257235" + "validatorAnnounce": "0xaf867da5b09a20ee49161d57f99477c0c42d100f34eb53da0d2eb7fc6c257235", + "technicalStack": "other" }, "polygon": { "aggregationHook": "0x34dAb05650Cf590088bA18aF9d597f3e081bCc47", @@ -2285,13 +2304,14 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "testTokenRecipient": "0x85ac1164878e017b67660a74ff1f41f3D05C02Bb", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "maxFeePerGas": 550000000000, - "maxPriorityFeePerGas": 50000000000 - }, "validatorAnnounce": "0x454E1a1E1CA8B51506090f1b5399083658eA4Fc5", "staticMerkleRootWeightedMultisigIsmFactory": "0x07CE1B0cFfa436AE2fb7Fbd7318648774FdA53f9", - "staticMessageIdWeightedMultisigIsmFactory": "0x9e22945bE593946618383B108CC5bce09eBA4C26" + "staticMessageIdWeightedMultisigIsmFactory": "0x9e22945bE593946618383B108CC5bce09eBA4C26", + "technicalStack": "other", + "transactionOverrides": { + "maxFeePerGas": 800000000000, + "maxPriorityFeePerGas": 50000000000 + } }, "polygonzkevm": { "aggregationHook": "0x8464aF853363B8d6844070F68b0AB34Cb6523d0F", @@ -2306,7 +2326,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 10, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 1101, "deployer": { @@ -2357,12 +2377,13 @@ "storageGasOracle": "0x19dc38aeae620380430C200a6E990D5Af5480117", "testRecipient": "0xD127D4549cb4A5B2781303a4fE99a10EAd13263A", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "gasPrice": 1000000000 - }, "validatorAnnounce": "0x2fa5F5C96419C222cDbCeC797D696e6cE428A7A9", "staticMerkleRootWeightedMultisigIsmFactory": "0xc24f3ba8619Fe9db9b95fB616D6945779669e591", - "staticMessageIdWeightedMultisigIsmFactory": "0x882Ad0CcB25CDf928e2a9C899F23eC033C4113f7" + "staticMessageIdWeightedMultisigIsmFactory": "0x882Ad0CcB25CDf928e2a9C899F23eC033C4113f7", + "technicalStack": "polygoncdk", + "transactionOverrides": { + "gasPrice": 1000000000 + } }, "proofofplay": { "aggregationHook": "0xF6C1769d5390Be0f77080eF7791fBbA7eF4D5659", @@ -2377,7 +2398,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 1, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 70700, "deployer": { @@ -2440,7 +2461,7 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 4, + "estimateBlockTime": 30, "reorgPeriod": 0 }, "chainId": 111188, @@ -2505,7 +2526,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 690, "deployer": { @@ -2554,7 +2575,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0", "staticMerkleRootWeightedMultisigIsmFactory": "0x794Fe7970EE45945b0ad2667f99A5bBc9ddfB5d7", - "staticMessageIdWeightedMultisigIsmFactory": "0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0" + "staticMessageIdWeightedMultisigIsmFactory": "0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0", + "technicalStack": "opstack" }, "sanko": { "aggregationHook": "0xF6C1769d5390Be0f77080eF7791fBbA7eF4D5659", @@ -2568,8 +2590,8 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 10, - "reorgPeriod": 0 + "estimateBlockTime": 15, + "reorgPeriod": 1 }, "chainId": 1996, "deployer": { @@ -2633,7 +2655,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 30 + "reorgPeriod": 17 }, "chainId": 534352, "deployer": { @@ -2681,12 +2703,10 @@ "storageGasOracle": "0x481171eb1aad17eDE6a56005B7F1aB00C581ef13", "testRecipient": "0x674f4698d063cE4C0d604c88dD7D542De72f327f", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "gasPrice": 2000000000 - }, "validatorAnnounce": "0xd83A4F747fE80Ed98839e05079B1B7Fe037b1638", "staticMerkleRootWeightedMultisigIsmFactory": "0xcb0D04010584AA5244b5826c990eeA4c16BeAC8C", - "staticMessageIdWeightedMultisigIsmFactory": "0x609707355a53d2aAb6366f48E2b607C599D26B29" + "staticMessageIdWeightedMultisigIsmFactory": "0x609707355a53d2aAb6366f48E2b607C599D26B29", + "technicalStack": "other" }, "sei": { "aggregationHook": "0x40514BD46C57455933Be8BAedE96C4F0Ba3507D6", @@ -2748,12 +2768,13 @@ "storageGasOracle": "0x26f32245fCF5Ad53159E875d5Cae62aEcf19c2d4", "testRecipient": "0xdB670e1a1e312BF17425b08cE55Bdf2cD8F8eD54", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "gasPrice": 101000000000 - }, "validatorAnnounce": "0x5332D1AC0A626D265298c14ff681c0A8D28dB86d", "staticMerkleRootWeightedMultisigIsmFactory": "0xDf347f7602fFF536337c0B90cEC19CD6998427C4", - "staticMessageIdWeightedMultisigIsmFactory": "0x816CF11aDFF6De498823F739eAfe350E82ee845D" + "staticMessageIdWeightedMultisigIsmFactory": "0x816CF11aDFF6De498823F739eAfe350E82ee845D", + "technicalStack": "other", + "transactionOverrides": { + "gasPrice": 101000000000 + } }, "solanamainnet": { "blockExplorers": [ @@ -2798,7 +2819,8 @@ } ], "validatorAnnounce": "pRgs5vN4Pj7WvFbxf6QDHizo2njq2uksqEUbaSghVA8", - "interchainSecurityModule": "372D5YP7jMYUgYBXTVJ7BZtzKv1mq1J6wvjSFLNTRreC" + "interchainSecurityModule": "372D5YP7jMYUgYBXTVJ7BZtzKv1mq1J6wvjSFLNTRreC", + "technicalStack": "other" }, "taiko": { "aggregationHook": "0x1175A31f66C5e3d0ce0ca3B7F80Abe72c6FcE272", @@ -2813,7 +2835,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 12, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 167000, "deployer": { @@ -2878,7 +2900,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 6, - "reorgPeriod": 0 + "reorgPeriod": 10 }, "chainId": 5845, "deployer": { @@ -2927,7 +2949,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0xcd849e612Aaa138f03698C3Edb42a34117BFF631", "interchainAccountIsm": "0x45285463352c53a481e882cD5E2AF2E25BBdAd0D", "interchainAccountRouter": "0x67F36550b73B731e5b2FC44E4F8f250d89c87bD6", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "polkadotsubstrate" }, "viction": { "aggregationHook": "0x5c7890FAf9c99dC55926F00d624D7Bc6D7ac6834", @@ -2942,7 +2965,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 3 }, "chainId": 88, "deployer": { @@ -2995,7 +3018,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x2fa5F5C96419C222cDbCeC797D696e6cE428A7A9", "staticMerkleRootWeightedMultisigIsmFactory": "0x766fc1d3F6CFAE5A06Fe8D6b65a3012401Bd36Ba", - "staticMessageIdWeightedMultisigIsmFactory": "0x9f4012ba9368FBb95F56c2Fc2D956df803D8779e" + "staticMessageIdWeightedMultisigIsmFactory": "0x9f4012ba9368FBb95F56c2Fc2D956df803D8779e", + "technicalStack": "other" }, "worldchain": { "aggregationHook": "0x8007d1e60991fB9BE1be26f70A7cE284fdE7da97", @@ -3010,7 +3034,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 480, "deployer": { @@ -3058,7 +3082,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x047ba6c9949baB22d13C347B40819b7A20C4C53a", "staticMerkleRootWeightedMultisigIsmFactory": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "staticMessageIdWeightedMultisigIsmFactory": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E" + "staticMessageIdWeightedMultisigIsmFactory": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", + "technicalStack": "opstack" }, "xai": { "aggregationHook": "0xF6C1769d5390Be0f77080eF7791fBbA7eF4D5659", @@ -3073,7 +3098,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 1, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 660279, "deployer": { @@ -3137,7 +3162,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 10, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 196, "deployer": { @@ -3190,7 +3215,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x047ba6c9949baB22d13C347B40819b7A20C4C53a", "staticMerkleRootWeightedMultisigIsmFactory": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", - "staticMessageIdWeightedMultisigIsmFactory": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2" + "staticMessageIdWeightedMultisigIsmFactory": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2", + "technicalStack": "polygoncdk" }, "zetachain": { "aggregationHook": "0x80D80cfBa98dD2d456ECd43Dcc1f852D5C4EeD7a", @@ -3257,7 +3283,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0x48083C69f5a42c6B69ABbAd48AE195BD36770ee2", "staticMerkleRootWeightedMultisigIsmFactory": "0xF645AeA0b8D26c9DBdfdeF2DEe59F845715BE32F", - "staticMessageIdWeightedMultisigIsmFactory": "0x0ed553e7e5D55535457d1E778Ba96cF839c18442" + "staticMessageIdWeightedMultisigIsmFactory": "0x0ed553e7e5D55535457d1E778Ba96cF839c18442", + "technicalStack": "other" }, "zircuit": { "aggregationHook": "0x198e8c938EC00Da143e772628c7958DD97B7c2A6", @@ -3272,7 +3299,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 48900, "deployer": { @@ -3327,7 +3354,8 @@ "staticMessageIdWeightedMultisigIsmFactory": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", "interchainAccountIsm": "0xd386Bb418B61E296e1689C95AfE94A2E321a6eaD", "interchainAccountRouter": "0x51545389E04c2Ac07d98A40b85d29B480a2AF6ce", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "opstack" }, "zoramainnet": { "aggregationHook": "0x1e7115a7E45804C81C77caFF37f2BA421f32a0b4", @@ -3342,7 +3370,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 7777777, "deployer": { @@ -3391,7 +3419,8 @@ "timelockController": "0x0000000000000000000000000000000000000000", "validatorAnnounce": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", "staticMerkleRootWeightedMultisigIsmFactory": "0x33AA12b4e8E79cA551Ca9D1F2eC7d2cE02129dd4", - "staticMessageIdWeightedMultisigIsmFactory": "0xB31553F20D7b06Eb8Eaefe29376146e1d276d091" + "staticMessageIdWeightedMultisigIsmFactory": "0xB31553F20D7b06Eb8Eaefe29376146e1d276d091", + "technicalStack": "opstack" }, "astar": { "blockExplorers": [ @@ -3405,7 +3434,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 13, - "reorgPeriod": 0 + "reorgPeriod": 32 }, "chainId": 592, "deployer": { @@ -3454,7 +3483,8 @@ }, "interchainAccountIsm": "0xd01A3E167d59FF98c983E83BAa5da0C3e0ADe726", "interchainAccountRouter": "0x5090dF2FBDa7127c7aDa41f60B79F5c55D380Dd8", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "polkadotsubstrate" }, "astarzkevm": { "blockExplorers": [ @@ -3468,7 +3498,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 3776, "deployer": { @@ -3520,7 +3550,8 @@ }, "interchainAccountIsm": "0xa35cbc2d169284580d82AecED883d0800aa7fbfC", "interchainAccountRouter": "0x7621e04860F0bDe63311db9D5D8b589AD3458A1f", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "polygoncdk" }, "bitlayer": { "blockExplorers": [ @@ -3534,7 +3565,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 20 }, "chainId": 200901, "deployer": { @@ -3589,7 +3620,8 @@ }, "interchainAccountIsm": "0xa97ec3E58cBd60199dcFDd6396431BE85c2E363e", "interchainAccountRouter": "0xA0a44cB8Bc0f7EDe788b0Cd29524A5b14fED7b45", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "other" }, "coredao": { "blockExplorers": [ @@ -3603,7 +3635,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 21 }, "chainId": 1116, "deployer": { @@ -3664,7 +3696,8 @@ }, "interchainAccountIsm": "0x87bDFaBbCC36D8B1aEdA871Cd54b2e86C7a4d597", "interchainAccountRouter": "0xd01A3E167d59FF98c983E83BAa5da0C3e0ADe726", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "other" }, "dogechain": { "blockExplorers": [ @@ -3678,7 +3711,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 2000, "deployer": { @@ -3727,7 +3760,8 @@ }, "interchainAccountIsm": "0x87bDFaBbCC36D8B1aEdA871Cd54b2e86C7a4d597", "interchainAccountRouter": "0xd01A3E167d59FF98c983E83BAa5da0C3e0ADe726", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "polygoncdk" }, "flare": { "blockExplorers": [ @@ -3741,7 +3775,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 3 }, "chainId": 14, "deployer": { @@ -3799,7 +3833,8 @@ }, "interchainAccountIsm": "0xc2Da384799488B4e1E773d70a83346529145085B", "interchainAccountRouter": "0x87bDFaBbCC36D8B1aEdA871Cd54b2e86C7a4d597", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "other" }, "molten": { "blockExplorers": [ @@ -3812,7 +3847,7 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 1, + "estimateBlockTime": 30, "reorgPeriod": 0 }, "chainId": 360, @@ -3877,7 +3912,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 109, "deployer": { @@ -3929,7 +3964,8 @@ }, "interchainAccountIsm": "0xA0a44cB8Bc0f7EDe788b0Cd29524A5b14fED7b45", "interchainAccountRouter": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a", - "timelockController": "0x0000000000000000000000000000000000000000" + "timelockController": "0x0000000000000000000000000000000000000000", + "technicalStack": "other" }, "everclear": { "blockExplorers": [ @@ -3943,7 +3979,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 2 }, "chainId": 25327, "deployer": { @@ -4056,7 +4092,8 @@ "validatorAnnounce": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c", "index": { "from": 26847587 - } + }, + "technicalStack": "other" }, "alephzeroevm": { "blockExplorers": [ @@ -4070,7 +4107,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 41455, "deployer": { @@ -4138,7 +4175,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 1 + "reorgPeriod": 9 }, "chainId": 88888, "deployer": { @@ -4191,9 +4228,9 @@ "index": { "from": 17051552 }, + "technicalStack": "other", "transactionOverrides": { - "maxPriorityFeePerGas": 1000000000, - "maxFeePerGas": 100000000000000 + "maxPriorityFeePerGas": 1000000000 } }, "immutablezkevm": { @@ -4208,7 +4245,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 20 }, "chainId": 13371, "deployer": { @@ -4261,9 +4298,10 @@ "index": { "from": 12797545 }, + "technicalStack": "other", "transactionOverrides": { - "maxPriorityFeePerGas": 100000000000, - "maxFeePerGas": 100000000000 + "maxFeePerGas": 100000000000, + "maxPriorityFeePerGas": 100000000000 } }, "lumia": { @@ -4278,7 +4316,7 @@ "blocks": { "confirmations": 3, "estimateBlockTime": 4, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 994873017, "deployer": { @@ -4330,7 +4368,8 @@ "validatorAnnounce": "0x989B7307d266151BE763935C856493D968b2affF", "index": { "from": 1923136 - } + }, + "technicalStack": "polygoncdk" }, "rari": { "blockExplorers": [ @@ -4343,7 +4382,7 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 2, + "estimateBlockTime": 30, "reorgPeriod": 0 }, "chainId": 1380012617, @@ -4436,10 +4475,6 @@ "http": "https://mycrypto.rsk.co" } ], - "transactionOverrides": { - "gasPrice": 70000000, - "gasLimit": 6800000 - }, "aggregationHook": "0xA530b21B2c1517ceFcAAE890c7f8A167e4C0f51E", "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", @@ -4467,6 +4502,10 @@ "validatorAnnounce": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", "index": { "from": 6749741 + }, + "technicalStack": "other", + "transactionOverrides": { + "gasPrice": 70000000 } }, "superposition": { @@ -4480,7 +4519,7 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 2, + "estimateBlockTime": 60, "reorgPeriod": 0 }, "chainId": 55244, @@ -4545,7 +4584,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 1750, "deployer": { @@ -4595,7 +4634,8 @@ "validatorAnnounce": "0xD569fb1753167312ec5b78526743F2Bea027E5d8", "index": { "from": 8547390 - } + }, + "technicalStack": "opstack" }, "polynomial": { "blockExplorers": [ @@ -4609,7 +4649,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 8008, "deployer": { @@ -4658,7 +4698,8 @@ "validatorAnnounce": "0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c", "index": { "from": 5310074 - } + }, + "technicalStack": "opstack" }, "flow": { "blockExplorers": [ @@ -4672,7 +4713,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 1, - "reorgPeriod": 1 + "reorgPeriod": 25 }, "chainId": 747, "deployer": { @@ -4695,9 +4736,6 @@ "http": "https://mainnet.evm.nodes.onflow.org" } ], - "transactionOverrides": { - "gasPrice": 100000000 - }, "aggregationHook": "0x24A681D6B1B7Fb6208938be982Efd512E842867a", "domainRoutingIsm": "0x85804e2ae21273F6539CFa1A688FE6154004D4dF", "domainRoutingIsmFactory": "0x8C3e1794018a589c9E9226b8543105fCb6cC88C4", @@ -4725,6 +4763,10 @@ "validatorAnnounce": "0xE2B36A37bD98ba81658dC5454F2dB2F98438d140", "index": { "from": 4240431 + }, + "technicalStack": "other", + "transactionOverrides": { + "gasPrice": 100000000 } } }, diff --git a/rust/main/config/testnet_config.json b/rust/main/config/testnet_config.json index a72250818..9cbbb5e1b 100644 --- a/rust/main/config/testnet_config.json +++ b/rust/main/config/testnet_config.json @@ -264,13 +264,13 @@ "testRecipient": "0xfbcD1c00a3d809f36cC1A15918694B17B32c0b6c", "testTokenRecipient": "0x260f6024119549a40595d0937471e607411E8ea5", "timelockController": "0x0000000000000000000000000000000000000000", - "transactionOverrides": { - "gasPrice": 8000000000 - }, "validatorAnnounce": "0xf09701B0a93210113D175461b6135a96773B5465", "staticMerkleRootWeightedMultisigIsmFactory": "0xCa152b249791Adf7A09C6c1bdbAb05e4A594966e", "staticMessageIdWeightedMultisigIsmFactory": "0xaa80d23299861b7D7ab1bE665579029Ed9137BD1", - "gasCurrencyCoinGeckoId": "binancecoin" + "gasCurrencyCoinGeckoId": "binancecoin", + "transactionOverrides": { + "gasPrice": 8000000000 + } }, "connextsepolia": { "aggregationHook": "0x331eb40963dc11F5BB271308c42d97ac6e41F124", diff --git a/typescript/infra/config/environments/mainnet3/chains.ts b/typescript/infra/config/environments/mainnet3/chains.ts index 206114ae3..e7ff32d46 100644 --- a/typescript/infra/config/environments/mainnet3/chains.ts +++ b/typescript/infra/config/environments/mainnet3/chains.ts @@ -19,13 +19,10 @@ export const chainMetadataOverrides: ChainMap> = { }, }, polygon: { - blocks: { - confirmations: 3, - }, transactionOverrides: { // A very high max fee per gas is used as Polygon is susceptible // to large swings in gas prices. - maxFeePerGas: 550 * 10 ** 9, // 550 gwei + maxFeePerGas: 800 * 10 ** 9, // 800 gwei maxPriorityFeePerGas: 50 * 10 ** 9, // 50 gwei }, }, @@ -34,23 +31,6 @@ export const chainMetadataOverrides: ChainMap> = { gasPrice: 1 * 10 ** 9, // 1 gwei }, }, - ethereum: { - blocks: { - confirmations: 3, - }, - transactionOverrides: { - maxFeePerGas: 150 * 10 ** 9, // gwei - maxPriorityFeePerGas: 5 * 10 ** 9, // gwei - }, - }, - scroll: { - transactionOverrides: { - // Scroll doesn't use EIP 1559 and the gas price that's returned is sometimes - // too low for the transaction to be included in a reasonable amount of time - - // this often leads to transaction underpriced issues. - gasPrice: 2 * 10 ** 9, // 2 gwei - }, - }, sei: { // Sei's `eth_feeHistory` is not to spec and incompatible with ethers-rs, // so we force legacy transactions by setting a gas price. @@ -75,7 +55,6 @@ export const chainMetadataOverrides: ChainMap> = { // chiliz: { // transactionOverrides: { // maxFeePerGas: 100000 * 10 ** 9, // 100,000 gwei - // maxPriorityFeePerGas: 1 * 10 ** 9, // 1 gwei // }, // }, }; diff --git a/typescript/infra/scripts/agents/update-agent-config.ts b/typescript/infra/scripts/agents/update-agent-config.ts index 30d64a9d9..de01a2cff 100644 --- a/typescript/infra/scripts/agents/update-agent-config.ts +++ b/typescript/infra/scripts/agents/update-agent-config.ts @@ -1,5 +1,9 @@ +// eslint-disable-next-line +import fs from 'fs'; + import { ChainAddresses } from '@hyperlane-xyz/registry'; import { + AgentConfig, ChainMap, ChainTechnicalStack, CoreFactories, @@ -13,6 +17,7 @@ import { ProtocolType, objFilter, objMap, + objMerge, promiseObjAll, } from '@hyperlane-xyz/utils'; @@ -26,7 +31,8 @@ import { chainIsProtocol, filterRemoteDomainMetadata, isEthereumProtocolChain, - writeMergedJSONAtPath, + readJSONAtPath, + writeJsonAtPath, } from '../../src/utils/utils.js'; import { Modules, @@ -138,10 +144,18 @@ export async function writeAgentConfig( additionalConfig, ); - writeMergedJSONAtPath( - getAgentConfigJsonPath(envNameToAgentEnv[environment]), - agentConfig, - ); + const filepath = getAgentConfigJsonPath(envNameToAgentEnv[environment]); + if (fs.existsSync(filepath)) { + const currentAgentConfig: AgentConfig = readJSONAtPath(filepath); + // Remove transactionOverrides from each chain in the agent config + // To ensure all overrides are configured in infra code or the registry, and not in JSON + for (const chainConfig of Object.values(currentAgentConfig.chains)) { + delete chainConfig.transactionOverrides; + } + writeJsonAtPath(filepath, objMerge(currentAgentConfig, agentConfig)); + } else { + writeJsonAtPath(filepath, agentConfig); + } } main() From 3662297fc581b375c5c1c2b6d6615a9ede5eb56c Mon Sep 17 00:00:00 2001 From: xeno097 Date: Tue, 15 Oct 2024 18:13:10 -0400 Subject: [PATCH 139/224] feat: `warp init` simplified config (#4504) ### Description This PR updates the ISM configuration prompting for the `warp init` command allowing the user to choose if a trusted ISM should be used by default or a configured one. Before: ![image](https://github.com/user-attachments/assets/7be4e5af-d664-4481-ac31-b87caf609b91) ![image](https://github.com/user-attachments/assets/030aa59c-82ad-4349-a973-273b0eb15403) After: ![image](https://github.com/user-attachments/assets/c19ca765-c771-4d04-8041-c5c19f44f645) ![image](https://github.com/user-attachments/assets/5e875beb-c86e-464d-bcf9-0c705a9f43ce) ### Drive-by changes - No ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4464 ### Backward compatibility - Yes ### Testing - Manual --------- Co-authored-by: Lee <6251863+ltyu@users.noreply.github.com> --- .changeset/long-swans-drive.md | 5 ++++ typescript/cli/src/config/warp.ts | 49 ++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 .changeset/long-swans-drive.md diff --git a/.changeset/long-swans-drive.md b/.changeset/long-swans-drive.md new file mode 100644 index 000000000..3f21e56c4 --- /dev/null +++ b/.changeset/long-swans-drive.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +Add prompt in `warp init` command to choose if a trusted relayer should be used instead of making the choice by default for the user and enable the `--yes` flag to default to a trusted ISM diff --git a/typescript/cli/src/config/warp.ts b/typescript/cli/src/config/warp.ts index 8e15ccc3c..6ce1f6665 100644 --- a/typescript/cli/src/config/warp.ts +++ b/typescript/cli/src/config/warp.ts @@ -1,4 +1,4 @@ -import { input, select } from '@inquirer/prompts'; +import { confirm, input, select } from '@inquirer/prompts'; import { stringify as yamlStringify } from 'yaml'; import { @@ -142,6 +142,29 @@ export async function createWarpRouteDeployConfig({ message: `Could not retrieve mailbox address from the registry for chain "${chain}". Please enter a valid mailbox address:`, })); + /** + * The logic from the cli is as follows: + * --advanced flag is provided: the user will have to build their own configuration using the available ISM types + * --yes flag is provided: the default ISM config will be used (Trusted ISM + Default fallback ISM) + * -- no flag is provided: the user must choose if the default ISM config should be used: + * - yes: the default ISM config will be used (Trusted ISM + Default fallback ISM) + * - no: the default fallback ISM will be used + */ + let interchainSecurityModule: IsmConfig; + if (advanced) { + interchainSecurityModule = await createAdvancedIsmConfig(context); + } else if (context.skipConfirmation) { + interchainSecurityModule = createDefaultWarpIsmConfig(owner); + } else if ( + await confirm({ + message: 'Do you want to use a trusted ISM for warp route?', + }) + ) { + interchainSecurityModule = createDefaultWarpIsmConfig(owner); + } else { + interchainSecurityModule = createFallbackRoutingConfig(owner); + } + const type = await select({ message: `Select ${chain}'s token type`, choices: TYPE_CHOICES, @@ -151,10 +174,6 @@ export async function createWarpRouteDeployConfig({ const isNft = type === TokenType.syntheticUri || type === TokenType.collateralUri; - const interchainSecurityModule = advanced - ? await createAdvancedIsmConfig(context) - : createDefaultWarpIsmConfig(owner); - switch (type) { case TokenType.collateral: case TokenType.XERC20: @@ -234,12 +253,22 @@ function createDefaultWarpIsmConfig(owner: Address): IsmConfig { type: IsmType.TRUSTED_RELAYER, relayer: owner, }, - { - type: IsmType.FALLBACK_ROUTING, - domains: {}, - owner, - }, + createFallbackRoutingConfig(owner), ], threshold: 1, }; } + +/** + * Creates a fallback configuration for an ISM with a FALLBACK_ROUTING and the provided `owner`. + * + * @param owner - The address of the owner of the ISM. + * @returns The Fallback Routing ISM configuration. + */ +function createFallbackRoutingConfig(owner: Address): IsmConfig { + return { + type: IsmType.FALLBACK_ROUTING, + domains: {}, + owner, + }; +} From 9382658db340288b34db37ae5684f756526c93e6 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:23:12 +0100 Subject: [PATCH 140/224] fix: update HyperlaneDomainTechnicalStack with latest stacks (#4688) ### Description fix: update HyperlaneDomainTechnicalStack with latest stacks We added new technical stacks, and updated these in registry, but did not update the enum in the agents. this caused a hard failure to load the configs when we tried deploying to prod. Note: we're omiting `zksync` because that is soon to be moved from a "tech stack" into a "protocol type", and we have no chains in registry with a `zksync` technical stack configured yet anyway. ### Drive-by changes update existing list of mainnets with "other" technical stack. can't just remove them right now because we have to ensure every value in the enum is mapped ### Related issues na ### Backward compatibility yes ### Testing todo: fix e2e --- rust/main/hyperlane-core/src/chain.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/rust/main/hyperlane-core/src/chain.rs b/rust/main/hyperlane-core/src/chain.rs index d1b7c5e34..bd73ff613 100644 --- a/rust/main/hyperlane-core/src/chain.rs +++ b/rust/main/hyperlane-core/src/chain.rs @@ -218,6 +218,9 @@ impl HyperlaneDomainProtocol { )] pub enum HyperlaneDomainTechnicalStack { ArbitrumNitro, + OpStack, + PolygonCDK, + PolkadotSubstrate, #[default] Other, } @@ -291,19 +294,27 @@ impl KnownHyperlaneDomain { // Test chains ConnextSepolia, PlumeTestnet, SuperpositionTestnet ], + HyperlaneDomainTechnicalStack::OpStack: [ + Ancient8, Blast, Bob, Cyber, Fraxtal, Kroma, Lisk, MantaPacific, Mantle, Metis, + Mint, Mode, Optimism, Redstone, Worldchain, Zircuit, ZoraMainnet + ], + HyperlaneDomainTechnicalStack::PolygonCDK: [ + Merlin, Xlayer + ], + HyperlaneDomainTechnicalStack::PolkadotSubstrate: [ + Moonbeam, Tangle + ], HyperlaneDomainTechnicalStack::Other: [ - Ancient8, Avalanche, BinanceSmartChain, Blast, Bob, Celo, Cyber, EclipseMainnet, Endurance, Ethereum, - Fraxtal, Fuji, FuseMainnet, Gnosis, Injective, Kroma, Linea, Lisk, Lukso, - MantaPacific, Mantle, Merlin, Metis, Mint, Mode, Moonbeam, Neutron, Optimism, Osmosis, - Polygon, Redstone, Sei, SolanaMainnet, Taiko, Tangle, Viction, Worldchain, Xlayer, Zetachain, - Zircuit, ZoraMainnet, + Avalanche, BinanceSmartChain, Celo, EclipseMainnet, Endurance, Ethereum, + FuseMainnet, Gnosis, Injective, Linea, Lukso, Neutron, Osmosis, Polygon, + Sei, SolanaMainnet, Taiko, Viction, Zetachain, // Local chains CosmosTest99990, CosmosTest99991, FuelTest1, SealevelTest1, SealevelTest2, Test1, Test2, Test3, // Test chains - Alfajores, BinanceSmartChainTestnet, Chiado, Holesky, MoonbaseAlpha, ScrollSepolia, + Alfajores, BinanceSmartChainTestnet, Chiado, Fuji, Holesky, MoonbaseAlpha, ScrollSepolia, Sepolia ], }) From efd438f9b2f0d384a4660a3604359e0e89c86065 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:52:56 +0100 Subject: [PATCH 141/224] chore: fix queue metric juggedness (#4689) ### Description See https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4068 for the problem description. In this fix, whenever an operation is moved from one queue to another, its metric count is decremented from the old queue and incremented for the new one. My initial implementation approach was to update these metrics inside `queue.push(op)`, but the metrics for the operation's previous queue aren't accessible there. #4068 suggests updating them in `op.set_status`, which can't be done for the same reason, even if `op` has a pointer to the current queue's metric internally. So the fix I went for does store a pointer to the current queue metric internally in `op`, but also adds a new `op.set_status_and_update_metrics(status, new_queue_metric)` method, which **must** be used if the queue metrics are to be correctly calculated. This works well except for when ops are removed from the confirm queue, because in the absence of a call to `set_status_and_update_metrics`, no metric decrementing is done. I considered using the `Drop` trait to decrement, but it'd have to be implemented individually for each `PendingOperation` type, which isn't very maintainable. I ended up decrementing the metric in `confirm_operation`, which is called for both batches and single submissions and, of course, all implementations of `PendingOperation`. Here's a screenshot of my local grafana server showing no jaggedness in the e2e run, with prometheus configured to scrape every 2s: ![Screenshot 2024-10-15 at 17 26 56](https://github.com/user-attachments/assets/26004e0e-2ccf-4cec-aa23-ee2d032df25a) ### Drive-by changes Adds the `prepare_queue` arg of `submit_single_operation` to the `instrument(skip(...))` list so it no longer pollutes logs. ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4068 ### Backward compatibility Yes ### Testing Manually, by checking the queue length metric of an e2e run in grafana --- rust/main/Cargo.lock | 1 + rust/main/agents/relayer/src/msg/op_queue.rs | 16 +++++---- .../agents/relayer/src/msg/op_submitter.rs | 5 ++- .../agents/relayer/src/msg/pending_message.rs | 11 +++++++ rust/main/hyperlane-core/Cargo.toml | 1 + .../src/traits/pending_operation.rs | 21 ++++++++++++ rust/sealevel/Cargo.lock | 33 +++++++++++++------ 7 files changed, 71 insertions(+), 17 deletions(-) diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index 9300a0ecb..87d2c813e 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -4489,6 +4489,7 @@ dependencies = [ "num-derive 0.4.2", "num-traits", "primitive-types", + "prometheus", "serde", "serde_json", "sha3 0.10.8", diff --git a/rust/main/agents/relayer/src/msg/op_queue.rs b/rust/main/agents/relayer/src/msg/op_queue.rs index 78a94de70..41ac5b6d6 100644 --- a/rust/main/agents/relayer/src/msg/op_queue.rs +++ b/rust/main/agents/relayer/src/msg/op_queue.rs @@ -30,10 +30,11 @@ impl OpQueue { #[instrument(skip(self), ret, fields(queue_label=%self.queue_metrics_label), level = "trace")] pub async fn push(&self, mut op: QueueOperation, new_status: Option) { if let Some(new_status) = new_status { - op.set_status(new_status); + op.set_status_and_update_metrics( + new_status, + Arc::new(self.get_operation_metric(op.as_ref())), + ); } - // increment the metric before pushing onto the queue, because we lose ownership afterwards - self.get_operation_metric(op.as_ref()).inc(); self.queue.lock().await.push(Reverse(op)); } @@ -52,9 +53,6 @@ impl OpQueue { let mut queue = self.queue.lock().await; let mut popped = vec![]; while let Some(Reverse(op)) = queue.pop() { - // even if the metric is decremented here, the operation may fail to process and be re-added to the queue. - // in those cases, the queue length will look like it has spikes whose sizes are at most `limit` - self.get_operation_metric(op.as_ref()).dec(); popped.push(op); if popped.len() >= limit { break; @@ -242,6 +240,12 @@ pub mod test { fn set_retries(&mut self, _retries: u32) { todo!() } + + fn get_metric(&self) -> Option> { + None + } + + fn set_metric(&mut self, _metric: Arc) {} } pub fn dummy_metrics_and_label() -> (IntGaugeVec, String) { diff --git a/rust/main/agents/relayer/src/msg/op_submitter.rs b/rust/main/agents/relayer/src/msg/op_submitter.rs index e72c5ef14..0694595ae 100644 --- a/rust/main/agents/relayer/src/msg/op_submitter.rs +++ b/rust/main/agents/relayer/src/msg/op_submitter.rs @@ -341,7 +341,7 @@ async fn submit_task( } } -#[instrument(skip(confirm_queue, metrics), ret, level = "debug")] +#[instrument(skip(prepare_queue, confirm_queue, metrics), ret, level = "debug")] async fn submit_single_operation( mut op: QueueOperation, prepare_queue: &mut OpQueue, @@ -457,6 +457,9 @@ async fn confirm_operation( PendingOperationResult::Success => { debug!(?op, "Operation confirmed"); metrics.ops_confirmed.inc(); + if let Some(metric) = op.get_metric() { + metric.dec() + } } PendingOperationResult::NotReady => { confirm_queue.push(op, None).await; diff --git a/rust/main/agents/relayer/src/msg/pending_message.rs b/rust/main/agents/relayer/src/msg/pending_message.rs index 350e9f5b5..9d43595b5 100644 --- a/rust/main/agents/relayer/src/msg/pending_message.rs +++ b/rust/main/agents/relayer/src/msg/pending_message.rs @@ -82,6 +82,9 @@ pub struct PendingMessage { #[new(default)] #[serde(skip_serializing)] metadata: Option>, + #[new(default)] + #[serde(skip_serializing)] + metric: Option>, } impl Debug for PendingMessage { @@ -481,6 +484,14 @@ impl PendingOperation for PendingMessage { fn try_get_mailbox(&self) -> Option> { Some(self.ctx.destination_mailbox.clone()) } + + fn get_metric(&self) -> Option> { + self.metric.clone() + } + + fn set_metric(&mut self, metric: Arc) { + self.metric = Some(metric); + } } impl PendingMessage { diff --git a/rust/main/hyperlane-core/Cargo.toml b/rust/main/hyperlane-core/Cargo.toml index d7591225c..4e835f914 100644 --- a/rust/main/hyperlane-core/Cargo.toml +++ b/rust/main/hyperlane-core/Cargo.toml @@ -33,6 +33,7 @@ itertools.workspace = true num = { workspace = true, features = ["serde"] } num-derive.workspace = true num-traits.workspace = true +prometheus.workspace = true serde = { workspace = true } serde_json = { workspace = true } sha3 = { workspace = true } diff --git a/rust/main/hyperlane-core/src/traits/pending_operation.rs b/rust/main/hyperlane-core/src/traits/pending_operation.rs index 9dfbd93c7..8906777c3 100644 --- a/rust/main/hyperlane-core/src/traits/pending_operation.rs +++ b/rust/main/hyperlane-core/src/traits/pending_operation.rs @@ -13,6 +13,7 @@ use crate::{ }; use async_trait::async_trait; use num::CheckedDiv; +use prometheus::IntGauge; use strum::Display; use tracing::warn; @@ -63,6 +64,12 @@ pub trait PendingOperation: Send + Sync + Debug + TryBatchAs { /// Label to use for metrics granularity. fn app_context(&self) -> Option; + /// Get the metric associated with this operation. + fn get_metric(&self) -> Option>; + + /// Set the metric associated with this operation. + fn set_metric(&mut self, metric: Arc); + /// The status of the operation, which should explain why it is in the /// queue. fn status(&self) -> PendingOperationStatus; @@ -70,6 +77,20 @@ pub trait PendingOperation: Send + Sync + Debug + TryBatchAs { /// Set the status of the operation. fn set_status(&mut self, status: PendingOperationStatus); + /// Set the status of the operation and update the metrics. + fn set_status_and_update_metrics( + &mut self, + status: PendingOperationStatus, + new_metric: Arc, + ) { + self.set_status(status); + if let Some(old_metric) = self.get_metric() { + old_metric.dec(); + } + new_metric.inc(); + self.set_metric(new_metric); + } + /// Get tuple of labels for metrics. fn get_operation_labels(&self) -> (String, String) { let app_context = self.app_context().unwrap_or("Unknown".to_string()); diff --git a/rust/sealevel/Cargo.lock b/rust/sealevel/Cargo.lock index 80489fde2..81beeb35b 100644 --- a/rust/sealevel/Cargo.lock +++ b/rust/sealevel/Cargo.lock @@ -2390,10 +2390,11 @@ dependencies = [ "fixed-hash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "getrandom 0.2.15", "hex", - "itertools 0.12.1", + "itertools 0.13.0", "num 0.4.3", "num-derive 0.4.2", "num-traits", + "prometheus", "serde", "serde_json", "sha3 0.10.8", @@ -2995,15 +2996,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -3993,6 +3985,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prometheus" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "memchr", + "parking_lot 0.12.3", + "protobuf", + "thiserror", +] + +[[package]] +name = "protobuf" +version = "2.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" + [[package]] name = "qstring" version = "0.7.2" From 95fdc5f79383846d48158d05363a10893a901526 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:44:02 +0100 Subject: [PATCH 142/224] chore: update agents with reorg remediations (#4686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description chore: update agents with reorg remediations replaces https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4685 ### Drive-by changes na ### Related issues na ### Backward compatibility yes ### Testing 👁️ --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- typescript/infra/config/environments/mainnet3/agent.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 40464a562..6e34d70cf 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -418,7 +418,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '18c29c8-20241014-133718', + tag: 'efd438f-20241016-101828', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -427,7 +427,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: '18c29c8-20241014-133718', + tag: 'efd438f-20241016-101828', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -437,7 +437,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '18c29c8-20241014-133718', + tag: 'efd438f-20241016-101828', }, resources: scraperResources, }, From 777ef084a67f864c529757a250e1c3898b470b03 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:01:30 +0100 Subject: [PATCH 143/224] fix: queue length metric bug (#4691) ### Description Fix for https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4689, where `Dropped` status operations weren't decremented from the metric. I noticed there's still a small difference on a handful of chains, such as celo, where even if Dropped ones are considered, the prep queue metric reports an extra 53 ops compared to the actual queue. Could be that I manually miscounted, I expect releasing this will be a big improvement anyway. ### Backward compatibility Yes ### Testing No, just checked all places where we `.pop_many` but don't `push` --- rust/main/agents/relayer/src/msg/op_queue.rs | 10 ++++------ rust/main/agents/relayer/src/msg/op_submitter.rs | 7 ++++--- .../hyperlane-core/src/traits/pending_operation.rs | 13 +++++++++++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/rust/main/agents/relayer/src/msg/op_queue.rs b/rust/main/agents/relayer/src/msg/op_queue.rs index 41ac5b6d6..d22e0c3c8 100644 --- a/rust/main/agents/relayer/src/msg/op_queue.rs +++ b/rust/main/agents/relayer/src/msg/op_queue.rs @@ -29,12 +29,10 @@ impl OpQueue { /// it's very likely that its status has just changed, so this forces the caller to consider the new status #[instrument(skip(self), ret, fields(queue_label=%self.queue_metrics_label), level = "trace")] pub async fn push(&self, mut op: QueueOperation, new_status: Option) { - if let Some(new_status) = new_status { - op.set_status_and_update_metrics( - new_status, - Arc::new(self.get_operation_metric(op.as_ref())), - ); - } + op.set_status_and_update_metrics( + new_status, + Arc::new(self.get_operation_metric(op.as_ref())), + ); self.queue.lock().await.push(Reverse(op)); } diff --git a/rust/main/agents/relayer/src/msg/op_submitter.rs b/rust/main/agents/relayer/src/msg/op_submitter.rs index 0694595ae..f35a991c4 100644 --- a/rust/main/agents/relayer/src/msg/op_submitter.rs +++ b/rust/main/agents/relayer/src/msg/op_submitter.rs @@ -293,6 +293,7 @@ async fn prepare_task( } PendingOperationResult::Drop => { metrics.ops_dropped.inc(); + op.decrement_metric_if_exists(); } PendingOperationResult::Confirm(reason) => { debug!(?op, "Pushing operation to confirm queue"); @@ -369,6 +370,7 @@ async fn submit_single_operation( } PendingOperationResult::Drop => { // Not expected to hit this case in `submit`, but it's here for completeness + op.decrement_metric_if_exists(); } PendingOperationResult::Success | PendingOperationResult::Confirm(_) => { confirm_op(op, confirm_queue, metrics).await @@ -457,9 +459,7 @@ async fn confirm_operation( PendingOperationResult::Success => { debug!(?op, "Operation confirmed"); metrics.ops_confirmed.inc(); - if let Some(metric) = op.get_metric() { - metric.dec() - } + op.decrement_metric_if_exists(); } PendingOperationResult::NotReady => { confirm_queue.push(op, None).await; @@ -478,6 +478,7 @@ async fn confirm_operation( } PendingOperationResult::Drop => { metrics.ops_dropped.inc(); + op.decrement_metric_if_exists(); } } operation_result diff --git a/rust/main/hyperlane-core/src/traits/pending_operation.rs b/rust/main/hyperlane-core/src/traits/pending_operation.rs index 8906777c3..f5480b197 100644 --- a/rust/main/hyperlane-core/src/traits/pending_operation.rs +++ b/rust/main/hyperlane-core/src/traits/pending_operation.rs @@ -67,6 +67,13 @@ pub trait PendingOperation: Send + Sync + Debug + TryBatchAs { /// Get the metric associated with this operation. fn get_metric(&self) -> Option>; + /// Decrement the metric associated with this operation if it exists. + fn decrement_metric_if_exists(&self) { + if let Some(metric) = self.get_metric() { + metric.dec(); + } + } + /// Set the metric associated with this operation. fn set_metric(&mut self, metric: Arc); @@ -80,10 +87,12 @@ pub trait PendingOperation: Send + Sync + Debug + TryBatchAs { /// Set the status of the operation and update the metrics. fn set_status_and_update_metrics( &mut self, - status: PendingOperationStatus, + status: Option, new_metric: Arc, ) { - self.set_status(status); + if let Some(status) = status { + self.set_status(status); + } if let Some(old_metric) = self.get_metric() { old_metric.dec(); } From b1ff48bd1d34e0ab2b0d9419d3767c53c469fcae Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:18:06 -0400 Subject: [PATCH 144/224] feat(cli,sdk): Add rebase yield route support (#4474) ### Description This PR adds support for **Rebase Collateral Vault** and **Synthetic Rebase** into the SDK and CLI. The SDK enforces a single Rebase Collateral Vault **must** be deployed with Synthetic Rebase via schema validation and transformation. The CLI filters the subsequent token list depending on the selection. ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4512 ### Backward compatibility Yes ### Testing Manual/Unit Tests - Manually test deployment - E2E test for deployment and message sending --- .changeset/plenty-chicken-clean.md | 6 + typescript/cli/package.json | 4 +- typescript/cli/src/config/warp.ts | 40 +++++- typescript/cli/src/send/transfer.ts | 6 +- typescript/cli/src/tests/commands/helpers.ts | 58 ++++++++- typescript/cli/src/tests/commands/warp.ts | 21 ++++ .../cli/src/tests/warp-apply.e2e-test.ts | 2 +- .../cli/src/tests/warp-deploy.e2e-test.ts | 114 +++++++++++++++++ typescript/sdk/src/index.ts | 2 + .../token/EvmERC20WarpModule.hardhat-test.ts | 7 +- .../EvmERC20WarpRouteReader.hardhat-test.ts | 110 +++++++++++++++-- .../sdk/src/token/EvmERC20WarpRouteReader.ts | 25 +++- typescript/sdk/src/token/Token.test.ts | 17 +++ typescript/sdk/src/token/Token.ts | 20 +-- typescript/sdk/src/token/TokenStandard.ts | 8 ++ typescript/sdk/src/token/config.ts | 3 + typescript/sdk/src/token/contracts.ts | 10 +- typescript/sdk/src/token/deploy.ts | 8 +- typescript/sdk/src/token/schemas.test.ts | 116 ++++++++++++++++-- typescript/sdk/src/token/schemas.ts | 70 ++++++++++- yarn.lock | 33 ++++- 21 files changed, 628 insertions(+), 52 deletions(-) create mode 100644 .changeset/plenty-chicken-clean.md create mode 100644 typescript/cli/src/tests/warp-deploy.e2e-test.ts diff --git a/.changeset/plenty-chicken-clean.md b/.changeset/plenty-chicken-clean.md new file mode 100644 index 000000000..e35a59eff --- /dev/null +++ b/.changeset/plenty-chicken-clean.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Add rebasing yield route support into CLI/SDK diff --git a/typescript/cli/package.json b/typescript/cli/package.json index 19421e2e9..eb1403de0 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -25,12 +25,14 @@ "devDependencies": { "@ethersproject/abi": "*", "@ethersproject/providers": "*", + "@types/chai-as-promised": "^8", "@types/mocha": "^10.0.1", "@types/node": "^18.14.5", "@types/yargs": "^17.0.24", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", - "chai": "4.5.0", + "chai": "^4.5.0", + "chai-as-promised": "^8.0.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "mocha": "^10.2.0", diff --git a/typescript/cli/src/config/warp.ts b/typescript/cli/src/config/warp.ts index 6ce1f6665..29246cd33 100644 --- a/typescript/cli/src/config/warp.ts +++ b/typescript/cli/src/config/warp.ts @@ -34,12 +34,15 @@ import { createAdvancedIsmConfig } from './ism.js'; const TYPE_DESCRIPTIONS: Record = { [TokenType.synthetic]: 'A new ERC20 with remote transfer functionality', + [TokenType.syntheticRebase]: `A rebasing ERC20 with remote transfer functionality. Must be paired with ${TokenType.collateralVaultRebase}`, [TokenType.collateral]: 'Extends an existing ERC20 with remote transfer functionality', [TokenType.native]: 'Extends the native token with remote transfer functionality', [TokenType.collateralVault]: - 'Extends an existing ERC4626 with remote transfer functionality', + 'Extends an existing ERC4626 with remote transfer functionality. Yields are manually claimed by owner.', + [TokenType.collateralVaultRebase]: + 'Extends an existing ERC4626 with remote transfer functionality. Rebases yields to token holders.', [TokenType.collateralFiat]: 'Extends an existing FiatToken with remote transfer functionality', [TokenType.XERC20]: @@ -129,6 +132,7 @@ export async function createWarpRouteDeployConfig({ ); const result: WarpRouteDeployConfig = {}; + let typeChoices = TYPE_CHOICES; for (const chain of warpChains) { logBlue(`${chain}: Configuring warp route...`); @@ -167,7 +171,7 @@ export async function createWarpRouteDeployConfig({ const type = await select({ message: `Select ${chain}'s token type`, - choices: TYPE_CHOICES, + choices: typeChoices, }); // TODO: restore NFT prompting @@ -192,6 +196,34 @@ export async function createWarpRouteDeployConfig({ }), }; break; + case TokenType.syntheticRebase: + result[chain] = { + mailbox, + type, + owner, + isNft, + collateralChainName: '', // This will be derived correctly by zod.parse() below + interchainSecurityModule, + }; + typeChoices = restrictChoices([ + TokenType.syntheticRebase, + TokenType.collateralVaultRebase, + ]); + break; + case TokenType.collateralVaultRebase: + result[chain] = { + mailbox, + type, + owner, + isNft, + interchainSecurityModule, + token: await input({ + message: `Enter the ERC-4626 vault address on chain ${chain}`, + }), + }; + + typeChoices = restrictChoices([TokenType.syntheticRebase]); + break; case TokenType.collateralVault: result[chain] = { mailbox, @@ -229,6 +261,10 @@ export async function createWarpRouteDeployConfig({ } } +function restrictChoices(typeChoices: TokenType[]) { + return TYPE_CHOICES.filter((choice) => typeChoices.includes(choice.name)); +} + // Note, this is different than the function above which reads a config // for a DEPLOYMENT. This gets a config for using a warp route (aka WarpCoreConfig) export function readWarpCoreConfig(filePath: string): WarpCoreConfig { diff --git a/typescript/cli/src/send/transfer.ts b/typescript/cli/src/send/transfer.ts index a2f56ef29..a89eb6aa9 100644 --- a/typescript/cli/src/send/transfer.ts +++ b/typescript/cli/src/send/transfer.ts @@ -23,6 +23,10 @@ import { indentYamlOrJson } from '../utils/files.js'; import { stubMerkleTreeConfig } from '../utils/relay.js'; import { runTokenSelectionStep } from '../utils/tokens.js'; +export const WarpSendLogs = { + SUCCESS: 'Transfer was self-relayed!', +}; + export async function sendTestTransfer({ context, warpCoreConfig, @@ -183,7 +187,7 @@ async function executeDelivery({ log('Attempting self-relay of transfer...'); await relayer.relayMessage(transferTxReceipt, messageIndex, message); - logGreen('Transfer was self-relayed!'); + logGreen(WarpSendLogs.SUCCESS); return; } diff --git a/typescript/cli/src/tests/commands/helpers.ts b/typescript/cli/src/tests/commands/helpers.ts index 2d2be7a6e..c4ad03651 100644 --- a/typescript/cli/src/tests/commands/helpers.ts +++ b/typescript/cli/src/tests/commands/helpers.ts @@ -1,3 +1,4 @@ +import { ERC20Test__factory, ERC4626Test__factory } from '@hyperlane-xyz/core'; import { ChainAddresses } from '@hyperlane-xyz/registry'; import { TokenRouterConfig, @@ -10,7 +11,11 @@ import { getContext } from '../../context/context.js'; import { readYamlOrJson, writeYamlOrJson } from '../../utils/files.js'; import { hyperlaneCoreDeploy } from './core.js'; -import { hyperlaneWarpApply, readWarpConfig } from './warp.js'; +import { + hyperlaneWarpApply, + hyperlaneWarpSendRelay, + readWarpConfig, +} from './warp.js'; export const TEST_CONFIGS_PATH = './test-configs'; export const REGISTRY_PATH = `${TEST_CONFIGS_PATH}/anvil`; @@ -123,3 +128,54 @@ export async function getChainId(chainName: string, key: string) { const chainMetadata = await registry.getChainMetadata(chainName); return String(chainMetadata?.chainId); } + +export async function deployToken(privateKey: string, chain: string) { + const { multiProvider } = await getContext({ + registryUri: REGISTRY_PATH, + registryOverrideUri: '', + key: privateKey, + }); + + const token = await new ERC20Test__factory( + multiProvider.getSigner(chain), + ).deploy('token', 'token', '100000000000000000000', 18); + await token.deployed(); + + return token; +} + +export async function deploy4626Vault( + privateKey: string, + chain: string, + tokenAddress: string, +) { + const { multiProvider } = await getContext({ + registryUri: REGISTRY_PATH, + registryOverrideUri: '', + key: privateKey, + }); + + const vault = await new ERC4626Test__factory( + multiProvider.getSigner(chain), + ).deploy(tokenAddress, 'VAULT', 'VAULT'); + await vault.deployed(); + + return vault; +} + +/** + * Performs a round-trip warp relay between two chains using the specified warp core config. + * + * @param chain1 - The first chain to send the warp relay from. + * @param chain2 - The second chain to send the warp relay to and back from. + * @param warpCoreConfigPath - The path to the warp core config file. + * @returns A promise that resolves when the round-trip warp relay is complete. + */ +export async function sendWarpRouteMessageRoundTrip( + chain1: string, + chain2: string, + warpCoreConfigPath: string, +) { + await hyperlaneWarpSendRelay(chain1, chain2, warpCoreConfigPath); + return hyperlaneWarpSendRelay(chain2, chain1, warpCoreConfigPath); +} diff --git a/typescript/cli/src/tests/commands/warp.ts b/typescript/cli/src/tests/commands/warp.ts index 16b8acbfe..3f3eec338 100644 --- a/typescript/cli/src/tests/commands/warp.ts +++ b/typescript/cli/src/tests/commands/warp.ts @@ -12,8 +12,10 @@ $.verbose = true; * Deploys the Warp route to the specified chain using the provided config. */ export async function hyperlaneWarpDeploy(warpCorePath: string) { + // --overrides is " " to allow local testing to work return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp deploy \ --registry ${REGISTRY_PATH} \ + --overrides " " \ --config ${warpCorePath} \ --key ${ANVIL_KEY} \ --verbosity debug \ @@ -30,6 +32,7 @@ export async function hyperlaneWarpApply( ) { return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp apply \ --registry ${REGISTRY_PATH} \ + --overrides " " \ --config ${warpDeployPath} \ --warp ${warpCorePath} \ --key ${ANVIL_KEY} \ @@ -45,6 +48,7 @@ export async function hyperlaneWarpRead( ) { return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp read \ --registry ${REGISTRY_PATH} \ + --overrides " " \ --address ${warpAddress} \ --chain ${chain} \ --key ${ANVIL_KEY} \ @@ -52,6 +56,23 @@ export async function hyperlaneWarpRead( --config ${warpDeployPath}`; } +export async function hyperlaneWarpSendRelay( + origin: string, + destination: string, + warpCorePath: string, +) { + return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp send \ + --relay \ + --registry ${REGISTRY_PATH} \ + --overrides " " \ + --origin ${origin} \ + --destination ${destination} \ + --warp ${warpCorePath} \ + --key ${ANVIL_KEY} \ + --verbosity debug \ + --yes`; +} + /** * Reads the Warp route deployment config to specified output path. * @param warpCorePath path to warp core diff --git a/typescript/cli/src/tests/warp-apply.e2e-test.ts b/typescript/cli/src/tests/warp-apply.e2e-test.ts index 7b0c20d91..2346038d6 100644 --- a/typescript/cli/src/tests/warp-apply.e2e-test.ts +++ b/typescript/cli/src/tests/warp-apply.e2e-test.ts @@ -36,7 +36,7 @@ const TEMP_PATH = '/tmp'; // /temp gets removed at the end of all-test.sh const WARP_CONFIG_PATH_2 = `${TEMP_PATH}/anvil2/warp-route-deployment-anvil2.yaml`; const WARP_CORE_CONFIG_PATH_2 = `${REGISTRY_PATH}/deployments/warp_routes/ETH/anvil2-config.yaml`; -const TEST_TIMEOUT = 60_000; // Long timeout since these tests can take a while +const TEST_TIMEOUT = 100_000; // Long timeout since these tests can take a while describe('WarpApply e2e tests', async function () { let chain2Addresses: ChainAddresses = {}; this.timeout(TEST_TIMEOUT); diff --git a/typescript/cli/src/tests/warp-deploy.e2e-test.ts b/typescript/cli/src/tests/warp-deploy.e2e-test.ts new file mode 100644 index 000000000..6263f70cb --- /dev/null +++ b/typescript/cli/src/tests/warp-deploy.e2e-test.ts @@ -0,0 +1,114 @@ +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import { ChainAddresses } from '@hyperlane-xyz/registry'; +import { TokenType, WarpRouteDeployConfig } from '@hyperlane-xyz/sdk'; + +import { WarpSendLogs } from '../send/transfer.js'; +import { writeYamlOrJson } from '../utils/files.js'; + +import { + ANVIL_KEY, + REGISTRY_PATH, + deploy4626Vault, + deployOrUseExistingCore, + deployToken, + sendWarpRouteMessageRoundTrip, +} from './commands/helpers.js'; +import { hyperlaneWarpDeploy, readWarpConfig } from './commands/warp.js'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +chai.should(); + +const CHAIN_NAME_2 = 'anvil2'; +const CHAIN_NAME_3 = 'anvil3'; + +const EXAMPLES_PATH = './examples'; +const TEMP_PATH = '/tmp'; // /temp gets removed at the end of all-test.sh + +const CORE_CONFIG_PATH = `${EXAMPLES_PATH}/core-config.yaml`; +const WARP_CONFIG_PATH = `${TEMP_PATH}/warp-route-deployment-deploy.yaml`; +const WARP_CORE_CONFIG_PATH_2_3 = `${REGISTRY_PATH}/deployments/warp_routes/VAULT/anvil2-anvil3-config.yaml`; + +const TEST_TIMEOUT = 60_000; // Long timeout since these tests can take a while +describe('WarpDeploy e2e tests', async function () { + let chain2Addresses: ChainAddresses = {}; + let token: any; + let vault: any; + + this.timeout(TEST_TIMEOUT); + + before(async function () { + chain2Addresses = await deployOrUseExistingCore( + CHAIN_NAME_2, + CORE_CONFIG_PATH, + ANVIL_KEY, + ); + + await deployOrUseExistingCore(CHAIN_NAME_3, CORE_CONFIG_PATH, ANVIL_KEY); + + token = await deployToken(ANVIL_KEY, CHAIN_NAME_2); + vault = await deploy4626Vault(ANVIL_KEY, CHAIN_NAME_2, token.address); + }); + + it('should only allow rebasing yield route to be deployed with rebasing synthetic', async function () { + const warpConfig: WarpRouteDeployConfig = { + [CHAIN_NAME_2]: { + type: TokenType.collateralVaultRebase, + token: vault.address, + mailbox: chain2Addresses.mailbox, + owner: chain2Addresses.mailbox, + }, + [CHAIN_NAME_3]: { + type: TokenType.synthetic, + mailbox: chain2Addresses.mailbox, + owner: chain2Addresses.mailbox, + }, + }; + + writeYamlOrJson(WARP_CONFIG_PATH, warpConfig); + await hyperlaneWarpDeploy(WARP_CONFIG_PATH).should.be.rejected; // TODO: revisit this to figure out how to parse the error. + }); + + it(`should be able to bridge between ${TokenType.collateralVaultRebase} and ${TokenType.syntheticRebase}`, async function () { + const warpConfig: WarpRouteDeployConfig = { + [CHAIN_NAME_2]: { + type: TokenType.collateralVaultRebase, + token: vault.address, + mailbox: chain2Addresses.mailbox, + owner: chain2Addresses.mailbox, + }, + [CHAIN_NAME_3]: { + type: TokenType.syntheticRebase, + mailbox: chain2Addresses.mailbox, + owner: chain2Addresses.mailbox, + collateralChainName: CHAIN_NAME_2, + }, + }; + + writeYamlOrJson(WARP_CONFIG_PATH, warpConfig); + await hyperlaneWarpDeploy(WARP_CONFIG_PATH); + + // Check collateralRebase + const collateralRebaseConfig = ( + await readWarpConfig( + CHAIN_NAME_2, + WARP_CORE_CONFIG_PATH_2_3, + WARP_CONFIG_PATH, + ) + )[CHAIN_NAME_2]; + + expect(collateralRebaseConfig.type).to.equal( + TokenType.collateralVaultRebase, + ); + + // Try to send a transaction + const { stdout } = await sendWarpRouteMessageRoundTrip( + CHAIN_NAME_2, + CHAIN_NAME_3, + WARP_CORE_CONFIG_PATH_2_3, + ); + expect(stdout).to.include(WarpSendLogs.SUCCESS); + }); +}); diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index ee54c0409..e80ad1f3e 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -512,9 +512,11 @@ export { NativeConfig, TokenRouterConfigSchema, WarpRouteDeployConfigSchema, + WarpRouteDeployConfigSchemaErrors, isCollateralConfig, isNativeConfig, isSyntheticConfig, + isSyntheticRebaseConfig, isTokenMetadata, } from './token/schemas.js'; export { isCompliant } from './utils/schemas.js'; diff --git a/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts b/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts index 6db166c5b..467a150ad 100644 --- a/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts +++ b/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts @@ -111,7 +111,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => { }); it('should create with a collateral config', async () => { - const config = { + const config: TokenRouterConfig = { ...baseConfig, type: TokenType.collateral, token: token.address, @@ -139,7 +139,7 @@ describe('EvmERC20WarpHyperlaneModule', async () => { TOKEN_NAME, TOKEN_NAME, ); - const config = { + const config: TokenRouterConfig = { type: TokenType.collateralVault, token: vault.address, hook: hookAddress, @@ -172,9 +172,8 @@ describe('EvmERC20WarpHyperlaneModule', async () => { }); it('should create with a synthetic config', async () => { - const config = { + const config: TokenRouterConfig = { type: TokenType.synthetic, - token: token.address, hook: hookAddress, name: TOKEN_NAME, symbol: TOKEN_NAME, diff --git a/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts b/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts index f086f3b83..c6795fc6c 100644 --- a/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts +++ b/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts @@ -14,14 +14,16 @@ import { HyperlaneContractsMap, RouterConfig, TestChainName, - TokenRouterConfig, + WarpRouteDeployConfig, test3, } from '@hyperlane-xyz/sdk'; +import { assert } from '@hyperlane-xyz/utils'; import { TestCoreApp } from '../core/TestCoreApp.js'; import { TestCoreDeployer } from '../core/TestCoreDeployer.js'; import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js'; import { ProxyFactoryFactories } from '../deploy/contracts.js'; +import { DerivedIsmConfig } from '../ism/EvmIsmReader.js'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { ChainMap } from '../types.js'; @@ -122,12 +124,12 @@ describe('ERC20WarpRouterReader', async () => { it('should derive collateral config correctly', async () => { // Create config - const config = { + const config: WarpRouteDeployConfig = { [chain]: { type: TokenType.collateral, token: token.address, hook: await mailbox.defaultHook(), - interchainsecurityModule: await mailbox.defaultIsm(), + interchainSecurityModule: await mailbox.defaultIsm(), ...baseConfig, }, }; @@ -150,8 +152,10 @@ describe('ERC20WarpRouterReader', async () => { config[chain].hook as string, ), ); - // Check ism. should return undefined - expect(derivedConfig.interchainSecurityModule).to.be.undefined; + // Check ism + expect( + (derivedConfig.interchainSecurityModule as DerivedIsmConfig).address, + ).to.be.equal(await mailbox.defaultIsm()); // Check if token values matches if (derivedConfig.type === TokenType.collateral) { @@ -160,13 +164,45 @@ describe('ERC20WarpRouterReader', async () => { expect(derivedConfig.decimals).to.equal(TOKEN_DECIMALS); } }); + it('should derive synthetic rebase config correctly', async () => { + // Create config + const config: WarpRouteDeployConfig = { + [chain]: { + type: TokenType.syntheticRebase, + collateralChainName: TestChainName.test4, + hook: await mailbox.defaultHook(), + name: TOKEN_NAME, + symbol: TOKEN_NAME, + decimals: TOKEN_DECIMALS, + totalSupply: TOKEN_SUPPLY, + ...baseConfig, + }, + }; + // Deploy with config + const warpRoute = await deployer.deploy(config); + + // Derive config and check if each value matches + const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig( + warpRoute[chain].syntheticRebase.address, + ); + for (const [key, value] of Object.entries(derivedConfig)) { + const deployedValue = (config[chain] as any)[key]; + if (deployedValue && typeof value === 'string') + expect(deployedValue).to.equal(value); + } + + // Check if token values matches + if (derivedConfig.type === TokenType.collateral) { + expect(derivedConfig.name).to.equal(TOKEN_NAME); + expect(derivedConfig.symbol).to.equal(TOKEN_NAME); + } + }); it('should derive synthetic config correctly', async () => { // Create config - const config = { + const config: WarpRouteDeployConfig = { [chain]: { type: TokenType.synthetic, - token: token.address, hook: await mailbox.defaultHook(), name: TOKEN_NAME, symbol: TOKEN_NAME, @@ -197,13 +233,13 @@ describe('ERC20WarpRouterReader', async () => { it('should derive native config correctly', async () => { // Create config - const config = { + const config: WarpRouteDeployConfig = { [chain]: { type: TokenType.native, hook: await mailbox.defaultHook(), ...baseConfig, }, - } as ChainMap; + }; // Deploy with config const warpRoute = await deployer.deploy(config); @@ -221,9 +257,61 @@ describe('ERC20WarpRouterReader', async () => { expect(derivedConfig.decimals).to.equal(TOKEN_DECIMALS); }); + it('should derive collateral vault config correctly', async () => { + // Create config + const config: WarpRouteDeployConfig = { + [chain]: { + type: TokenType.collateralVault, + token: vault.address, + ...baseConfig, + }, + }; + // Deploy with config + const warpRoute = await deployer.deploy(config); + // Derive config and check if each value matches + const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig( + warpRoute[chain].collateralVault.address, + ); + + assert( + derivedConfig.type === TokenType.collateralVault, + 'Must be collateralVault', + ); + expect(derivedConfig.type).to.equal(config[chain].type); + expect(derivedConfig.mailbox).to.equal(config[chain].mailbox); + expect(derivedConfig.owner).to.equal(config[chain].owner); + expect(derivedConfig.token).to.equal(token.address); + }); + + it('should derive rebase collateral vault config correctly', async () => { + // Create config + const config: WarpRouteDeployConfig = { + [chain]: { + type: TokenType.collateralVaultRebase, + token: vault.address, + ...baseConfig, + }, + }; + // Deploy with config + const warpRoute = await deployer.deploy(config); + // Derive config and check if each value matches + const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig( + warpRoute[chain].collateralVaultRebase.address, + ); + + assert( + derivedConfig.type === TokenType.collateralVaultRebase, + 'Must be collateralVaultRebase', + ); + expect(derivedConfig.type).to.equal(config[chain].type); + expect(derivedConfig.mailbox).to.equal(config[chain].mailbox); + expect(derivedConfig.owner).to.equal(config[chain].owner); + expect(derivedConfig.token).to.equal(token.address); + }); + it('should return undefined if ism is not set onchain', async () => { // Create config - const config = { + const config: WarpRouteDeployConfig = { [chain]: { type: TokenType.collateral, token: token.address, @@ -246,7 +334,7 @@ describe('ERC20WarpRouterReader', async () => { // Create config const otherChain = TestChainName.test3; const otherChainMetadata = test3; - const config = { + const config: WarpRouteDeployConfig = { [chain]: { type: TokenType.collateral, token: token.address, diff --git a/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts b/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts index 2eb3838d5..8ffbe82cc 100644 --- a/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts +++ b/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts @@ -4,6 +4,8 @@ import { HypERC20Collateral__factory, HypERC20__factory, HypERC4626Collateral__factory, + HypERC4626OwnerCollateral__factory, + HypERC4626__factory, TokenRouter__factory, } from '@hyperlane-xyz/core'; import { @@ -81,15 +83,23 @@ export class EvmERC20WarpRouteReader extends HyperlaneReader { const contractTypes: Partial< Record > = { - collateralVault: { + [TokenType.collateralVaultRebase]: { factory: HypERC4626Collateral__factory, + method: 'NULL_RECIPIENT', + }, + [TokenType.collateralVault]: { + factory: HypERC4626OwnerCollateral__factory, method: 'vault', }, - collateral: { + [TokenType.collateral]: { factory: HypERC20Collateral__factory, method: 'wrappedToken', }, - synthetic: { + [TokenType.syntheticRebase]: { + factory: HypERC4626__factory, + method: 'collateralDomain', + }, + [TokenType.synthetic]: { factory: HypERC20__factory, method: 'decimals', }, @@ -106,11 +116,11 @@ export class EvmERC20WarpRouteReader extends HyperlaneReader { try { const warpRoute = factory.connect(warpRouteAddress, this.provider); await warpRoute[method](); - - this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger return tokenType as TokenType; } catch (e) { continue; + } finally { + this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger } } @@ -186,7 +196,10 @@ export class EvmERC20WarpRouteReader extends HyperlaneReader { await this.fetchERC20Metadata(token); return { name, symbol, decimals, totalSupply, token }; - } else if (type === TokenType.synthetic) { + } else if ( + type === TokenType.synthetic || + type === TokenType.syntheticRebase + ) { return this.fetchERC20Metadata(tokenAddress); } else if (type === TokenType.native) { const chainMetadata = this.multiProvider.getChainMetadata(this.chain); diff --git a/typescript/sdk/src/token/Token.test.ts b/typescript/sdk/src/token/Token.test.ts index cd232ebf7..1a6ac978a 100644 --- a/typescript/sdk/src/token/Token.test.ts +++ b/typescript/sdk/src/token/Token.test.ts @@ -48,6 +48,15 @@ const STANDARD_TO_TOKEN: Record = { symbol: 'USDC', name: 'USDC', }, + [TokenStandard.EvmHypRebaseCollateral]: { + chainName: TestChainName.test3, + standard: TokenStandard.EvmHypRebaseCollateral, + addressOrDenom: '0x31b5234A896FbC4b3e2F7237592D054716762131', + collateralAddressOrDenom: '0x64544969ed7ebf5f083679233325356ebe738930', + decimals: 18, + symbol: 'USDC', + name: 'USDC', + }, [TokenStandard.EvmHypOwnerCollateral]: { chainName: TestChainName.test3, standard: TokenStandard.EvmHypOwnerCollateral, @@ -74,6 +83,14 @@ const STANDARD_TO_TOKEN: Record = { symbol: 'USDC', name: 'USDC', }, + [TokenStandard.EvmHypSyntheticRebase]: { + chainName: TestChainName.test2, + standard: TokenStandard.EvmHypSyntheticRebase, + addressOrDenom: '0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147', + decimals: 6, + symbol: 'USDC', + name: 'USDC', + }, [TokenStandard.EvmHypXERC20]: { chainName: TestChainName.test2, standard: TokenStandard.EvmHypXERC20, diff --git a/typescript/sdk/src/token/Token.ts b/typescript/sdk/src/token/Token.ts index e2541db6b..527adc2b5 100644 --- a/typescript/sdk/src/token/Token.ts +++ b/typescript/sdk/src/token/Token.ts @@ -189,19 +189,19 @@ export class Token implements IToken { return new EvmHypNativeAdapter(chainName, multiProvider, { token: addressOrDenom, }); - } else if (standard === TokenStandard.EvmHypCollateral) { - return new EvmHypCollateralAdapter(chainName, multiProvider, { - token: addressOrDenom, - }); - } else if (standard === TokenStandard.EvmHypCollateralFiat) { - return new EvmHypCollateralAdapter(chainName, multiProvider, { - token: addressOrDenom, - }); - } else if (standard === TokenStandard.EvmHypOwnerCollateral) { + } else if ( + standard === TokenStandard.EvmHypCollateral || + standard === TokenStandard.EvmHypCollateralFiat || + standard === TokenStandard.EvmHypOwnerCollateral || + standard === TokenStandard.EvmHypRebaseCollateral + ) { return new EvmHypCollateralAdapter(chainName, multiProvider, { token: addressOrDenom, }); - } else if (standard === TokenStandard.EvmHypSynthetic) { + } else if ( + standard === TokenStandard.EvmHypSynthetic || + standard === TokenStandard.EvmHypSyntheticRebase + ) { return new EvmHypSyntheticAdapter(chainName, multiProvider, { token: addressOrDenom, }); diff --git a/typescript/sdk/src/token/TokenStandard.ts b/typescript/sdk/src/token/TokenStandard.ts index 002501d32..ee434b777 100644 --- a/typescript/sdk/src/token/TokenStandard.ts +++ b/typescript/sdk/src/token/TokenStandard.ts @@ -15,8 +15,10 @@ export enum TokenStandard { EvmHypNative = 'EvmHypNative', EvmHypCollateral = 'EvmHypCollateral', EvmHypOwnerCollateral = 'EvmHypOwnerCollateral', + EvmHypRebaseCollateral = 'EvmHypRebaseCollateral', EvmHypCollateralFiat = 'EvmHypCollateralFiat', EvmHypSynthetic = 'EvmHypSynthetic', + EvmHypSyntheticRebase = 'EvmHypSyntheticRebase', EvmHypXERC20 = 'EvmHypXERC20', EvmHypXERC20Lockbox = 'EvmHypXERC20Lockbox', @@ -52,8 +54,10 @@ export const TOKEN_STANDARD_TO_PROTOCOL: Record = { EvmHypNative: ProtocolType.Ethereum, EvmHypCollateral: ProtocolType.Ethereum, EvmHypOwnerCollateral: ProtocolType.Ethereum, + EvmHypRebaseCollateral: ProtocolType.Ethereum, EvmHypCollateralFiat: ProtocolType.Ethereum, EvmHypSynthetic: ProtocolType.Ethereum, + EvmHypSyntheticRebase: ProtocolType.Ethereum, EvmHypXERC20: ProtocolType.Ethereum, EvmHypXERC20Lockbox: ProtocolType.Ethereum, @@ -114,7 +118,9 @@ export const TOKEN_HYP_STANDARDS = [ TokenStandard.EvmHypCollateral, TokenStandard.EvmHypCollateralFiat, TokenStandard.EvmHypOwnerCollateral, + TokenStandard.EvmHypRebaseCollateral, TokenStandard.EvmHypSynthetic, + TokenStandard.EvmHypSyntheticRebase, TokenStandard.EvmHypXERC20, TokenStandard.EvmHypXERC20Lockbox, TokenStandard.SealevelHypNative, @@ -148,9 +154,11 @@ export const TOKEN_TYPE_TO_STANDARD: Record = { [TokenType.XERC20]: TokenStandard.EvmHypXERC20, [TokenType.XERC20Lockbox]: TokenStandard.EvmHypXERC20Lockbox, [TokenType.collateralVault]: TokenStandard.EvmHypOwnerCollateral, + [TokenType.collateralVaultRebase]: TokenStandard.EvmHypRebaseCollateral, [TokenType.collateralUri]: TokenStandard.EvmHypCollateral, [TokenType.fastCollateral]: TokenStandard.EvmHypCollateral, [TokenType.synthetic]: TokenStandard.EvmHypSynthetic, + [TokenType.syntheticRebase]: TokenStandard.EvmHypSyntheticRebase, [TokenType.syntheticUri]: TokenStandard.EvmHypSynthetic, [TokenType.fastSynthetic]: TokenStandard.EvmHypSynthetic, [TokenType.nativeScaled]: TokenStandard.EvmHypNative, diff --git a/typescript/sdk/src/token/config.ts b/typescript/sdk/src/token/config.ts index a89264ee6..08fb750f2 100644 --- a/typescript/sdk/src/token/config.ts +++ b/typescript/sdk/src/token/config.ts @@ -1,9 +1,11 @@ export enum TokenType { synthetic = 'synthetic', + syntheticRebase = 'syntheticRebase', fastSynthetic = 'fastSynthetic', syntheticUri = 'syntheticUri', collateral = 'collateral', collateralVault = 'collateralVault', + collateralVaultRebase = 'collateralVaultRebase', XERC20 = 'xERC20', XERC20Lockbox = 'xERC20Lockbox', collateralFiat = 'collateralFiat', @@ -16,6 +18,7 @@ export enum TokenType { export const CollateralExtensions = [ TokenType.collateral, TokenType.collateralVault, + TokenType.collateralVaultRebase, ]; export const gasOverhead = (tokenType: TokenType): number => { diff --git a/typescript/sdk/src/token/contracts.ts b/typescript/sdk/src/token/contracts.ts index 281c084ff..a9ced3cb1 100644 --- a/typescript/sdk/src/token/contracts.ts +++ b/typescript/sdk/src/token/contracts.ts @@ -8,6 +8,8 @@ import { HypERC721URIStorage__factory, HypERC721__factory, HypERC4626Collateral__factory, + HypERC4626OwnerCollateral__factory, + HypERC4626__factory, HypFiatToken__factory, HypNativeScaled__factory, HypNative__factory, @@ -21,11 +23,13 @@ export const hypERC20contracts = { [TokenType.fastCollateral]: 'FastHypERC20Collateral', [TokenType.fastSynthetic]: 'FastHypERC20', [TokenType.synthetic]: 'HypERC20', + [TokenType.syntheticRebase]: 'HypERC4626', [TokenType.collateral]: 'HypERC20Collateral', [TokenType.collateralFiat]: 'HypFiatToken', [TokenType.XERC20]: 'HypXERC20', [TokenType.XERC20Lockbox]: 'HypXERC20Lockbox', - [TokenType.collateralVault]: 'HypERC20CollateralVaultDeposit', + [TokenType.collateralVault]: 'HypERC4626OwnerCollateral', + [TokenType.collateralVaultRebase]: 'HypERC4626Collateral', [TokenType.native]: 'HypNative', [TokenType.nativeScaled]: 'HypNativeScaled', }; @@ -36,7 +40,9 @@ export const hypERC20factories = { [TokenType.fastSynthetic]: new FastHypERC20__factory(), [TokenType.synthetic]: new HypERC20__factory(), [TokenType.collateral]: new HypERC20Collateral__factory(), - [TokenType.collateralVault]: new HypERC4626Collateral__factory(), + [TokenType.collateralVault]: new HypERC4626OwnerCollateral__factory(), + [TokenType.collateralVaultRebase]: new HypERC4626Collateral__factory(), + [TokenType.syntheticRebase]: new HypERC4626__factory(), [TokenType.collateralFiat]: new HypFiatToken__factory(), [TokenType.XERC20]: new HypXERC20__factory(), [TokenType.XERC20Lockbox]: new HypXERC20Lockbox__factory(), diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index 843f933f1..ee2a9a399 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -33,6 +33,7 @@ import { isCollateralConfig, isNativeConfig, isSyntheticConfig, + isSyntheticRebaseConfig, isTokenMetadata, } from './schemas.js'; import { TokenMetadata, WarpRouteDeployConfig } from './types.js'; @@ -64,6 +65,11 @@ abstract class TokenDeployer< } else if (isSyntheticConfig(config)) { assert(config.decimals, 'decimals is undefined for config'); // decimals must be defined by this point return [config.decimals, config.mailbox]; + } else if (isSyntheticRebaseConfig(config)) { + const collateralDomain = this.multiProvider.getDomainId( + config.collateralChainName, + ); + return [config.decimals, config.mailbox, collateralDomain]; } else { throw new Error('Unknown token type when constructing arguments'); } @@ -82,7 +88,7 @@ abstract class TokenDeployer< ]; if (isCollateralConfig(config) || isNativeConfig(config)) { return defaultArgs; - } else if (isSyntheticConfig(config)) { + } else if (isSyntheticConfig(config) || isSyntheticRebaseConfig(config)) { return [config.totalSupply, config.name, config.symbol, ...defaultArgs]; } else { throw new Error('Unknown collateral type when initializing arguments'); diff --git a/typescript/sdk/src/token/schemas.test.ts b/typescript/sdk/src/token/schemas.test.ts index 65f780cd0..1a8d606ea 100644 --- a/typescript/sdk/src/token/schemas.test.ts +++ b/typescript/sdk/src/token/schemas.test.ts @@ -1,8 +1,15 @@ import { expect } from 'chai'; import { ethers } from 'ethers'; +import { assert } from '@hyperlane-xyz/utils'; + import { TokenType } from './config.js'; -import { WarpRouteDeployConfigSchema } from './schemas.js'; +import { + WarpRouteDeployConfigSchema, + WarpRouteDeployConfigSchemaErrors, + isCollateralConfig, +} from './schemas.js'; +import { WarpRouteDeployConfig } from './types.js'; const SOME_ADDRESS = ethers.Wallet.createRandom().address; const COLLATERAL_TYPES = [ @@ -19,7 +26,7 @@ const NON_COLLATERAL_TYPES = [ ]; describe('WarpRouteDeployConfigSchema refine', () => { - let config: any; + let config: WarpRouteDeployConfig; beforeEach(() => { config = { arbitrum: { @@ -33,18 +40,24 @@ describe('WarpRouteDeployConfigSchema refine', () => { it('should require token type', () => { expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.true; + + //@ts-ignore delete config.arbitrum.type; expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.false; }); it('should require token address', () => { expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.true; + + //@ts-ignore delete config.arbitrum.token; expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.false; }); it('should require mailbox address', () => { expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.true; + + //@ts-ignore delete config.arbitrum.mailbox; expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.false; }); @@ -52,6 +65,9 @@ describe('WarpRouteDeployConfigSchema refine', () => { it('should throw if collateral type and token is empty', async () => { for (const type of COLLATERAL_TYPES) { config.arbitrum.type = type; + assert(isCollateralConfig(config.arbitrum), 'must be collateral'); + + //@ts-ignore config.arbitrum.token = undefined; expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.false; @@ -61,13 +77,8 @@ describe('WarpRouteDeployConfigSchema refine', () => { } }); - it('should accept native type if token is empty', async () => { - config.arbitrum.type = TokenType.native; - config.arbitrum.token = undefined; - expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.true; - }); - it('should succeed if non-collateral type, token is empty, metadata is defined', async () => { + //@ts-ignore delete config.arbitrum.token; config.arbitrum.totalSupply = '0'; config.arbitrum.name = 'name'; @@ -81,4 +92,93 @@ describe('WarpRouteDeployConfigSchema refine', () => { expect(WarpRouteDeployConfigSchema.safeParse(config).success).to.be.true; } }); + + it(`should throw if deploying rebasing collateral with anything other than ${TokenType.syntheticRebase}`, async () => { + config = { + arbitrum: { + type: TokenType.collateralVaultRebase, + token: SOME_ADDRESS, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + }, + ethereum: { + type: TokenType.collateralVault, + token: SOME_ADDRESS, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + }, + optimism: { + type: TokenType.syntheticRebase, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + collateralChainName: '', + }, + }; + let parseResults = WarpRouteDeployConfigSchema.safeParse(config); + assert(!parseResults.success, 'must be false'); // Needed so 'message' shows up because parseResults is a discriminate union + expect(parseResults.error.issues[0].message).to.equal( + WarpRouteDeployConfigSchemaErrors.ONLY_SYNTHETIC_REBASE, + ); + + config.ethereum.type = TokenType.syntheticRebase; + //@ts-ignore + config.ethereum.collateralChainName = ''; + parseResults = WarpRouteDeployConfigSchema.safeParse(config); + //@ts-ignore + expect(parseResults.success).to.be.true; + }); + + it(`should throw if deploying only ${TokenType.collateralVaultRebase}`, async () => { + config = { + arbitrum: { + type: TokenType.collateralVaultRebase, + token: SOME_ADDRESS, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + }, + }; + let parseResults = WarpRouteDeployConfigSchema.safeParse(config); + expect(parseResults.success).to.be.false; + + config.ethereum = { + type: TokenType.collateralVaultRebase, + token: SOME_ADDRESS, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + }; + parseResults = WarpRouteDeployConfigSchema.safeParse(config); + expect(parseResults.success).to.be.false; + }); + + it(`should derive the collateral chain name for ${TokenType.syntheticRebase}`, async () => { + config = { + arbitrum: { + type: TokenType.collateralVaultRebase, + token: SOME_ADDRESS, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + }, + ethereum: { + type: TokenType.syntheticRebase, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + collateralChainName: '', + }, + optimism: { + type: TokenType.syntheticRebase, + owner: SOME_ADDRESS, + mailbox: SOME_ADDRESS, + collateralChainName: '', + }, + }; + const parseResults = WarpRouteDeployConfigSchema.safeParse(config); + assert(parseResults.success, 'must be true'); + const warpConfig: WarpRouteDeployConfig = parseResults.data; + + assert( + warpConfig.optimism.type === TokenType.syntheticRebase, + 'must be syntheticRebase', + ); + expect(warpConfig.optimism.collateralChainName).to.equal('arbitrum'); + }); }); diff --git a/typescript/sdk/src/token/schemas.ts b/typescript/sdk/src/token/schemas.ts index 8ce070c1e..1ef4a770b 100644 --- a/typescript/sdk/src/token/schemas.ts +++ b/typescript/sdk/src/token/schemas.ts @@ -1,10 +1,16 @@ import { z } from 'zod'; +import { objMap } from '@hyperlane-xyz/utils'; + import { GasRouterConfigSchema } from '../router/schemas.js'; import { isCompliant } from '../utils/schemas.js'; import { TokenType } from './config.js'; +export const WarpRouteDeployConfigSchemaErrors = { + ONLY_SYNTHETIC_REBASE: `Config with ${TokenType.collateralVaultRebase} must be deployed with ${TokenType.syntheticRebase}`, + NO_SYNTHETIC_ONLY: `Config must include Native or Collateral OR all synthetics must define token metadata`, +}; export const TokenMetadataSchema = z.object({ name: z.string(), symbol: z.string(), @@ -18,6 +24,7 @@ export const CollateralConfigSchema = TokenMetadataSchema.partial().extend({ type: z.enum([ TokenType.collateral, TokenType.collateralVault, + TokenType.collateralVaultRebase, TokenType.XERC20, TokenType.XERC20Lockbox, TokenType.collateralFiat, @@ -33,6 +40,18 @@ export const NativeConfigSchema = TokenMetadataSchema.partial().extend({ type: z.enum([TokenType.native, TokenType.nativeScaled]), }); +export const CollateralRebaseConfigSchema = + TokenMetadataSchema.partial().extend({ + type: z.literal(TokenType.collateralVaultRebase), + }); + +export const SyntheticRebaseConfigSchema = TokenMetadataSchema.partial().extend( + { + type: z.literal(TokenType.syntheticRebase), + collateralChainName: z.string(), + }, +); + export const SyntheticConfigSchema = TokenMetadataSchema.partial().extend({ type: z.enum([ TokenType.synthetic, @@ -50,6 +69,7 @@ export const TokenConfigSchema = z.discriminatedUnion('type', [ NativeConfigSchema, CollateralConfigSchema, SyntheticConfigSchema, + SyntheticRebaseConfigSchema, ]); export const TokenRouterConfigSchema = TokenConfigSchema.and( @@ -61,6 +81,10 @@ export type NativeConfig = z.infer; export type CollateralConfig = z.infer; export const isSyntheticConfig = isCompliant(SyntheticConfigSchema); +export const isSyntheticRebaseConfig = isCompliant(SyntheticRebaseConfigSchema); +export const isCollateralRebaseConfig = isCompliant( + CollateralRebaseConfigSchema, +); export const isCollateralConfig = isCompliant(CollateralConfigSchema); export const isNativeConfig = isCompliant(NativeConfigSchema); export const isTokenMetadata = isCompliant(TokenMetadataSchema); @@ -71,7 +95,49 @@ export const WarpRouteDeployConfigSchema = z const entries = Object.entries(configMap); return ( entries.some( - ([_, config]) => isCollateralConfig(config) || isNativeConfig(config), + ([_, config]) => + isCollateralConfig(config) || + isCollateralRebaseConfig(config) || + isNativeConfig(config), ) || entries.every(([_, config]) => isTokenMetadata(config)) ); - }, `Config must include Native or Collateral OR all synthetics must define token metadata`); + }, WarpRouteDeployConfigSchemaErrors.NO_SYNTHETIC_ONLY) + .transform((warpRouteDeployConfig, ctx) => { + const collateralRebaseEntry = Object.entries(warpRouteDeployConfig).find( + ([_, config]) => isCollateralRebaseConfig(config), + ); + if (!collateralRebaseEntry) return warpRouteDeployConfig; // Pass through for other token types + + if (isCollateralRebasePairedCorrectly(warpRouteDeployConfig)) { + const collateralChainName = collateralRebaseEntry[0]; + return objMap(warpRouteDeployConfig, (_, config) => { + if (config.type === TokenType.syntheticRebase) + config.collateralChainName = collateralChainName; + return config; + }) as Record; + } + + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: WarpRouteDeployConfigSchemaErrors.ONLY_SYNTHETIC_REBASE, + }); + + return z.NEVER; // Causes schema validation to throw with above issue + }); + +function isCollateralRebasePairedCorrectly( + warpRouteDeployConfig: Record, +): boolean { + // Filter out all the non-collateral rebase configs to check if they are only synthetic rebase tokens + const otherConfigs = Object.entries(warpRouteDeployConfig).filter( + ([_, config]) => !isCollateralRebaseConfig(config), + ); + + if (otherConfigs.length === 0) return false; + + // The other configs MUST be synthetic rebase + const allOthersSynthetic: boolean = otherConfigs.every( + ([_, config], _index) => isSyntheticRebaseConfig(config), + ); + return allOthersSynthetic; +} diff --git a/yarn.lock b/yarn.lock index bae817923..910c021e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7827,6 +7827,7 @@ __metadata: "@hyperlane-xyz/sdk": "npm:5.5.0" "@hyperlane-xyz/utils": "npm:5.5.0" "@inquirer/prompts": "npm:^3.0.0" + "@types/chai-as-promised": "npm:^8" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:^18.14.5" "@types/yargs": "npm:^17.0.24" @@ -7834,7 +7835,8 @@ __metadata: "@typescript-eslint/parser": "npm:^7.4.0" asn1.js: "npm:^5.4.1" bignumber.js: "npm:^9.1.1" - chai: "npm:4.5.0" + chai: "npm:^4.5.0" + chai-as-promised: "npm:^8.0.0" chalk: "npm:^5.3.0" eslint: "npm:^8.57.0" eslint-config-prettier: "npm:^9.1.0" @@ -13119,6 +13121,15 @@ __metadata: languageName: node linkType: hard +"@types/chai-as-promised@npm:^8": + version: 8.0.0 + resolution: "@types/chai-as-promised@npm:8.0.0" + dependencies: + "@types/chai": "npm:*" + checksum: f6db5698e4f28fd6e3914740810f356269b7f4e93a0650b38a9b01a1bae030593487c80bc57a0e69dd0bfb069a61d3dd285bfcfba6d1daf66ef3939577b68169 + languageName: node + linkType: hard + "@types/chai@npm:*, @types/chai@npm:^4.2.21": version: 4.3.1 resolution: "@types/chai@npm:4.3.1" @@ -16218,7 +16229,18 @@ __metadata: languageName: node linkType: hard -"chai@npm:4.5.0, chai@npm:^4.3.10, chai@npm:^4.3.7": +"chai-as-promised@npm:^8.0.0": + version: 8.0.0 + resolution: "chai-as-promised@npm:8.0.0" + dependencies: + check-error: "npm:^2.0.0" + peerDependencies: + chai: ">= 2.1.2 < 6" + checksum: 91d6a49caac7965440b8f8af421ebe6f060a3b5523599ae143816d08fc19d9a971ea2bc5401f82ce88d15d8bc7b64d356bf3e53542ace9e2f25cc454164d3247 + languageName: node + linkType: hard + +"chai@npm:4.5.0, chai@npm:^4.3.10, chai@npm:^4.3.7, chai@npm:^4.5.0": version: 4.5.0 resolution: "chai@npm:4.5.0" dependencies: @@ -16338,6 +16360,13 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^2.0.0": + version: 2.1.1 + resolution: "check-error@npm:2.1.1" + checksum: d785ed17b1d4a4796b6e75c765a9a290098cf52ff9728ce0756e8ffd4293d2e419dd30c67200aee34202463b474306913f2fcfaf1890641026d9fc6966fea27a + languageName: node + linkType: hard + "chokidar@npm:3.3.0": version: 3.3.0 resolution: "chokidar@npm:3.3.0" From 6295693f314c118e33f246c267a29e5aa2bda173 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 17 Oct 2024 10:36:39 +0100 Subject: [PATCH 145/224] chore: extend list of blocked addresses on relayer (#4696) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../config/environments/mainnet3/agent.ts | 6 ++-- typescript/infra/src/config/agent/relayer.ts | 30 ++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 6e34d70cf..a470b1c87 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -418,7 +418,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'efd438f-20241016-101828', + tag: 'b1ff48b-20241016-183301', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -452,7 +452,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '5cb1787-20240924-192934', + tag: 'b1ff48b-20241016-183301', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. @@ -485,7 +485,7 @@ const neutron: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '5a0d68b-20240916-144115', + tag: 'b1ff48b-20241016-183301', }, gasPaymentEnforcement: [ { diff --git a/typescript/infra/src/config/agent/relayer.ts b/typescript/infra/src/config/agent/relayer.ts index aebcac245..cd7e4a46d 100644 --- a/typescript/infra/src/config/agent/relayer.ts +++ b/typescript/infra/src/config/agent/relayer.ts @@ -169,16 +169,26 @@ export class RelayerConfigHelper extends AgentConfigHelper { }), ); - return allSanctionedAddresses.flat().filter((address) => { - if (!isValidAddressEvm(address)) { - this.logger.debug( - { address }, - 'Invalid sanctioned address, throwing out', - ); - return false; - } - return true; - }); + const sanctionedEthereumAdresses = allSanctionedAddresses + .flat() + .filter((address) => { + if (!isValidAddressEvm(address)) { + this.logger.debug( + { address }, + 'Invalid sanctioned address, throwing out', + ); + return false; + } + return true; + }); + + const radiantExploiter = [ + '0xA0e768A68ba1BFffb9F4366dfC8D9195EE7217d1', + '0x0629b1048298AE9deff0F4100A31967Fb3f98962', + '0x97a05beCc2e7891D07F382457Cd5d57FD242e4e8', + ]; + + return [...sanctionedEthereumAdresses, ...radiantExploiter]; } // Returns whether the relayer requires AWS credentials From b3495b205c90fa4dbfc28b79ab492fbfb424386c Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Thu, 17 Oct 2024 06:47:57 -0400 Subject: [PATCH 146/224] chore: Update warp Ids for Renzo (#4695) ### Description Updates the warp Ids for latest renzo deployment to sei and taiko used by the checker --- .changeset/silver-dancers-rhyme.md | 5 +++++ .../infra/config/environments/mainnet3/warp/warpIds.ts | 2 +- typescript/infra/config/warp.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/silver-dancers-rhyme.md diff --git a/.changeset/silver-dancers-rhyme.md b/.changeset/silver-dancers-rhyme.md new file mode 100644 index 000000000..14ce7dd00 --- /dev/null +++ b/.changeset/silver-dancers-rhyme.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/infra': minor +--- + +Updates the warpIds for Renzo's latest deployment to Sei and Taiko to be used by the Checker diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index 5e8052d42..3d9d08899 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -1,6 +1,6 @@ export enum WarpRouteIds { Ancient8EthereumUSDC = 'USDC/ancient8-ethereum', - ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-zircuit', + ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-sei-taiko-zircuit', ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron', ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet', diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 994c9fa9c..4b122718c 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -38,7 +38,7 @@ export const warpConfigGetterMap: Record< [WarpRouteIds.EthereumInevmUSDT]: getEthereumInevmUSDTWarpConfig, [WarpRouteIds.ArbitrumNeutronEclip]: getArbitrumNeutronEclipWarpConfig, [WarpRouteIds.ArbitrumNeutronTIA]: getArbitrumNeutronTiaWarpConfig, - [WarpRouteIds.ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismZircuitEZETH]: + [WarpRouteIds.ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH]: getRenzoEZETHWarpConfig, [WarpRouteIds.InevmInjectiveINJ]: getInevmInjectiveINJWarpConfig, [WarpRouteIds.EthereumVictionETH]: getEthereumVictionETHWarpConfig, From 6dd47465964e61e1b308bfcf129ce121bc08ddfd Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 17 Oct 2024 11:48:04 +0100 Subject: [PATCH 147/224] chore: update key funder image (#4698) ### Description Updates the key funder to include the latest polygon tx overrides added by #4682 ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/infra/config/environments/mainnet3/funding.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index 2dcd8d134..a9bd1ec0c 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '18c29c8-20241014-133714', + tag: '6295693-20241017-095058', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron From b4d26ddb7fc7fe9dad32fdbbf15a55bec1e3ed1c Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 17 Oct 2024 13:01:00 +0100 Subject: [PATCH 148/224] feat: add FASTUSD/ethereum-sei to checker (#4697) ### Description Adds recent fastUSD deploy to our checking infra ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../getEthereumSeiFastUSDWarpConfig.ts | 47 +++++++++++++++++++ .../environments/mainnet3/warp/warpIds.ts | 1 + typescript/infra/config/warp.ts | 12 +++-- typescript/infra/src/config/warp.ts | 4 ++ 4 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.ts diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.ts new file mode 100644 index 000000000..5bd4938d2 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.ts @@ -0,0 +1,47 @@ +import { ethers } from 'ethers'; + +import { + ChainMap, + RouterConfig, + TokenRouterConfig, + TokenType, +} from '@hyperlane-xyz/sdk'; + +import { tokens } from '../../../../../src/config/warp.js'; + +// Elixir +const owner = '0x00000000F51340906F767C6999Fe512b1275955C'; + +export const getEthereumSeiFastUSDWarpConfig = async ( + routerConfig: ChainMap, +): Promise> => { + const sei: TokenRouterConfig = { + ...routerConfig.viction, + type: TokenType.XERC20, + name: 'fastUSD', + symbol: 'fastUSD', + decimals: 18, + token: tokens.sei.fastUSD, + interchainSecurityModule: ethers.constants.AddressZero, + owner, + ownerOverrides: { + proxyAdmin: owner, + }, + }; + + const ethereum: TokenRouterConfig = { + ...routerConfig.ethereum, + type: TokenType.collateral, + token: tokens.ethereum.deUSD, + owner, + interchainSecurityModule: ethers.constants.AddressZero, + ownerOverrides: { + proxyAdmin: owner, + }, + }; + + return { + sei, + ethereum, + }; +}; diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index 3d9d08899..7a75bcd2c 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -9,6 +9,7 @@ export enum WarpRouteIds { EthereumInevmUSDT = 'USDT/ethereum-inevm', EthereumEclipseTETH = 'tETH/eclipsemainnet-ethereum', EthereumEclipseUSDC = 'USDC/eclipsemainnet-ethereum-solanamainnet', + EthereumSeiFastUSD = 'FASTUSD/ethereum-sei', EthereumVictionETH = 'ETH/ethereum-viction', EthereumVictionUSDC = 'USDC/ethereum-viction', EthereumVictionUSDT = 'USDT/ethereum-viction', diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 4b122718c..7cfb624f3 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -15,6 +15,7 @@ import { getEthereumEclipseTETHWarpConfig } from './environments/mainnet3/warp/c import { getEthereumEclipseUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumEclipseUSDCWarpConfig.js'; import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js'; import { getEthereumInevmUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDTWarpConfig.js'; +import { getEthereumSeiFastUSDWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.js'; import { getEthereumVictionETHWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionETHWarpConfig.js'; import { getEthereumVictionUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionUSDCWarpConfig.js'; import { getEthereumVictionUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumVictionUSDTWarpConfig.js'; @@ -41,12 +42,13 @@ export const warpConfigGetterMap: Record< [WarpRouteIds.ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH]: getRenzoEZETHWarpConfig, [WarpRouteIds.InevmInjectiveINJ]: getInevmInjectiveINJWarpConfig, + [WarpRouteIds.EthereumEclipseTETH]: getEthereumEclipseTETHWarpConfig, + [WarpRouteIds.EthereumEclipseUSDC]: getEthereumEclipseUSDCWarpConfig, + [WarpRouteIds.EthereumSeiFastUSD]: getEthereumSeiFastUSDWarpConfig, [WarpRouteIds.EthereumVictionETH]: getEthereumVictionETHWarpConfig, [WarpRouteIds.EthereumVictionUSDC]: getEthereumVictionUSDCWarpConfig, [WarpRouteIds.EthereumVictionUSDT]: getEthereumVictionUSDTWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, - [WarpRouteIds.EthereumEclipseTETH]: getEthereumEclipseTETHWarpConfig, - [WarpRouteIds.EthereumEclipseUSDC]: getEthereumEclipseUSDCWarpConfig, }; export async function getWarpConfig( @@ -59,7 +61,11 @@ export async function getWarpConfig( const warpConfigGetter = warpConfigGetterMap[warpRouteId]; if (!warpConfigGetter) { - throw new Error(`Unknown warp route: ${warpRouteId}`); + throw new Error( + `Unknown warp route: ${warpRouteId}, must be one of: ${Object.keys( + warpConfigGetterMap, + ).join(', ')}`, + ); } if (warpConfigGetter.length === 1) { diff --git a/typescript/infra/src/config/warp.ts b/typescript/infra/src/config/warp.ts index cf9d125d8..25bd40818 100644 --- a/typescript/infra/src/config/warp.ts +++ b/typescript/infra/src/config/warp.ts @@ -6,5 +6,9 @@ export const tokens: ChainMap> = { ethereum: { USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdac17f958d2ee523a2206206994597c13d831ec7', + deUSD: '0x15700B564Ca08D9439C58cA5053166E8317aa138', + }, + sei: { + fastUSD: '0x37a4dD9CED2b19Cfe8FAC251cd727b5787E45269', }, }; From 1606f85df30e5f5df453584911058751c2698cc5 Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Thu, 17 Oct 2024 07:54:52 -0500 Subject: [PATCH 149/224] feat(warpChecker): Support Renzo PZETH route (#4628) ### Description - support Renzo PZETH warp route in checker ### Drive-by changes - introduce `CheckerWarpRouteIds` enum for warp routes that are supported in the checker, eclipse and sol routes are not currently supported ### Testing Manual --- .../infra/config/environments/mainnet3/warp/warpIds.ts | 1 + typescript/infra/config/warp.ts | 6 ++---- typescript/infra/scripts/check/check-warp-deploy.ts | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index 7a75bcd2c..9ff51677e 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -13,6 +13,7 @@ export enum WarpRouteIds { EthereumVictionETH = 'ETH/ethereum-viction', EthereumVictionUSDC = 'USDC/ethereum-viction', EthereumVictionUSDT = 'USDT/ethereum-viction', + EthereumZircuitPZETH = 'PZETH/ethereum-zircuit', InevmInjectiveINJ = 'INJ/inevm-injective', MantapacificNeutronTIA = 'TIA/mantapacific-neutron', } diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 7cfb624f3..447183e8c 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -11,8 +11,6 @@ import { EnvironmentConfig } from '../src/config/environment.js'; import { getAncient8EthereumUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getAncient8EthereumUSDCWarpConfig.js'; import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronEclipWarpConfig.js'; import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js'; -import { getEthereumEclipseTETHWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumEclipseTETHWarpConfig.js'; -import { getEthereumEclipseUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumEclipseUSDCWarpConfig.js'; import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js'; import { getEthereumInevmUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDTWarpConfig.js'; import { getEthereumSeiFastUSDWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.js'; @@ -22,6 +20,7 @@ import { getEthereumVictionUSDTWarpConfig } from './environments/mainnet3/warp/c import { getInevmInjectiveINJWarpConfig } from './environments/mainnet3/warp/configGetters/getInevmInjectiveINJWarpConfig.js'; import { getMantapacificNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getMantapacificNeutronTiaWarpConfig.js'; import { getRenzoEZETHWarpConfig } from './environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.js'; +import { getRenzoPZETHWarpConfig } from './environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.js'; import { WarpRouteIds } from './environments/mainnet3/warp/warpIds.js'; type WarpConfigGetterWithConfig = ( @@ -42,12 +41,11 @@ export const warpConfigGetterMap: Record< [WarpRouteIds.ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH]: getRenzoEZETHWarpConfig, [WarpRouteIds.InevmInjectiveINJ]: getInevmInjectiveINJWarpConfig, - [WarpRouteIds.EthereumEclipseTETH]: getEthereumEclipseTETHWarpConfig, - [WarpRouteIds.EthereumEclipseUSDC]: getEthereumEclipseUSDCWarpConfig, [WarpRouteIds.EthereumSeiFastUSD]: getEthereumSeiFastUSDWarpConfig, [WarpRouteIds.EthereumVictionETH]: getEthereumVictionETHWarpConfig, [WarpRouteIds.EthereumVictionUSDC]: getEthereumVictionUSDCWarpConfig, [WarpRouteIds.EthereumVictionUSDT]: getEthereumVictionUSDTWarpConfig, + [WarpRouteIds.EthereumZircuitPZETH]: getRenzoPZETHWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, }; diff --git a/typescript/infra/scripts/check/check-warp-deploy.ts b/typescript/infra/scripts/check/check-warp-deploy.ts index 66334b8cf..aa51c7016 100644 --- a/typescript/infra/scripts/check/check-warp-deploy.ts +++ b/typescript/infra/scripts/check/check-warp-deploy.ts @@ -1,7 +1,7 @@ import chalk from 'chalk'; import { Gauge, Registry } from 'prom-client'; -import { WarpRouteIds } from '../../config/environments/mainnet3/warp/warpIds.js'; +import { warpConfigGetterMap } from '../../config/warp.js'; import { submitMetrics } from '../../src/utils/metrics.js'; import { Modules } from '../agent-utils.js'; @@ -25,7 +25,7 @@ async function main() { const failedWarpRoutesChecks: string[] = []; // TODO: consider retrying this if check throws an error - for (const warpRouteId of Object.values(WarpRouteIds)) { + for (const warpRouteId of Object.keys(warpConfigGetterMap)) { console.log(`\nChecking warp route ${warpRouteId}...`); const warpModule = Modules.WARP; From dbb7e954f545b3dd557b45fc17a5f9a9b9f767db Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 17 Oct 2024 16:07:09 +0100 Subject: [PATCH 150/224] fix: use correct contract for proxyAdmin ownership violation (#4700) ### Description Quick change I encountered when trying to change proxy admin owners -- the contract passed in was the app router, not the proxy admin ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- typescript/sdk/src/deploy/HyperlaneAppChecker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts index 871019a17..9a9bf4bcc 100644 --- a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts +++ b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts @@ -139,7 +139,7 @@ export abstract class HyperlaneAppChecker< type: ViolationType.Owner, actual: actualProxyAdminOwner, expected: expectedOwner, - contract, + contract: actualProxyAdminContract, }; this.addViolation(violation); } From 3f48f5a8ed5ed872ddbb5a592032a54352638f66 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:36:05 +0100 Subject: [PATCH 151/224] chore: add scroll gasPrice override (#4701) ### Description chore: add back the scroll gasPrice override relayer's unaffected because we override that to 0.8 gwei ### Drive-by changes update agent config ### Related issues key funder :'( ### Backward compatibility yes ### Testing manual? --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- rust/main/config/mainnet_config.json | 5 ++++- typescript/infra/config/environments/mainnet3/chains.ts | 8 ++++++++ typescript/infra/config/environments/mainnet3/funding.ts | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index c460fe308..2667590fe 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -2706,7 +2706,10 @@ "validatorAnnounce": "0xd83A4F747fE80Ed98839e05079B1B7Fe037b1638", "staticMerkleRootWeightedMultisigIsmFactory": "0xcb0D04010584AA5244b5826c990eeA4c16BeAC8C", "staticMessageIdWeightedMultisigIsmFactory": "0x609707355a53d2aAb6366f48E2b607C599D26B29", - "technicalStack": "other" + "technicalStack": "other", + "transactionOverrides": { + "gasPrice": 200000000 + } }, "sei": { "aggregationHook": "0x40514BD46C57455933Be8BAedE96C4F0Ba3507D6", diff --git a/typescript/infra/config/environments/mainnet3/chains.ts b/typescript/infra/config/environments/mainnet3/chains.ts index e7ff32d46..e4d7f774f 100644 --- a/typescript/infra/config/environments/mainnet3/chains.ts +++ b/typescript/infra/config/environments/mainnet3/chains.ts @@ -31,6 +31,14 @@ export const chainMetadataOverrides: ChainMap> = { gasPrice: 1 * 10 ** 9, // 1 gwei }, }, + scroll: { + transactionOverrides: { + // Scroll doesn't use EIP 1559 and the gas price that's returned is sometimes + // too low for the transaction to be included in a reasonable amount of time - + // this often leads to transaction underpriced issues. + gasPrice: 2 * 10 ** 8, // 0.2 gwei + }, + }, sei: { // Sei's `eth_feeHistory` is not to spec and incompatible with ethers-rs, // so we force legacy transactions by setting a gas price. diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index a9bd1ec0c..dafee524d 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '6295693-20241017-095058', + tag: '436988a-20241017-151047', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron From 01e7070ebe4f53a6298296eaf193bbdf3bd65da6 Mon Sep 17 00:00:00 2001 From: xeno097 Date: Thu, 17 Oct 2024 18:30:05 -0400 Subject: [PATCH 152/224] feat: better chain selection concept (#4596) ### Description This PR implements an updated view of the multi-chain selection step that now allows searching for chains in the current list #### Before: ![image](https://github.com/user-attachments/assets/64876be9-16f6-4c23-8562-637776d1db0a) ![image](https://github.com/user-attachments/assets/165c46c5-e94a-48b6-aa7c-38a68b20eed7) #### After: ![image](https://github.com/user-attachments/assets/1c91c34f-c7aa-43df-8de6-7e7322c1ba70) ![image](https://github.com/user-attachments/assets/adfac628-a9c2-4c28-85a2-853dea1da551) ![image](https://github.com/user-attachments/assets/809fef22-9a2a-4220-8192-9108ae1e093e) ### Drive-by changes - Updated the `runMultiChainSelectionStep` function to take as param an object instead of a list of params because the list was growing larger ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4513 ### Backward compatibility - Yes ### Testing - Manual - Manual testing has also been conducted on Windows to see if https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4508 was solved. In this case, the following were discovered: - The chain selection is unusable on `gitbash`. - The chain selection works perfectly fine using `powershell` and `cmd`. I assume the issue is linked to how `gitbash` handles inputs or simulates a UNIX environment on Windows. CLI users on windows should use either one of these options --- .changeset/tricky-mangos-sin.md | 5 + typescript/cli/package.json | 1 + typescript/cli/src/config/hooks.ts | 10 +- typescript/cli/src/config/ism.ts | 20 +- typescript/cli/src/config/multisig.ts | 4 +- typescript/cli/src/config/warp.ts | 11 +- typescript/cli/src/deploy/agent.ts | 10 +- typescript/cli/src/utils/chains.ts | 108 +++++- typescript/cli/src/utils/input.ts | 509 +++++++++++++++++++++++++- yarn.lock | 17 + 10 files changed, 649 insertions(+), 46 deletions(-) create mode 100644 .changeset/tricky-mangos-sin.md diff --git a/.changeset/tricky-mangos-sin.md b/.changeset/tricky-mangos-sin.md new file mode 100644 index 000000000..31ea11b57 --- /dev/null +++ b/.changeset/tricky-mangos-sin.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +updates the multi chain selection prompt by adding search functionality and an optional confirmation prompt for the current selection diff --git a/typescript/cli/package.json b/typescript/cli/package.json index eb1403de0..ee91e5fc8 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -9,6 +9,7 @@ "@hyperlane-xyz/sdk": "5.5.0", "@hyperlane-xyz/utils": "5.5.0", "@inquirer/prompts": "^3.0.0", + "ansi-escapes": "^7.0.0", "asn1.js": "^5.4.1", "bignumber.js": "^9.1.1", "chalk": "^5.3.0", diff --git a/typescript/cli/src/config/hooks.ts b/typescript/cli/src/config/hooks.ts index 30294d19d..a075d6655 100644 --- a/typescript/cli/src/config/hooks.ts +++ b/typescript/cli/src/config/hooks.ts @@ -265,11 +265,11 @@ export const createRoutingConfig = callWithConfigCreationLogs( message: 'Enter owner address for routing Hook', }); const ownerAddress = owner; - const chains = await runMultiChainSelectionStep( - context.chainMetadata, - 'Select chains for routing Hook', - 1, - ); + const chains = await runMultiChainSelectionStep({ + chainMetadata: context.chainMetadata, + message: 'Select chains for routing Hook', + requireNumber: 1, + }); const domainsMap: ChainMap = {}; for (const chain of chains) { diff --git a/typescript/cli/src/config/ism.ts b/typescript/cli/src/config/ism.ts index c975bb895..e40a00c26 100644 --- a/typescript/cli/src/config/ism.ts +++ b/typescript/cli/src/config/ism.ts @@ -226,11 +226,11 @@ export const createRoutingConfig = callWithConfigCreationLogs( message: 'Enter owner address for routing ISM', }); const ownerAddress = owner; - const chains = await runMultiChainSelectionStep( - context.chainMetadata, - 'Select chains to configure routing ISM for', - 1, - ); + const chains = await runMultiChainSelectionStep({ + chainMetadata: context.chainMetadata, + message: 'Select chains to configure routing ISM for', + requireNumber: 1, + }); const domainsMap: ChainMap = {}; for (const chain of chains) { @@ -249,11 +249,11 @@ export const createRoutingConfig = callWithConfigCreationLogs( export const createFallbackRoutingConfig = callWithConfigCreationLogs( async (context: CommandContext): Promise => { - const chains = await runMultiChainSelectionStep( - context.chainMetadata, - 'Select chains to configure fallback routing ISM for', - 1, - ); + const chains = await runMultiChainSelectionStep({ + chainMetadata: context.chainMetadata, + message: 'Select chains to configure fallback routing ISM for', + requireNumber: 1, + }); const domainsMap: ChainMap = {}; for (const chain of chains) { diff --git a/typescript/cli/src/config/multisig.ts b/typescript/cli/src/config/multisig.ts index bb2e0ebbf..28648b271 100644 --- a/typescript/cli/src/config/multisig.ts +++ b/typescript/cli/src/config/multisig.ts @@ -72,7 +72,9 @@ export async function createMultisigConfig({ log( 'Select your own chain below to run your own validators. If you want to reuse existing Hyperlane validators instead of running your own, do not select additional mainnet or testnet chains.', ); - const chains = await runMultiChainSelectionStep(context.chainMetadata); + const chains = await runMultiChainSelectionStep({ + chainMetadata: context.chainMetadata, + }); const chainAddresses = await context.registry.getAddresses(); const result: MultisigConfigMap = {}; diff --git a/typescript/cli/src/config/warp.ts b/typescript/cli/src/config/warp.ts index 29246cd33..dd3a23713 100644 --- a/typescript/cli/src/config/warp.ts +++ b/typescript/cli/src/config/warp.ts @@ -125,11 +125,12 @@ export async function createWarpRouteDeployConfig({ 'signer', ); - const warpChains = await runMultiChainSelectionStep( - context.chainMetadata, - 'Select chains to connect', - 1, - ); + const warpChains = await runMultiChainSelectionStep({ + chainMetadata: context.chainMetadata, + message: 'Select chains to connect', + requireNumber: 1, + requiresConfirmation: true, + }); const result: WarpRouteDeployConfig = {}; let typeChoices = TYPE_CHOICES; diff --git a/typescript/cli/src/deploy/agent.ts b/typescript/cli/src/deploy/agent.ts index 5b93e10c4..ca490fc5f 100644 --- a/typescript/cli/src/deploy/agent.ts +++ b/typescript/cli/src/deploy/agent.ts @@ -28,11 +28,11 @@ export async function runKurtosisAgentDeploy({ ); } if (!relayChains) { - const selectedRelayChains = await runMultiChainSelectionStep( - context.chainMetadata, - 'Select chains to relay between', - 2, - ); + const selectedRelayChains = await runMultiChainSelectionStep({ + chainMetadata: context.chainMetadata, + message: 'Select chains to relay between', + requireNumber: 2, + }); relayChains = selectedRelayChains.join(','); } diff --git a/typescript/cli/src/utils/chains.ts b/typescript/cli/src/utils/chains.ts index fe226b1b8..09975aca3 100644 --- a/typescript/cli/src/utils/chains.ts +++ b/typescript/cli/src/utils/chains.ts @@ -1,13 +1,14 @@ -import { Separator, checkbox } from '@inquirer/prompts'; +import { Separator, confirm } from '@inquirer/prompts'; import select from '@inquirer/select'; import chalk from 'chalk'; import { ChainMap, ChainMetadata } from '@hyperlane-xyz/sdk'; import { toTitleCase } from '@hyperlane-xyz/utils'; -import { log, logRed, logTip } from '../logger.js'; +import { log } from '../logger.js'; import { calculatePageSize } from './cli-options.js'; +import { SearchableCheckboxChoice, searchableCheckBox } from './input.js'; // A special value marker to indicate user selected // a new chain in the list @@ -18,37 +19,101 @@ export async function runSingleChainSelectionStep( message = 'Select chain', ) { const networkType = await selectNetworkType(); - const choices = getChainChoices(chainMetadata, networkType); + const { choices, networkTypeSeparator } = getChainChoices( + chainMetadata, + networkType, + ); const chain = (await select({ message, - choices, + choices: [networkTypeSeparator, ...choices], pageSize: calculatePageSize(2), })) as string; handleNewChain([chain]); return chain; } -export async function runMultiChainSelectionStep( - chainMetadata: ChainMap, +type RunMultiChainSelectionStepOptions = { + /** + * The metadata of the chains that will be displayed to the user + */ + chainMetadata: ChainMap; + + /** + * The message to display to the user + * + * @default 'Select chains' + */ + message?: string; + + /** + * The minimum number of chains that must be selected + * + * @default 0 + */ + requireNumber?: number; + + /** + * Whether to ask for confirmation after the selection + * + * @default false + */ + requiresConfirmation?: boolean; +}; + +export async function runMultiChainSelectionStep({ + chainMetadata, message = 'Select chains', requireNumber = 0, -) { + requiresConfirmation = false, +}: RunMultiChainSelectionStepOptions) { const networkType = await selectNetworkType(); - const choices = getChainChoices(chainMetadata, networkType); + const { choices, networkTypeSeparator } = getChainChoices( + chainMetadata, + networkType, + ); + + let currentChoiceSelection = new Set(); while (true) { - logTip( - `Use SPACE key to select at least ${requireNumber} chains, then press ENTER`, - ); - const chains = (await checkbox({ + const chains = await searchableCheckBox({ message, - choices, + selectableOptionsSeparator: networkTypeSeparator, + choices: choices.map((choice) => + currentChoiceSelection.has(choice.name) + ? { ...choice, checked: true } + : choice, + ), + instructions: `Use TAB key to select at least ${requireNumber} chains, then press ENTER to proceed. Type to search for a specific chain.`, + theme: { + style: { + // The leading space is needed because the help tip will be tightly close to the message header + helpTip: (text: string) => ` ${chalk.bgYellow(text)}`, + }, + helpMode: 'always', + }, pageSize: calculatePageSize(2), - })) as string[]; + validate: (answer): string | boolean => { + if (answer.length < requireNumber) { + return `Please select at least ${requireNumber} chains`; + } + + return true; + }, + }); + handleNewChain(chains); - if (chains?.length < requireNumber) { - logRed(`Please select at least ${requireNumber} chains`); + + const confirmed = requiresConfirmation + ? await confirm({ + message: `Is this chain selection correct?: ${chalk.cyan( + chains.join(', '), + )}`, + }) + : true; + if (!confirmed) { + currentChoiceSelection = new Set(chains); continue; } + return chains; } } @@ -75,12 +140,17 @@ function getChainChoices( const filteredChains = chains.filter((c) => networkType === 'mainnet' ? !c.isTestnet : !!c.isTestnet, ); - const choices: Parameters['0']['choices'] = [ + const choices: SearchableCheckboxChoice[] = [ { name: '(New custom chain)', value: NEW_CHAIN_MARKER }, - new Separator(`--${toTitleCase(networkType)} Chains--`), ...chainsToChoices(filteredChains), ]; - return choices; + + return { + choices, + networkTypeSeparator: new Separator( + `--${toTitleCase(networkType)} Chains--`, + ), + }; } function handleNewChain(chainNames: string[]) { diff --git a/typescript/cli/src/utils/input.ts b/typescript/cli/src/utils/input.ts index 0f8c9ef66..4b54c4f3e 100644 --- a/typescript/cli/src/utils/input.ts +++ b/typescript/cli/src/utils/input.ts @@ -1,4 +1,22 @@ -import { confirm, input } from '@inquirer/prompts'; +import { + Separator, + type Theme, + createPrompt, + isEnterKey, + makeTheme, + useEffect, + useKeypress, + useMemo, + usePagination, + usePrefix, + useRef, + useState, +} from '@inquirer/core'; +import figures from '@inquirer/figures'; +import { KeypressEvent, confirm, input } from '@inquirer/prompts'; +import type { PartialDeep } from '@inquirer/type'; +import ansiEscapes from 'ansi-escapes'; +import chalk from 'chalk'; import { logGray } from '../logger.js'; @@ -53,3 +71,492 @@ export async function inputWithInfo({ } while (answer === INFO_COMMAND); return answer; } + +/** + * Searchable checkbox code + * + * Note that the code below hab been implemented by taking inspiration from + * the @inquirer/prompt package search and checkbox prompts + * + * - https://github.com/SBoudrias/Inquirer.js/blob/main/packages/search/src/index.mts + * - https://github.com/SBoudrias/Inquirer.js/blob/main/packages/checkbox/src/index.mts + */ + +type Status = 'loading' | 'idle' | 'done'; + +type SearchableCheckboxTheme = { + icon: { + checked: string; + unchecked: string; + cursor: string; + }; + style: { + disabledChoice: (text: string) => string; + renderSelectedChoices: ( + selectedChoices: ReadonlyArray>, + allChoices: ReadonlyArray | Separator>, + ) => string; + description: (text: string) => string; + helpTip: (text: string) => string; + }; + helpMode: 'always' | 'never' | 'auto'; +}; + +const checkboxTheme: SearchableCheckboxTheme = { + icon: { + checked: chalk.green(figures.circleFilled), + unchecked: figures.circle, + cursor: figures.pointer, + }, + style: { + disabledChoice: (text: string) => chalk.dim(`- ${text}`), + renderSelectedChoices: (selectedChoices) => + selectedChoices.map((choice) => choice.short).join(', '), + description: (text: string) => chalk.cyan(text), + helpTip: (text) => ` ${text}`, + }, + helpMode: 'always', +}; + +export type SearchableCheckboxChoice = { + value: Value; + name?: string; + description?: string; + short?: string; + disabled?: boolean | string; + checked?: boolean; +}; + +type NormalizedChoice = Required< + Omit, 'description'> +> & { + description?: string; +}; + +type SearchableCheckboxConfig = { + message: string; + prefix?: string; + pageSize?: number; + instructions?: string; + choices: ReadonlyArray>; + loop?: boolean; + required?: boolean; + selectableOptionsSeparator?: Separator; + validate?: ( + choices: ReadonlyArray>, + ) => boolean | string | Promise; + theme?: PartialDeep>; +}; + +type Item = NormalizedChoice | Separator; + +type SearchableCheckboxState = { + options: Item[]; + currentOptionState: Record>; +}; + +function isSelectable( + item: Item, +): item is NormalizedChoice { + return !Separator.isSeparator(item) && !item.disabled; +} + +function isChecked(item: Item): item is NormalizedChoice { + return isSelectable(item) && Boolean(item.checked); +} + +function toggle(item: Item): Item { + return isSelectable(item) ? { ...item, checked: !item.checked } : item; +} + +function normalizeChoices( + choices: ReadonlyArray>, +): NormalizedChoice[] { + return choices.map((choice) => { + const name = choice.name ?? String(choice.value); + return { + value: choice.value, + name, + short: choice.short ?? name, + description: choice.description, + disabled: choice.disabled ?? false, + checked: choice.checked ?? false, + }; + }); +} + +function sortNormalizedItems( + a: NormalizedChoice, + b: NormalizedChoice, +): number { + return a.name.localeCompare(b.name); +} + +function organizeItems( + items: Array>, + selectableOptionsSeparator?: Separator, +): Array | Separator> { + const orderedItems = []; + + const checkedItems = items.filter( + (item) => !Separator.isSeparator(item) && item.checked, + ) as NormalizedChoice[]; + + if (checkedItems.length !== 0) { + orderedItems.push(new Separator('--Selected Options--')); + + orderedItems.push(...checkedItems.sort(sortNormalizedItems)); + } + + orderedItems.push( + selectableOptionsSeparator ?? new Separator('--Available Options--'), + ); + + const nonCheckedItems = items.filter( + (item) => !Separator.isSeparator(item) && !item.checked, + ) as NormalizedChoice[]; + + orderedItems.push(...nonCheckedItems.sort(sortNormalizedItems)); + + if (orderedItems.length === 1) { + return []; + } + + return orderedItems; +} + +interface BuildViewOptions { + theme: Readonly>; + pageSize: number; + firstRender: { current: boolean }; + page: string; + currentOptions: ReadonlyArray>; + prefix: string; + message: string; + errorMsg?: string; + status: Status; + searchTerm: string; + description?: string; + instructions?: string; +} + +interface GetErrorMessageOptions + extends Pick< + BuildViewOptions, + 'theme' | 'errorMsg' | 'status' | 'searchTerm' + > { + currentItemCount: number; +} + +function getErrorMessage({ + theme, + errorMsg, + currentItemCount, + status, + searchTerm, +}: GetErrorMessageOptions): string { + if (errorMsg) { + return `${theme.style.error(errorMsg)}`; + } else if (currentItemCount === 0 && searchTerm !== '' && status === 'idle') { + return theme.style.error('No results found'); + } + + return ''; +} + +interface GetHelpTipsOptions + extends Pick< + BuildViewOptions, + 'theme' | 'pageSize' | 'firstRender' | 'instructions' + > { + currentItemCount: number; +} + +function getHelpTips({ + theme, + instructions, + currentItemCount, + pageSize, + firstRender, +}: GetHelpTipsOptions): { helpTipTop: string; helpTipBottom: string } { + let helpTipTop = ''; + let helpTipBottom = ''; + const defaultTopHelpTip = + instructions ?? + `(Press ${theme.style.key('tab')} to select, and ${theme.style.key( + 'enter', + )} to proceed`; + const defaultBottomHelpTip = `\n${theme.style.help( + '(Use arrow keys to reveal more choices)', + )}`; + + if (theme.helpMode === 'always') { + helpTipTop = theme.style.helpTip(defaultTopHelpTip); + helpTipBottom = currentItemCount > pageSize ? defaultBottomHelpTip : ''; + firstRender.current = false; + } else if (theme.helpMode === 'auto' && firstRender.current) { + helpTipTop = theme.style.helpTip(defaultTopHelpTip); + helpTipBottom = currentItemCount > pageSize ? defaultBottomHelpTip : ''; + firstRender.current = false; + } + + return { helpTipBottom, helpTipTop }; +} + +function formatRenderedItem( + item: Readonly>, + isActive: boolean, + theme: Readonly>, +): string { + if (Separator.isSeparator(item)) { + return ` ${item.separator}`; + } + + if (item.disabled) { + const disabledLabel = + typeof item.disabled === 'string' ? item.disabled : '(disabled)'; + return theme.style.disabledChoice(`${item.name} ${disabledLabel}`); + } + + const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked; + const color = isActive ? theme.style.highlight : (x: string) => x; + const cursor = isActive ? theme.icon.cursor : ' '; + return color(`${cursor}${checkbox} ${item.name}`); +} + +function getListBounds(items: ReadonlyArray>): { + first: number; + last: number; +} { + const first = items.findIndex(isSelectable); + // findLastIndex replacement as the project must support older ES versions + let last = -1; + for (let i = items.length; i >= 0; --i) { + if (items[i] && isSelectable(items[i])) { + last = i; + break; + } + } + + return { first, last }; +} + +function buildView({ + page, + prefix, + theme, + status, + message, + errorMsg, + pageSize, + firstRender, + searchTerm, + description, + instructions, + currentOptions, +}: BuildViewOptions): string { + message = theme.style.message(message); + if (status === 'done') { + const selection = currentOptions.filter(isChecked); + const answer = theme.style.answer( + theme.style.renderSelectedChoices(selection, currentOptions), + ); + + return `${prefix} ${message} ${answer}`; + } + + const currentItemCount = currentOptions.length; + const { helpTipBottom, helpTipTop } = getHelpTips({ + theme, + instructions, + currentItemCount, + pageSize, + firstRender, + }); + + const choiceDescription = description + ? `\n${theme.style.description(description)}` + : ``; + + const error = getErrorMessage({ + theme, + errorMsg, + currentItemCount, + status, + searchTerm, + }); + + return `${prefix} ${message}${helpTipTop} ${searchTerm}\n${page}${helpTipBottom}${choiceDescription}${error}${ansiEscapes.cursorHide}`; +} + +// the isUpKey function from the inquirer package is not used +// because it detects k and p as custom keybindings that cause +// the option selection to go up instead of writing the letters +// in the search string +function isUpKey(key: KeypressEvent): boolean { + return key.name === 'up'; +} + +// the isDownKey function from the inquirer package is not used +// because it detects j and n as custom keybindings that cause +// the option selection to go down instead of writing the letters +// in the search string +function isDownKey(key: KeypressEvent): boolean { + return key.name === 'down'; +} + +export const searchableCheckBox = createPrompt( + ( + config: SearchableCheckboxConfig, + done: (value: Array) => void, + ) => { + const { + instructions, + pageSize = 7, + loop = true, + required, + validate = () => true, + selectableOptionsSeparator, + } = config; + const theme = makeTheme( + checkboxTheme, + config.theme, + ); + const firstRender = useRef(true); + const [status, setStatus] = useState('idle'); + const prefix = usePrefix({ theme }); + const [searchTerm, setSearchTerm] = useState(''); + const [errorMsg, setError] = useState(); + + const normalizedChoices = normalizeChoices(config.choices); + const [optionState, setOptionState] = useState< + SearchableCheckboxState + >({ + options: normalizedChoices, + currentOptionState: Object.fromEntries( + normalizedChoices.map((item) => [item.name, item]), + ), + }); + + const bounds = useMemo( + () => getListBounds(optionState.options), + [optionState.options], + ); + + const [active, setActive] = useState(bounds.first); + + useEffect(() => { + let filteredItems; + if (!searchTerm) { + filteredItems = Object.values(optionState.currentOptionState); + } else { + filteredItems = Object.values(optionState.currentOptionState).filter( + (item) => + Separator.isSeparator(item) || + item.name.includes(searchTerm) || + item.checked, + ); + } + + setActive(0); + setError(undefined); + setOptionState({ + currentOptionState: optionState.currentOptionState, + options: organizeItems(filteredItems, selectableOptionsSeparator), + }); + }, [searchTerm]); + + useKeypress(async (key, rl) => { + if (isEnterKey(key)) { + const selection = optionState.options.filter(isChecked); + const isValid = await validate(selection); + if (required && !optionState.options.some(isChecked)) { + setError('At least one choice must be selected'); + } else if (isValid === true) { + setStatus('done'); + done(selection.map((choice) => choice.value)); + } else { + setError(isValid || 'You must select a valid value'); + setSearchTerm(''); + } + } else if (isUpKey(key) || isDownKey(key)) { + if ( + loop || + (isUpKey(key) && active !== bounds.first) || + (isDownKey(key) && active !== bounds.last) + ) { + const offset = isUpKey(key) ? -1 : 1; + let next = active; + do { + next = + (next + offset + optionState.options.length) % + optionState.options.length; + } while ( + optionState.options[next] && + !isSelectable(optionState.options[next]) + ); + setActive(next); + } + } else if (key.name === 'tab' && optionState.options.length > 0) { + // Avoid the message header to be printed again in the console + rl.clearLine(0); + + const currentElement = optionState.options[active]; + if ( + currentElement && + !Separator.isSeparator(currentElement) && + optionState.currentOptionState[currentElement.name] + ) { + const updatedDataMap: Record> = { + ...optionState.currentOptionState, + [currentElement.name]: toggle( + optionState.currentOptionState[currentElement.name], + ) as NormalizedChoice, + }; + + setError(undefined); + setOptionState({ + options: organizeItems( + Object.values(updatedDataMap), + selectableOptionsSeparator, + ), + currentOptionState: updatedDataMap, + }); + setSearchTerm(''); + } + } else { + setSearchTerm(rl.line); + } + }); + + let description; + const page = usePagination({ + items: optionState.options, + active, + renderItem({ item, isActive }) { + if (isActive && !Separator.isSeparator(item)) { + description = item.description; + } + + return formatRenderedItem(item, isActive, theme); + }, + pageSize, + loop, + }); + + return buildView({ + page, + theme, + prefix, + status, + pageSize, + errorMsg, + firstRender, + searchTerm, + description, + instructions, + currentOptions: optionState.options, + message: theme.style.message(config.message), + }); + }, +); diff --git a/yarn.lock b/yarn.lock index 910c021e8..ebfca2e5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7833,6 +7833,7 @@ __metadata: "@types/yargs": "npm:^17.0.24" "@typescript-eslint/eslint-plugin": "npm:^7.4.0" "@typescript-eslint/parser": "npm:^7.4.0" + ansi-escapes: "npm:^7.0.0" asn1.js: "npm:^5.4.1" bignumber.js: "npm:^9.1.1" chai: "npm:^4.5.0" @@ -14712,6 +14713,15 @@ __metadata: languageName: node linkType: hard +"ansi-escapes@npm:^7.0.0": + version: 7.0.0 + resolution: "ansi-escapes@npm:7.0.0" + dependencies: + environment: "npm:^1.0.0" + checksum: 2d0e2345087bd7ae6bf122b9cc05ee35560d40dcc061146edcdc02bc2d7c7c50143cd12a22e69a0b5c0f62b948b7bc9a4539ee888b80f5bd33cdfd82d01a70ab + languageName: node + linkType: hard + "ansi-regex@npm:^2.0.0": version: 2.1.1 resolution: "ansi-regex@npm:2.1.1" @@ -18093,6 +18103,13 @@ __metadata: languageName: node linkType: hard +"environment@npm:^1.0.0": + version: 1.1.0 + resolution: "environment@npm:1.1.0" + checksum: dd3c1b9825e7f71f1e72b03c2344799ac73f2e9ef81b78ea8b373e55db021786c6b9f3858ea43a436a2c4611052670ec0afe85bc029c384cc71165feee2f4ba6 + languageName: node + linkType: hard + "erc721a@npm:^4.2.3": version: 4.2.3 resolution: "erc721a@npm:4.2.3" From 9c0c4bbe21c260865b6c15a65fcb05c8037f0ed1 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Fri, 18 Oct 2024 12:23:58 +0100 Subject: [PATCH 153/224] feat: Add logging block hash (#4707) ### Description Add logging block hash so that we have both block height and block hash. When Scraper will report that it cannot retrieve block by hash, we'll be able to find its block height. ### Backward compatibility Yes ### Testing Run Scraper locally to see the log message --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../hyperlane-cosmos/src/providers/rpc/provider.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs index f9ec3e975..20b6ac714 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs @@ -14,7 +14,7 @@ use tendermint_rpc::endpoint::block_results::Response as BlockResultsResponse; use tendermint_rpc::endpoint::tx; use tendermint_rpc::HttpClient; use time::OffsetDateTime; -use tracing::{debug, instrument, trace}; +use tracing::{debug, info, instrument, trace}; use hyperlane_core::{ ChainCommunicationError, ChainResult, ContractLocator, HyperlaneDomain, LogMeta, H256, U256, @@ -249,6 +249,9 @@ impl WasmRpcProvider for CosmosWasmRpcProvider { // The two calls below could be made in parallel, but on cosmos rate limiting is a bigger problem // than indexing latency, so we do them sequentially. let block = self.rpc_client.get_block(block_number).await?; + + debug!(?block_number, block_hash = ?block.block_id.hash, cursor_label, domain=?self.domain, "Getting logs in block with hash"); + let block_results = self.rpc_client.get_block_results(block_number).await?; Ok(self.handle_txs(block, block_results, parser, cursor_label)) @@ -268,7 +271,12 @@ impl WasmRpcProvider for CosmosWasmRpcProvider { debug!(?hash, cursor_label, domain=?self.domain, "Getting logs in transaction"); let tx = self.rpc_client.get_tx_by_hash(hash).await?; - let block = self.rpc_client.get_block(tx.height.value() as u32).await?; + + let block_number = tx.height.value() as u32; + let block = self.rpc_client.get_block(block_number).await?; + + debug!(?block_number, block_hash = ?block.block_id.hash, cursor_label, domain=?self.domain, "Getting logs in transaction: block info"); + let block_hash = H256::from_slice(block.block_id.hash.as_bytes()); Ok(self.handle_tx(tx, block_hash, parser).collect()) From a54210583e73e9a994e2897722866e72166c34f7 Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Fri, 18 Oct 2024 15:51:08 +0100 Subject: [PATCH 154/224] feat(warpMonitor): Add support for sei-FASTUSD warp monitor (#4702) ### Description - Support sei-ethereum-FastUSD warp monitor - Support xERC20 balance metrics ### Testing Manual --- .../mainnet3/warp/EZETH-deployments.yaml | 2 +- .../warp/sei-FASTUSD-deployments.yaml | 21 ++ .../monitor-warp-routes-balances.ts | 199 +++++++++++------- 3 files changed, 150 insertions(+), 72 deletions(-) create mode 100644 typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml diff --git a/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml index bc90c54bb..b83663645 100644 --- a/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml @@ -9,7 +9,7 @@ data: name: Renzo Restaked ETH symbol: ezETH hypAddress: '0xC59336D8edDa9722B4f1Ec104007191Ec16f7087' - tokenAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5' + tokenAddress: '0xbf5495Efe5DB9ce00f80364C8B423567e58d2110' decimals: 18 bsc: protocolType: ethereum diff --git a/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml new file mode 100644 index 000000000..885c1a4db --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml @@ -0,0 +1,21 @@ +description: Hyperlane Warp Route artifacts +timestamp: '2024-10-17T14:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + ethereum: + protocolType: ethereum + type: collateral + hypAddress: '0x9AD81058c6C3Bf552C9014CB30E824717A0ee21b' + tokenAddress: '0x15700B564Ca08D9439C58cA5053166E8317aa138' + name: fastUSD + symbol: fastUSD + decimals: 18 + sei: + protocolType: ethereum + type: xERC20 + hypAddress: '0xeA895A7Ff45d8d3857A04c1E38A362f3bd9a076f' + tokenAddress: '0x37a4dD9CED2b19Cfe8FAC251cd727b5787E45269' + name: fastUSD + symbol: fastUSD + decimals: 18 diff --git a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts index 160a777f5..3d946a9e6 100644 --- a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts +++ b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts @@ -55,10 +55,11 @@ const xERC20LimitsGauge = new Gauge({ name: 'hyperlane_xerc20_limits', help: 'Current minting and burning limits of xERC20 tokens', registers: [metricsRegister], - labelNames: ['chain_name', 'limit_type'], + labelNames: ['chain_name', 'limit_type', 'token_name'], }); interface xERC20Limit { + tokenName: string; mint: number; burn: number; mintMax: number; @@ -102,18 +103,7 @@ async function main(): Promise { const registry = await envConfig.getRegistry(); const chainMetadata = await registry.getMetadata(); - // TODO: eventually support token balance checks for xERC20 token type also - if ( - Object.values(tokenConfig).some( - (token) => - token.type === TokenType.XERC20 || - token.type === TokenType.XERC20Lockbox, - ) - ) { - await checkXERC20Limits(checkFrequency, tokenConfig, chainMetadata); - } else { - await checkTokenBalances(checkFrequency, tokenConfig, chainMetadata); - } + await checkWarpRouteMetrics(checkFrequency, tokenConfig, chainMetadata); return true; } @@ -136,7 +126,7 @@ async function checkBalance( ethers.utils.formatUnits(nativeBalance, token.decimals), ); } - case ProtocolType.Sealevel: + case ProtocolType.Sealevel: { const adapter = new SealevelHypNativeAdapter( chain, multiProtocolProvider, @@ -155,6 +145,7 @@ async function checkBalance( return parseFloat( ethers.utils.formatUnits(balance, token.decimals), ); + } case ProtocolType.Cosmos: { if (!token.ibcDenom) throw new Error('IBC denom missing for native token'); @@ -245,7 +236,7 @@ async function checkBalance( ethers.utils.formatUnits(syntheticBalance, token.decimals), ); } - case ProtocolType.Sealevel: + case ProtocolType.Sealevel: { if (!token.tokenAddress) throw new Error('Token address missing for synthetic token'); const adapter = new SealevelHypSyntheticAdapter( @@ -265,12 +256,67 @@ async function checkBalance( return parseFloat( ethers.utils.formatUnits(syntheticBalance, token.decimals), ); + } case ProtocolType.Cosmos: // TODO - cosmos synthetic return 0; } break; } + case TokenType.XERC20: { + switch (token.protocolType) { + case ProtocolType.Ethereum: { + const provider = multiProtocolProvider.getEthersV5Provider(chain); + const hypXERC20 = HypXERC20__factory.connect( + token.hypAddress, + provider, + ); + const xerc20Address = await hypXERC20.wrappedToken(); + const xerc20 = IXERC20__factory.connect(xerc20Address, provider); + const syntheticBalance = await xerc20.totalSupply(); + + return parseFloat( + ethers.utils.formatUnits(syntheticBalance, token.decimals), + ); + } + default: + throw new Error( + `Unsupported protocol type ${token.protocolType} for token type ${token.type}`, + ); + } + } + case TokenType.XERC20Lockbox: { + switch (token.protocolType) { + case ProtocolType.Ethereum: { + if (!token.tokenAddress) + throw new Error( + 'Token address missing for xERC20Lockbox token', + ); + const provider = multiProtocolProvider.getEthersV5Provider(chain); + const hypXERC20Lockbox = HypXERC20Lockbox__factory.connect( + token.hypAddress, + provider, + ); + const xerc20LockboxAddress = await hypXERC20Lockbox.lockbox(); + const tokenContract = ERC20__factory.connect( + token.tokenAddress, + provider, + ); + + const collateralBalance = await tokenContract.balanceOf( + xerc20LockboxAddress, + ); + + return parseFloat( + ethers.utils.formatUnits(collateralBalance, token.decimals), + ); + } + default: + throw new Error( + `Unsupported protocol type ${token.protocolType} for token type ${token.type}`, + ); + } + } } return 0; }, @@ -301,46 +347,51 @@ export function updateTokenBalanceMetrics( }); } -export function updateXERC20LimitsMetrics(xERC20Limits: ChainMap) { - objMap(xERC20Limits, (chain: ChainName, limit: xERC20Limit) => { - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'mint', - }) - .set(limit.mint); - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'burn', - }) - .set(limit.burn); - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'mintMax', - }) - .set(limit.mintMax); - xERC20LimitsGauge - .labels({ - chain_name: chain, - limit_type: 'burnMax', - }) - .set(limit.burnMax); - logger.info('xERC20 limits updated for chain', { - chain, - mint: limit.mint, - burn: limit.burn, - mintMax: limit.mintMax, - burnMax: limit.burnMax, - }); +export function updateXERC20LimitsMetrics( + xERC20Limits: ChainMap, +) { + objMap(xERC20Limits, (chain: ChainName, limits: xERC20Limit | undefined) => { + if (limits) { + xERC20LimitsGauge + .labels({ + chain_name: chain, + limit_type: 'mint', + token_name: limits.tokenName, + }) + .set(limits.mint); + xERC20LimitsGauge + .labels({ + chain_name: chain, + limit_type: 'burn', + token_name: limits.tokenName, + }) + .set(limits.burn); + xERC20LimitsGauge + .labels({ + chain_name: chain, + limit_type: 'mintMax', + token_name: limits.tokenName, + }) + .set(limits.mintMax); + xERC20LimitsGauge + .labels({ + chain_name: chain, + limit_type: 'burnMax', + token_name: limits.tokenName, + }) + .set(limits.burnMax); + logger.info('xERC20 limits updated for chain', { + chain, + limits, + }); + } }); } async function getXERC20Limits( tokenConfig: WarpRouteConfig, chainMetadata: ChainMap, -): Promise> { +): Promise> { const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); const output = objMap( @@ -358,7 +409,12 @@ async function getXERC20Limits( ); const xerc20Address = await lockbox.xERC20(); const xerc20 = IXERC20__factory.connect(xerc20Address, provider); - return getXERC20Limit(routerAddress, xerc20, token.decimals); + return getXERC20Limit( + routerAddress, + xerc20, + token.decimals, + token.name, + ); } case TokenType.XERC20: { const provider = multiProtocolProvider.getEthersV5Provider(chain); @@ -369,10 +425,19 @@ async function getXERC20Limits( ); const xerc20Address = await hypXERC20.wrappedToken(); const xerc20 = IXERC20__factory.connect(xerc20Address, provider); - return getXERC20Limit(routerAddress, xerc20, token.decimals); + return getXERC20Limit( + routerAddress, + xerc20, + token.decimals, + token.name, + ); } default: - throw new Error(`Unsupported token type ${token.type}`); + logger.info( + `Unsupported token type ${token.type} for xERC20 limits check on protocol type ${token.protocolType}`, + ); + + return undefined; } } default: @@ -388,12 +453,14 @@ const getXERC20Limit = async ( routerAddress: string, xerc20: IXERC20, decimals: number, + tokenName: string, ): Promise => { const mintCurrent = await xerc20.mintingCurrentLimitOf(routerAddress); const mintMax = await xerc20.mintingMaxLimitOf(routerAddress); const burnCurrent = await xerc20.burningCurrentLimitOf(routerAddress); const burnMax = await xerc20.burningMaxLimitOf(routerAddress); return { + tokenName, mint: parseFloat(ethers.utils.formatUnits(mintCurrent, decimals)), mintMax: parseFloat(ethers.utils.formatUnits(mintMax, decimals)), burn: parseFloat(ethers.utils.formatUnits(burnCurrent, decimals)), @@ -401,37 +468,27 @@ const getXERC20Limit = async ( }; }; -async function checkXERC20Limits( +async function checkWarpRouteMetrics( checkFrequency: number, tokenConfig: WarpRouteConfig, chainMetadata: ChainMap, ) { setInterval(async () => { try { - const xERC20Limits = await getXERC20Limits(tokenConfig, chainMetadata); - logger.info('xERC20 Limits:', xERC20Limits); - updateXERC20LimitsMetrics(xERC20Limits); + const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); + const balances = await checkBalance(tokenConfig, multiProtocolProvider); + logger.info('Token Balances:', balances); + updateTokenBalanceMetrics(tokenConfig, balances); } catch (e) { logger.error('Error checking balances', e); } - }, checkFrequency); -} - -async function checkTokenBalances( - checkFrequency: number, - tokenConfig: WarpRouteConfig, - chainMetadata: ChainMap, -) { - logger.info('Starting Warp Route balance monitor'); - const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); - setInterval(async () => { try { - logger.debug('Checking balances'); - const balances = await checkBalance(tokenConfig, multiProtocolProvider); - updateTokenBalanceMetrics(tokenConfig, balances); + const xERC20Limits = await getXERC20Limits(tokenConfig, chainMetadata); + logger.info('xERC20 Limits:', xERC20Limits); + updateXERC20LimitsMetrics(xERC20Limits); } catch (e) { - logger.error('Error checking balances', e); + logger.error('Error checking xERC20 limits', e); } }, checkFrequency); } From 41035aac8f75dc10fe7b2a50f4451b1a4bdf593b Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:40:14 -0400 Subject: [PATCH 155/224] fix: early strategy detection in warp apply (#4706) ### Description When using `warp apply`, a user may provide a `strategyUrl`. However, they won't know if 1) it's valid, and 2) if it even exists until much later. This adds the detection & validation early. ### Drive-by changes Remove yaml print ### Backward compatibility Yes ### Testing Manual --- .changeset/dry-foxes-battle.md | 6 ++++++ typescript/cli/src/commands/warp.ts | 4 ++++ typescript/cli/src/deploy/warp.ts | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 .changeset/dry-foxes-battle.md diff --git a/.changeset/dry-foxes-battle.md b/.changeset/dry-foxes-battle.md new file mode 100644 index 000000000..eadb8427e --- /dev/null +++ b/.changeset/dry-foxes-battle.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +Add strategyUrl detect and validation in the beginning of `warp apply` +Remove yaml transactions print from `warp apply` diff --git a/typescript/cli/src/commands/warp.ts b/typescript/cli/src/commands/warp.ts index d3bee1e00..107db6850 100644 --- a/typescript/cli/src/commands/warp.ts +++ b/typescript/cli/src/commands/warp.ts @@ -9,6 +9,7 @@ import { } from '@hyperlane-xyz/core'; import { ChainMap, + ChainSubmissionStrategySchema, EvmERC20WarpRouteReader, TokenStandard, WarpCoreConfig, @@ -30,6 +31,7 @@ import { log, logGray, logGreen, logRed, logTable } from '../logger.js'; import { sendTestTransfer } from '../send/transfer.js'; import { indentYamlOrJson, + readYamlOrJson, removeEndingSlash, writeYamlOrJson, } from '../utils/files.js'; @@ -113,6 +115,8 @@ export const apply: CommandModuleWithWriteContext<{ logRed(`Please specify either a symbol or warp config`); process.exit(0); } + if (strategyUrl) + ChainSubmissionStrategySchema.parse(readYamlOrJson(strategyUrl)); const warpDeployConfig = await readWarpRouteDeployConfig(config); await runWarpRouteApply({ diff --git a/typescript/cli/src/deploy/warp.ts b/typescript/cli/src/deploy/warp.ts index 872edb400..36bbc2ad8 100644 --- a/typescript/cli/src/deploy/warp.ts +++ b/typescript/cli/src/deploy/warp.ts @@ -848,11 +848,6 @@ async function submitWarpApplyTransactions( `Transactions receipts successfully written to ${receiptPath}`, ); } - - logGreen( - `✅ Warp route update success with ${submitter.txSubmitterType} on ${chain}:\n\n`, - indentYamlOrJson(yamlStringify(transactionReceipts, null, 2), 0), - ); }), ); } From 0b901886cb745c944cb107e9df55164863d0357a Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Fri, 18 Oct 2024 17:13:12 +0100 Subject: [PATCH 156/224] feat(warpMonitor): Support Lumia bsc-lumia-ethereum warp monitor service (#4709) ### Description - Support Lumia bsc-lumia-ethereum warp monitor service ### Testing Manual --- .../warp/bsc-lumia-LUMIA-deployments.yaml | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml diff --git a/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml new file mode 100644 index 000000000..9db075248 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml @@ -0,0 +1,29 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +# Between Ethereum and Binance Smart Chain and Lumia +description: Hyperlane Warp Route artifacts +timestamp: '2024-10-18T14:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + ethereum: + protocolType: ethereum + type: collateral + hypAddress: '0xdD313D475f8A9d81CBE2eA953a357f52e10BA357' + tokenAddress: '0xd9343a049d5dbd89cd19dc6bca8c48fb3a0a42a7' + name: Lumia Token + symbol: LUMIA + decimals: 18 + bsc: + protocolType: ethereum + type: synthetic + hypAddress: '0x7F39BcdCa8E0E581c1d43aaa1cB862AA1c8C2047' + name: Lumia Token + symbol: LUMIA + decimals: 18 + lumia: + protocolType: ethereum + type: native + hypAddress: '0x6a77331cE28E47c3Cb9Fea48AB6cD1e9594ce0A9' + name: Lumia Token + symbol: LUMIA + decimals: 18 From eeae55bf95003fd440f0c19008024d6a789ceef8 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Mon, 21 Oct 2024 10:30:04 +0100 Subject: [PATCH 157/224] feat: Upgrade scraper (#4708) ### Description Add logging for debugging ### Backward compatibility Yes ### Testing Locally Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- typescript/infra/config/environments/mainnet3/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index a470b1c87..6b6f2bae5 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -437,7 +437,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'efd438f-20241016-101828', + tag: '9c0c4bb-20241018-113820', }, resources: scraperResources, }, From 02a5b92ba774c3ce8c706966c9b9f23272215fa5 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:57:44 +0100 Subject: [PATCH 158/224] feat: enroll new chains + validators on default ISMs (#4694) ### Description feat: enroll new chains + validators on default ISMs - migrate new chains to ICAs - migrate some existing SAFE owned chains to ICAs - ensure defaultHook on inevm is made hot again - add J to safe signers ### Drive-by changes - IGP gas/token price updates - add tx overrides when deploying ICA accounts - swap out A for J on safe signers - add support for updating owners when doing a safe multisend - add support for checking and surfacing defaulthook/requiredhook owner violations - improve logging + skip bytecode mismatches for now - parallelise call inference in base app governor - parallelise deployment of ICAs in get-owner-ica.ts - reuse existing configured gasPrices for sealevel chains ### Related issues na ### Backward compatibility yes ### Testing will be testing as part of check-deploy --- .changeset/few-goats-add.md | 5 + .../config/environments/mainnet3/chains.ts | 7 +- .../environments/mainnet3/gasPrices.json | 28 ++-- .../config/environments/mainnet3/owners.ts | 40 ++++- .../mainnet3/safe/safeSigners.json | 2 +- .../environments/mainnet3/tokenPrices.json | 138 +++++++++--------- typescript/infra/scripts/get-owner-ica.ts | 57 ++++++-- typescript/infra/scripts/print-gas-prices.ts | 24 ++- .../infra/src/govern/HyperlaneAppGovernor.ts | 55 +++++-- .../infra/src/govern/HyperlaneCoreGovernor.ts | 6 +- .../infra/src/govern/HyperlaneIgpGovernor.ts | 6 +- typescript/infra/src/utils/safe.ts | 54 ++++++- typescript/sdk/src/consts/multisigIsm.ts | 80 +++++++--- .../sdk/src/core/HyperlaneCoreChecker.ts | 49 ++++++- .../sdk/src/deploy/HyperlaneAppChecker.ts | 7 +- .../middleware/account/InterchainAccount.ts | 3 + 16 files changed, 411 insertions(+), 150 deletions(-) create mode 100644 .changeset/few-goats-add.md diff --git a/.changeset/few-goats-add.md b/.changeset/few-goats-add.md new file mode 100644 index 000000000..ffcab1f49 --- /dev/null +++ b/.changeset/few-goats-add.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Enroll new validators. Add tx overrides when deploying ICA accounts. Core checker now surfaces owner violations for defaultHook and requiredHook. App checker temporarily ignores bytecode mismatch violations. diff --git a/typescript/infra/config/environments/mainnet3/chains.ts b/typescript/infra/config/environments/mainnet3/chains.ts index e4d7f774f..b32fdeff1 100644 --- a/typescript/infra/config/environments/mainnet3/chains.ts +++ b/typescript/infra/config/environments/mainnet3/chains.ts @@ -59,12 +59,17 @@ export const chainMetadataOverrides: ChainMap> = { // gasLimit: 6800000, // set when deploying contracts }, }, - // set when deploying contracts + // Deploy-only overrides, set when deploying contracts // chiliz: { // transactionOverrides: { // maxFeePerGas: 100000 * 10 ** 9, // 100,000 gwei // }, // }, + // zircuit: { + // blocks: { + // confirmations: 3, + // }, + // }, }; export const getRegistry = async (useSecrets = true): Promise => diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 81e8ae1ef..d68a6d290 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -24,7 +24,7 @@ "decimals": 9 }, "base": { - "amount": "0.008669818", + "amount": "0.015396226", "decimals": 9 }, "bitlayer": { @@ -32,7 +32,7 @@ "decimals": 9 }, "blast": { - "amount": "0.004707204", + "amount": "0.005712307", "decimals": 9 }, "bob": { @@ -72,15 +72,15 @@ "decimals": 9 }, "eclipsemainnet": { - "amount": "0.001", - "decimals": 9 + "amount": "0.0000001", + "decimals": 1 }, "endurance": { "amount": "3.0756015", "decimals": 9 }, "ethereum": { - "amount": "21.610477208", + "amount": "14.852716956", "decimals": 9 }, "everclear": { @@ -88,11 +88,11 @@ "decimals": 9 }, "flare": { - "amount": "29.55878872", + "amount": "49.455765643", "decimals": 9 }, "flow": { - "amount": "0.0000001", + "amount": "0.1", "decimals": 9 }, "fraxtal": { @@ -104,11 +104,11 @@ "decimals": 9 }, "gnosis": { - "amount": "2.000000007", + "amount": "1.500000007", "decimals": 9 }, "immutablezkevm": { - "amount": "10.00000005", + "amount": "10.1", "decimals": 9 }, "inevm": { @@ -124,7 +124,7 @@ "decimals": 9 }, "linea": { - "amount": "0.240000007", + "amount": "0.243", "decimals": 9 }, "lisk": { @@ -156,7 +156,7 @@ "decimals": 9 }, "metis": { - "amount": "1.247735823", + "amount": "1.278943587", "decimals": 9 }, "mint": { @@ -236,12 +236,12 @@ "decimals": 9 }, "shibarium": { - "amount": "28.138673121", + "amount": "39.319461243", "decimals": 9 }, "solanamainnet": { - "amount": "0.001", - "decimals": 9 + "amount": "0.5", + "decimals": 1 }, "superposition": { "amount": "0.01", diff --git a/typescript/infra/config/environments/mainnet3/owners.ts b/typescript/infra/config/environments/mainnet3/owners.ts index 66cd8d17d..e32d8961c 100644 --- a/typescript/infra/config/environments/mainnet3/owners.ts +++ b/typescript/infra/config/environments/mainnet3/owners.ts @@ -68,13 +68,14 @@ export const icas: Partial< inevm: '0xFDF9EDcb2243D51f5f317b9CEcA8edD2bEEE036e', // Jul 26, 2024 batch - // ------------------------------------- + // ---------------------------------------------------------- xlayer: '0x1571c482fe9E76bbf50829912b1c746792966369', cheesechain: '0xEe2C5320BE9bC7A1492187cfb289953b53E3ff1b', worldchain: '0x1996DbFcFB433737fE404F58D2c32A7f5f334210', // zircuit: '0x0d67c56E818a02ABa58cd2394b95EF26db999aA3', // already has a safe // Aug 5, 2024 batch + // ---------------------------------------------------------- cyber: '0x984Fe5a45Ac4aaeC4E4655b50f776aB79c9Be19F', degenchain: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A', kroma: '0xc1e20A0D78E79B94D71d4bDBC8FD0Af7c856Dd7A', @@ -88,9 +89,10 @@ export const icas: Partial< sanko: '0x5DAcd2f1AafC749F2935A160865Ab1568eC23752', tangle: '0xCC2aeb692197C7894E561d31ADFE8F79746f7d9F', xai: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A', - // taiko: '0x483D218D2FEe7FC7204ba15F00C7901acbF9697D', // already has a safe + // taiko: '0x483D218D2FEe7FC7204ba15F00C7901acbF9697D', // renzo chain // Aug 26, 2024 batch + // ---------------------------------------------------------- astar: '0x6b241544eBa7d89B51b72DF85a0342dAa37371Ca', astarzkevm: '0x526c6DAee1175A1A2337E703B63593acb327Dde4', bitlayer: '0xe6239316cA60814229E801fF0B9DD71C9CA29008', @@ -101,9 +103,41 @@ export const icas: Partial< shibarium: '0x6348FAe3a8374dbAAaE84EEe5458AE4063Fe2be7', // Sep 9, 2024 batch - // ---------------------------- + // ---------------------------------------------------------- everclear: '0x63B2075372D6d0565F51210D0A296D3c8a773aB6', oortmainnet: '0x7021D11F9fAe455AB2f45D72dbc2C64d116Cb657', + + // Sep 19, 2024 SAFE --> ICA v1 Migration + // ---------------------------------------------------------- + celo: '0x3fA264c58E1365f1d5963B831b864EcdD2ddD19b', + avalanche: '0x8c8695cD9905e22d84E466804ABE55408A87e595', + polygon: '0xBDD25dd5203fedE33FD631e30fEF9b9eF2598ECE', + moonbeam: '0x480e5b5De6a29F07fe8295C60A1845d36b7BfdE6', + gnosis: '0xD42125a4889A7A36F32d7D12bFa0ae52B0AD106b', + scroll: '0x2a3fe2513F4A7813683d480724AB0a3683EfF8AC', + polygonzkevm: '0x66037De438a59C966214B78c1d377c4e93a5C7D1', + ancient8: '0xA9FD5BeB556AB1859D7625B381110a257f56F98C', + redstone: '0x5DAcd2f1AafC749F2935A160865Ab1568eC23752', + mantle: '0x08C880b88335CA3e85Ebb4E461245a7e899863c9', + bob: '0xc99e58b9A4E330e2E4d09e2c94CD3c553904F588', + zetachain: '0xc876B8e63c3ff5b636d9492715BE375644CaD345', + zoramainnet: '0x84977Eb15E0ff5824a6129c789F70e88352C230b', + fusemainnet: '0xbBdb1682B2922C282b56DD716C29db5EFbdb5632', + endurance: '0x470E04D8a3b7938b385093B93CeBd8Db7A1E557C', + // sei: '0xabad187003EdeDd6C720Fc633f929EA632996567', // renzo chain + + // Oct 16, 2024 batch + // ---------------------------------------------------------- + immutablezkevm: '0x8483e1480B62cB9f0aCecEbF42469b9f4013577a', + rari: '0x1124D54E989570A798769E534eAFbE1444f40AF6', + rootstock: '0x69350aeA98c5195F2c3cC6E6A065d0d8B12F659A', + alephzeroevm: '0x004a4C2e4Cd4F5Bd564fe0A6Ab2Da56258aE576f', + chiliz: '0xb52D281aD2BA9761c16f400d755837493e2baDB7', + lumia: '0x418E10Ac9e0b84022d0636228d05bc74172e0e41', + superposition: '0x34b57ff8fBA8da0cFdA795CC0F874FfaB14B1DE9', + flow: '0xf48377f8A3ddA7AAD7C2460C81d939434c829b45', + metall2: '0x2f1b1B0Fb7652E621316460f6c3b019F61d8dC9a', + polynomial: '0xC20eFa1e5A378af9233e9b24515eb3408d43f900', } as const; export const DEPLOYER = '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba'; diff --git a/typescript/infra/config/environments/mainnet3/safe/safeSigners.json b/typescript/infra/config/environments/mainnet3/safe/safeSigners.json index d66b992ab..fca35815f 100644 --- a/typescript/infra/config/environments/mainnet3/safe/safeSigners.json +++ b/typescript/infra/config/environments/mainnet3/safe/safeSigners.json @@ -3,7 +3,7 @@ "0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba", "0xc3E966E79eF1aA4751221F55fB8A36589C24C0cA", "0x3b7f8f68A4FD0420FeA2F42a1eFc53422f205599", - "0x88436919fAa2310d32A36D20d13E0a441D24fAc3", + "0x478be6076f31E9666123B9721D0B6631baD944AF", "0x003DDD9eEAb62013b7332Ab4CC6B10077a8ca961", "0xd00d6A31485C93c597D1d8231eeeE0ed17B9844B", "0x483fd7284A696343FEc0819DDF2cf7E06E8A06E5", diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index 5cbf8f157..df245702e 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -1,73 +1,73 @@ { - "ancient8": "2437.96", - "alephzeroevm": "0.36741", - "arbitrum": "2437.96", - "astar": "0.059165", - "astarzkevm": "2437.96", - "avalanche": "26.77", - "base": "2437.96", - "bitlayer": "62244", - "blast": "2437.96", - "bob": "2437.96", - "bsc": "572.12", - "celo": "0.764821", - "cheesechain": "0.00448064", - "chiliz": "0.069844", - "coredao": "0.912209", - "cyber": "2437.96", - "degenchain": "0.00934571", - "dogechain": "0.110085", - "eclipsemainnet": "2437.96", - "endurance": "2.11", - "ethereum": "2437.96", - "everclear": "2437.96", - "flare": "0.01456139", - "flow": "0.533589", - "fraxtal": "2434.37", - "fusemainnet": "0.02952521", - "gnosis": "1.009", - "immutablezkevm": "1.48", - "inevm": "20.24", - "injective": "20.24", - "kroma": "2437.96", - "linea": "2437.96", - "lisk": "2437.96", - "lukso": "1.51", - "lumia": "0.954153", - "mantapacific": "2437.96", - "mantle": "0.59813", - "merlin": "62293", - "metall2": "2437.96", - "metis": "34.53", - "mint": "2437.96", - "mode": "2437.96", - "molten": "0.632429", - "moonbeam": "0.163919", - "neutron": "0.390086", - "oortmainnet": "0.11645", - "optimism": "2437.96", - "osmosis": "0.521323", - "polygon": "0.371959", - "polygonzkevm": "2437.96", - "polynomial": "2437.96", - "proofofplay": "2437.96", - "rari": "2437.96", + "ancient8": "2629.74", + "alephzeroevm": "0.381786", + "arbitrum": "2629.74", + "astar": "0.061114", + "astarzkevm": "2629.74", + "avalanche": "27.96", + "base": "2629.74", + "bitlayer": "67813", + "blast": "2629.74", + "bob": "2629.74", + "bsc": "597.89", + "celo": "0.817141", + "cheesechain": "0.00556724", + "chiliz": "0.079288", + "coredao": "0.98348", + "cyber": "2629.74", + "degenchain": "0.00882961", + "dogechain": "0.126177", + "eclipsemainnet": "2629.74", + "endurance": "2.16", + "ethereum": "2629.74", + "everclear": "2629.74", + "flare": "0.01493582", + "flow": "0.558323", + "fraxtal": "2629.35", + "fusemainnet": "0.02901498", + "gnosis": "0.997404", + "immutablezkevm": "1.54", + "inevm": "21.05", + "injective": "21.05", + "kroma": "2629.74", + "linea": "2629.74", + "lisk": "2629.74", + "lukso": "1.47", + "lumia": "0.969511", + "mantapacific": "2629.74", + "mantle": "0.636484", + "merlin": "67781", + "metall2": "2629.74", + "metis": "45.78", + "mint": "2629.74", + "mode": "2629.74", + "molten": "0.436605", + "moonbeam": "0.169406", + "neutron": "0.408859", + "oortmainnet": "0.114304", + "optimism": "2629.74", + "osmosis": "0.558566", + "polygon": "0.371646", + "polygonzkevm": "2629.74", + "polynomial": "2629.74", + "proofofplay": "2629.74", + "rari": "2629.74", "real": "1", - "redstone": "2437.96", - "rootstock": "61812", - "sanko": "41.59", - "scroll": "2437.96", - "sei": "0.444401", - "shibarium": "0.404651", - "solanamainnet": "144.84", - "superposition": "2437.96", - "taiko": "2437.96", + "redstone": "2629.74", + "rootstock": "67219", + "sanko": "70.7", + "scroll": "2629.74", + "sei": "0.447635", + "shibarium": "0.410927", + "solanamainnet": "155.35", + "superposition": "2629.74", + "taiko": "2629.74", "tangle": "1", - "viction": "0.359062", - "worldchain": "2437.96", - "xai": "0.215315", - "xlayer": "42.29", - "zetachain": "0.581304", - "zircuit": "2437.96", - "zoramainnet": "2437.96" + "viction": "0.369839", + "worldchain": "2629.74", + "xai": "0.216438", + "xlayer": "41.56", + "zetachain": "0.617959", + "zircuit": "2629.74", + "zoramainnet": "2629.74" } diff --git a/typescript/infra/scripts/get-owner-ica.ts b/typescript/infra/scripts/get-owner-ica.ts index e4ea61a7b..91c7ec9a8 100644 --- a/typescript/infra/scripts/get-owner-ica.ts +++ b/typescript/infra/scripts/get-owner-ica.ts @@ -1,11 +1,13 @@ import { AccountConfig, InterchainAccount } from '@hyperlane-xyz/sdk'; -import { Address, assert, eqAddress } from '@hyperlane-xyz/utils'; +import { Address, eqAddress } from '@hyperlane-xyz/utils'; -import { getArgs as getEnvArgs, withChainsRequired } from './agent-utils.js'; +import { isEthereumProtocolChain } from '../src/utils/utils.js'; + +import { getArgs as getEnvArgs, withChains } from './agent-utils.js'; import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js'; function getArgs() { - return withChainsRequired(getEnvArgs()) + return withChains(getEnvArgs()) .option('ownerChain', { type: 'string', description: 'Origin chain where the governing owner lives', @@ -51,20 +53,47 @@ async function main() { owner: originOwner, }; + const getOwnerIcaChains = ( + chains?.length ? chains : config.supportedChainNames + ).filter(isEthereumProtocolChain); + const results: Record = {}; - for (const chain of chains) { - const account = await ica.getAccount(chain, ownerConfig); - results[chain] = { ICA: account }; + const settledResults = await Promise.allSettled( + getOwnerIcaChains.map(async (chain) => { + try { + const account = await ica.getAccount(chain, ownerConfig); + const result: { ICA: Address; Deployed?: string } = { ICA: account }; + + if (deploy) { + const deployedAccount = await ica.deployAccount(chain, ownerConfig); + result.Deployed = eqAddress(account, deployedAccount) ? '✅' : '❌'; + if (result.Deployed === '❌') { + console.warn( + `Mismatch between account and deployed account for ${chain}`, + ); + } + } - if (deploy) { - const deployedAccount = await ica.deployAccount(chain, ownerConfig); - assert( - eqAddress(account, deployedAccount), - 'Fatal mismatch between account and deployed account', - ); - results[chain].Deployed = '✅'; + return { chain, result }; + } catch (error) { + console.error(`Error processing chain ${chain}:`, error); + return { chain, error }; + } + }), + ); + + settledResults.forEach((settledResult) => { + if (settledResult.status === 'fulfilled') { + const { chain, result, error } = settledResult.value; + if (error || !result) { + console.error(`Failed to process ${chain}:`, error); + } else { + results[chain] = result; + } + } else { + console.error(`Promise rejected:`, settledResult.reason); } - } + }); console.table(results); } diff --git a/typescript/infra/scripts/print-gas-prices.ts b/typescript/infra/scripts/print-gas-prices.ts index 805122ad1..bbe15c7b1 100644 --- a/typescript/infra/scripts/print-gas-prices.ts +++ b/typescript/infra/scripts/print-gas-prices.ts @@ -7,8 +7,10 @@ import { ProtocolType } from '@hyperlane-xyz/utils'; // Intentionally circumvent `mainnet3/index.ts` and `getEnvironmentConfig('mainnet3')` // to avoid circular dependencies. import { getRegistry as getMainnet3Registry } from '../config/environments/mainnet3/chains.js'; +import mainnet3GasPrices from '../config/environments/mainnet3/gasPrices.json' assert { type: 'json' }; import { supportedChainNames as mainnet3SupportedChainNames } from '../config/environments/mainnet3/supportedChainNames.js'; import { getRegistry as getTestnet4Registry } from '../config/environments/testnet4/chains.js'; +import testnet4GasPrices from '../config/environments/testnet4/gasPrices.json' assert { type: 'json' }; import { supportedChainNames as testnet4SupportedChainNames } from '../config/environments/testnet4/supportedChainNames.js'; import { GasPriceConfig, @@ -19,15 +21,17 @@ import { getArgs } from './agent-utils.js'; async function main() { const { environment } = await getArgs().argv; - const { registry, supportedChainNames } = + const { registry, supportedChainNames, gasPrices } = environment === 'mainnet3' ? { registry: await getMainnet3Registry(), supportedChainNames: mainnet3SupportedChainNames, + gasPrices: mainnet3GasPrices, } : { registry: await getTestnet4Registry(), supportedChainNames: testnet4SupportedChainNames, + gasPrices: testnet4GasPrices, }; const chainMetadata = await registry.getMetadata(); @@ -37,7 +41,11 @@ async function main() { await Promise.all( supportedChainNames.map(async (chain) => [ chain, - await getGasPrice(mpp, chain), + await getGasPrice( + mpp, + chain, + gasPrices[chain as keyof typeof gasPrices], + ), ]), ), ); @@ -48,6 +56,7 @@ async function main() { async function getGasPrice( mpp: MultiProtocolProvider, chain: string, + currentGasPrice?: GasPriceConfig, ): Promise { const protocolType = mpp.getProtocol(chain); switch (protocolType) { @@ -68,11 +77,14 @@ async function getGasPrice( }; } case ProtocolType.Sealevel: + // Return the gas price from the config if it exists, otherwise return some default // TODO get a reasonable value - return { - amount: '0.001', - decimals: 9, - }; + return ( + currentGasPrice ?? { + amount: 'PLEASE SET A GAS PRICE FOR SEALEVEL', + decimals: 1, + } + ); default: throw new Error(`Unsupported protocol type: ${protocolType}`); } diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index 6df9d3551..d35a1499f 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -26,6 +26,8 @@ import { retryAsync, } from '@hyperlane-xyz/utils'; +import { getSafeAndService, updateSafeOwner } from '../utils/safe.js'; + import { ManualMultiSend, MultiSend, @@ -159,7 +161,22 @@ export abstract class HyperlaneAppGovernor< submissionType: SubmissionType, multiSend: MultiSend, ) => { - const callsForSubmissionType = filterCalls(submissionType) || []; + const callsForSubmissionType = []; + const filteredCalls = filterCalls(submissionType); + + // If calls are being submitted via a safe, we need to check for any safe owner changes first + if (submissionType === SubmissionType.SAFE) { + const { safeSdk } = await getSafeAndService( + chain, + this.checker.multiProvider, + (multiSend as SafeMultiSend).safeAddress, + ); + const updateOwnerCalls = await updateSafeOwner(safeSdk); + callsForSubmissionType.push(...updateOwnerCalls, ...filteredCalls); + } else { + callsForSubmissionType.push(...filteredCalls); + } + if (callsForSubmissionType.length > 0) { this.printSeparator(); const confirmed = await summarizeCalls( @@ -257,7 +274,6 @@ export abstract class HyperlaneAppGovernor< protected async inferCallSubmissionTypes() { const newCalls: ChainMap = {}; - const pushNewCall = (inferredCall: InferredCall) => { newCalls[inferredCall.chain] = newCalls[inferredCall.chain] || []; newCalls[inferredCall.chain].push({ @@ -267,20 +283,29 @@ export abstract class HyperlaneAppGovernor< }); }; - for (const chain of Object.keys(this.calls)) { - try { - for (const call of this.calls[chain]) { - const inferredCall = await this.inferCallSubmissionType(chain, call); - pushNewCall(inferredCall); + const results: ChainMap = {}; + await Promise.all( + Object.keys(this.calls).map(async (chain) => { + try { + results[chain] = await Promise.all( + this.calls[chain].map((call) => + this.inferCallSubmissionType(chain, call), + ), + ); + } catch (error) { + console.error( + chalk.red( + `Error inferring call submission types for chain ${chain}: ${error}`, + ), + ); + results[chain] = []; } - } catch (error) { - console.error( - chalk.red( - `Error inferring call submission types for chain ${chain}: ${error}`, - ), - ); - } - } + }), + ); + + Object.entries(results).forEach(([_, inferredCalls]) => { + inferredCalls.forEach(pushNewCall); + }); this.calls = newCalls; } diff --git a/typescript/infra/src/govern/HyperlaneCoreGovernor.ts b/typescript/infra/src/govern/HyperlaneCoreGovernor.ts index b6df69f4f..f4b9c7455 100644 --- a/typescript/infra/src/govern/HyperlaneCoreGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneCoreGovernor.ts @@ -84,7 +84,11 @@ export class HyperlaneCoreGovernor extends HyperlaneAppGovernor< return this.handleProxyAdminViolation(violation as ProxyAdminViolation); } default: - throw new Error(`Unsupported violation type ${violation.type}`); + throw new Error( + `Unsupported violation type ${violation.type}: ${JSON.stringify( + violation, + )}`, + ); } } } diff --git a/typescript/infra/src/govern/HyperlaneIgpGovernor.ts b/typescript/infra/src/govern/HyperlaneIgpGovernor.ts index 592301d9b..30528d230 100644 --- a/typescript/infra/src/govern/HyperlaneIgpGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneIgpGovernor.ts @@ -29,7 +29,11 @@ export class HyperlaneIgpGovernor extends HyperlaneAppGovernor< return super.handleOwnerViolation(violation as OwnerViolation); } default: - throw new Error(`Unsupported violation type ${violation.type}`); + throw new Error( + `Unsupported violation type ${violation.type}: ${JSON.stringify( + violation, + )}`, + ); } } diff --git a/typescript/infra/src/utils/safe.ts b/typescript/infra/src/utils/safe.ts index ad2104ddb..fc03e9366 100644 --- a/typescript/infra/src/utils/safe.ts +++ b/typescript/infra/src/utils/safe.ts @@ -6,7 +6,7 @@ import { SafeTransaction, } from '@safe-global/safe-core-sdk-types'; import chalk from 'chalk'; -import { ethers } from 'ethers'; +import { BigNumber, ethers } from 'ethers'; import { ChainNameOrId, @@ -14,7 +14,10 @@ import { getSafe, getSafeService, } from '@hyperlane-xyz/sdk'; -import { Address, CallData } from '@hyperlane-xyz/utils'; +import { Address, CallData, eqAddress } from '@hyperlane-xyz/utils'; + +import safeSigners from '../../config/environments/mainnet3/safe/safeSigners.json' assert { type: 'json' }; +import { AnnotatedCallData } from '../govern/HyperlaneAppGovernor.js'; export async function getSafeAndService( chain: ChainNameOrId, @@ -222,3 +225,50 @@ export async function deleteSafeTx( ); } } + +export async function updateSafeOwner( + safeSdk: Safe.default, +): Promise { + const threshold = await safeSdk.getThreshold(); + const owners = await safeSdk.getOwners(); + const newOwners = safeSigners.signers; + const ownersToRemove = owners.filter( + (owner) => !newOwners.some((newOwner) => eqAddress(owner, newOwner)), + ); + const ownersToAdd = newOwners.filter( + (newOwner) => !owners.some((owner) => eqAddress(newOwner, owner)), + ); + + console.log(chalk.magentaBright('Owners to remove:', ownersToRemove)); + console.log(chalk.magentaBright('Owners to add:', ownersToAdd)); + + const transactions: AnnotatedCallData[] = []; + + for (const ownerToRemove of ownersToRemove) { + const { data: removeTxData } = await safeSdk.createRemoveOwnerTx({ + ownerAddress: ownerToRemove, + threshold, + }); + transactions.push({ + to: removeTxData.to, + data: removeTxData.data, + value: BigNumber.from(removeTxData.value), + description: `Remove safe owner ${ownerToRemove}`, + }); + } + + for (const ownerToAdd of ownersToAdd) { + const { data: addTxData } = await safeSdk.createAddOwnerTx({ + ownerAddress: ownerToAdd, + threshold, + }); + transactions.push({ + to: addTxData.to, + data: addTxData.data, + value: BigNumber.from(addTxData.value), + description: `Add safe owner ${ownerToAdd}`, + }); + } + + return transactions; +} diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index 0a8806bde..5184a4b9e 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -4,8 +4,12 @@ import { ChainMap } from '../types.js'; // TODO: consider migrating these to the registry too export const defaultMultisigConfigs: ChainMap = { alephzeroevm: { - threshold: 1, - validators: ['0xcae8fab142adc4e434bb7409e40dd932cc3851aa'], + threshold: 2, + validators: [ + '0xcae8fab142adc4e434bb7409e40dd932cc3851aa', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, alfajores: { @@ -175,8 +179,12 @@ export const defaultMultisigConfigs: ChainMap = { }, chiliz: { - threshold: 1, - validators: ['0x82d024f453b1a3f3f6606226f06b038da27596f3'], + threshold: 2, + validators: [ + '0x82d024f453b1a3f3f6606226f06b038da27596f3', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, citreatestnet: { @@ -286,8 +294,12 @@ export const defaultMultisigConfigs: ChainMap = { }, flow: { - threshold: 1, - validators: ['0x3aee1090318e9c54d1d23194dcd0f2bee00ddc97'], + threshold: 2, + validators: [ + '0x3aee1090318e9c54d1d23194dcd0f2bee00ddc97', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, formtestnet: { @@ -343,8 +355,12 @@ export const defaultMultisigConfigs: ChainMap = { }, immutablezkevm: { - threshold: 1, - validators: ['0xa787c2952a4d22f776ee6e87e828e6f75de24330'], + threshold: 2, + validators: [ + '0xa787c2952a4d22f776ee6e87e828e6f75de24330', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, inevm: { @@ -402,8 +418,12 @@ export const defaultMultisigConfigs: ChainMap = { }, lumia: { - threshold: 1, - validators: ['0x9e283254ed2cd2c80f007348c2822fc8e5c2fa5f'], + threshold: 2, + validators: [ + '0x9e283254ed2cd2c80f007348c2822fc8e5c2fa5f', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, mantapacific: { @@ -438,8 +458,12 @@ export const defaultMultisigConfigs: ChainMap = { }, metall2: { - threshold: 1, - validators: ['0x1b000e1e1f0a032ed382c6d69a2d58f6fe773c09'], + threshold: 2, + validators: [ + '0x1b000e1e1f0a032ed382c6d69a2d58f6fe773c09', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, metis: { @@ -567,8 +591,12 @@ export const defaultMultisigConfigs: ChainMap = { }, polynomial: { - threshold: 1, - validators: ['0xa63ad0891e921ad5947d57e05831fabb9816eca7'], + threshold: 2, + validators: [ + '0xa63ad0891e921ad5947d57e05831fabb9816eca7', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, proofofplay: { @@ -581,8 +609,12 @@ export const defaultMultisigConfigs: ChainMap = { }, rari: { - threshold: 1, - validators: ['0x989d6862e09de21337078efbd86843a3eb1133e3'], + threshold: 2, + validators: [ + '0x989d6862e09de21337078efbd86843a3eb1133e3', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, real: { @@ -604,8 +636,12 @@ export const defaultMultisigConfigs: ChainMap = { }, rootstock: { - threshold: 1, - validators: ['0xcb8e3a72cf427feff27416d0e2ec375a052eaaee'], + threshold: 2, + validators: [ + '0xcb8e3a72cf427feff27416d0e2ec375a052eaaee', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, sanko: { @@ -721,8 +757,12 @@ export const defaultMultisigConfigs: ChainMap = { }, superposition: { - threshold: 1, - validators: ['0x5978d0e6afa9270ddb87cff43a8fa7a763a5dfc4'], + threshold: 2, + validators: [ + '0x5978d0e6afa9270ddb87cff43a8fa7a763a5dfc4', + '0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f', // merkly + '0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis + ], }, superpositiontestnet: { diff --git a/typescript/sdk/src/core/HyperlaneCoreChecker.ts b/typescript/sdk/src/core/HyperlaneCoreChecker.ts index cb7bb9046..82a26c405 100644 --- a/typescript/sdk/src/core/HyperlaneCoreChecker.ts +++ b/typescript/sdk/src/core/HyperlaneCoreChecker.ts @@ -1,10 +1,12 @@ import { ethers, utils as ethersUtils } from 'ethers'; +import { Ownable__factory } from '@hyperlane-xyz/core'; import { assert, eqAddress, rootLogger } from '@hyperlane-xyz/utils'; import { BytecodeHash } from '../consts/bytecode.js'; import { HyperlaneAppChecker } from '../deploy/HyperlaneAppChecker.js'; import { proxyImplementation } from '../deploy/proxy.js'; +import { OwnerViolation, ViolationType } from '../deploy/types.js'; import { DerivedIsmConfig, EvmIsmReader } from '../ism/EvmIsmReader.js'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js'; import { collectValidators, moduleMatchesConfig } from '../ism/utils.js'; @@ -66,6 +68,31 @@ export class HyperlaneCoreChecker extends HyperlaneAppChecker< return this.checkOwnership(chain, config.owner, config.ownerOverrides); } + async checkHook( + chain: ChainName, + hookName: string, + hookAddress: string, + expectedHookOwner: string, + ): Promise { + const hook = Ownable__factory.connect( + hookAddress, + this.multiProvider.getProvider(chain), + ); + const hookOwner = await hook.owner(); + + if (!eqAddress(hookOwner, expectedHookOwner)) { + const violation: OwnerViolation = { + type: ViolationType.Owner, + chain, + name: hookName, + actual: hookOwner, + expected: expectedHookOwner, + contract: hook, + }; + this.addViolation(violation); + } + } + async checkMailbox(chain: ChainName): Promise { const contracts = this.app.getContracts(chain); const mailbox = contracts.mailbox; @@ -77,9 +104,27 @@ export class HyperlaneCoreChecker extends HyperlaneAppChecker< )} for ${chain}`, ); - const actualIsmAddress = await mailbox.defaultIsm(); - const config = this.configMap[chain]; + const expectedHookOwner = this.getOwner( + config.owner, + 'fallbackRoutingHook', + config.ownerOverrides, + ); + + await this.checkHook( + chain, + 'defaultHook', + await mailbox.defaultHook(), + expectedHookOwner, + ); + await this.checkHook( + chain, + 'requiredHook', + await mailbox.requiredHook(), + expectedHookOwner, + ); + + const actualIsmAddress = await mailbox.defaultIsm(); const matches = await moduleMatchesConfig( chain, actualIsmAddress, diff --git a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts index 9a9bf4bcc..55f288f08 100644 --- a/typescript/sdk/src/deploy/HyperlaneAppChecker.ts +++ b/typescript/sdk/src/deploy/HyperlaneAppChecker.ts @@ -12,6 +12,7 @@ import { eqAddress, objMap, promiseObjAll, + rootLogger, } from '@hyperlane-xyz/utils'; import { HyperlaneApp } from '../app/HyperlaneApp.js'; @@ -82,6 +83,10 @@ export abstract class HyperlaneAppChecker< } addViolation(violation: CheckerViolation): void { + if (violation.type === ViolationType.BytecodeMismatch) { + rootLogger.warn({ violation }, `Found bytecode mismatch. Ignoring...`); + return; + } this.violations.push(violation); } @@ -208,7 +213,7 @@ export abstract class HyperlaneAppChecker< return bytecode.substring(0, bytecode.length - 90); } - private getOwner( + protected getOwner( owner: Address, contractName: string, ownableOverrides?: Record, diff --git a/typescript/sdk/src/middleware/account/InterchainAccount.ts b/typescript/sdk/src/middleware/account/InterchainAccount.ts index 273efb587..d705fedf3 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccount.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccount.ts @@ -120,6 +120,8 @@ export class InterchainAccount extends RouterApp { .getProvider(destinationChain) .getCode(destinationAccount)) === '0x' ) { + const txOverrides = + this.multiProvider.getTransactionOverrides(destinationChain); await this.multiProvider.handleTx( destinationChain, destinationRouter[ @@ -129,6 +131,7 @@ export class InterchainAccount extends RouterApp { config.owner, originRouterAddress, destinationIsmAddress, + txOverrides, ), ); this.logger.debug(`Interchain account deployed at ${destinationAccount}`); From 5300230c4496a704381f8066452626bc53d3732c Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Mon, 21 Oct 2024 14:19:40 +0100 Subject: [PATCH 159/224] refactor: Make Sealevel RPC client more functional (#4699) ### Description Make Sealevel RPC client more functional. Move some methods and error mapping into RPC client. ### Backward compatibility Yes ### Testing E2E Ethereum + Sealevel test --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../chains/hyperlane-sealevel/src/client.rs | 29 --- .../hyperlane-sealevel/src/interchain_gas.rs | 52 ++-- .../src/interchain_security_module.rs | 29 ++- .../main/chains/hyperlane-sealevel/src/lib.rs | 6 +- .../chains/hyperlane-sealevel/src/mailbox.rs | 118 +++------ .../src/merkle_tree_hook.rs | 10 +- .../hyperlane-sealevel/src/multisig_ism.rs | 32 +-- .../chains/hyperlane-sealevel/src/provider.rs | 27 +- .../main/chains/hyperlane-sealevel/src/rpc.rs | 3 + .../hyperlane-sealevel/src/rpc/client.rs | 242 ++++++++++++++++++ .../chains/hyperlane-sealevel/src/utils.rs | 93 ------- .../src/validator_announce.rs | 22 +- 12 files changed, 350 insertions(+), 313 deletions(-) delete mode 100644 rust/main/chains/hyperlane-sealevel/src/client.rs create mode 100644 rust/main/chains/hyperlane-sealevel/src/rpc.rs create mode 100644 rust/main/chains/hyperlane-sealevel/src/rpc/client.rs delete mode 100644 rust/main/chains/hyperlane-sealevel/src/utils.rs diff --git a/rust/main/chains/hyperlane-sealevel/src/client.rs b/rust/main/chains/hyperlane-sealevel/src/client.rs deleted file mode 100644 index cc41cd0b2..000000000 --- a/rust/main/chains/hyperlane-sealevel/src/client.rs +++ /dev/null @@ -1,29 +0,0 @@ -use solana_client::nonblocking::rpc_client::RpcClient; -use solana_sdk::commitment_config::CommitmentConfig; - -/// Kludge to implement Debug for RpcClient. -pub struct RpcClientWithDebug(RpcClient); - -impl RpcClientWithDebug { - pub fn new(rpc_endpoint: String) -> Self { - Self(RpcClient::new(rpc_endpoint)) - } - - pub fn new_with_commitment(rpc_endpoint: String, commitment: CommitmentConfig) -> Self { - Self(RpcClient::new_with_commitment(rpc_endpoint, commitment)) - } -} - -impl std::fmt::Debug for RpcClientWithDebug { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("RpcClient { ... }") - } -} - -impl std::ops::Deref for RpcClientWithDebug { - type Target = RpcClient; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} diff --git a/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs b/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs index 8c0972c9a..d2f78eb4b 100644 --- a/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs +++ b/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs @@ -16,9 +16,7 @@ use solana_client::{ use std::ops::RangeInclusive; use tracing::{info, instrument}; -use crate::{ - client::RpcClientWithDebug, utils::get_finalized_block_number, ConnectionConf, SealevelProvider, -}; +use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey}; use derive_new::new; @@ -60,20 +58,14 @@ impl SealevelInterchainGasPaymaster { } async fn determine_igp_program_id( - rpc_client: &RpcClientWithDebug, + rpc_client: &SealevelRpcClient, igp_account_pubkey: &H256, ) -> ChainResult { let account = rpc_client - .get_account_with_commitment( - &Pubkey::from(<[u8; 32]>::from(*igp_account_pubkey)), - CommitmentConfig::finalized(), - ) - .await - .map_err(ChainCommunicationError::from_other)? - .value - .ok_or_else(|| { - ChainCommunicationError::from_other_str("Could not find IGP account for pubkey") - })?; + .get_account_with_finalized_commitment(&Pubkey::from(<[u8; 32]>::from( + *igp_account_pubkey, + ))) + .await?; Ok(account.owner) } } @@ -99,7 +91,7 @@ impl InterchainGasPaymaster for SealevelInterchainGasPaymaster {} /// Struct that retrieves event data for a Sealevel IGP contract #[derive(Debug)] pub struct SealevelInterchainGasPaymasterIndexer { - rpc_client: RpcClientWithDebug, + rpc_client: SealevelRpcClient, igp: SealevelInterchainGasPaymaster, } @@ -118,10 +110,7 @@ impl SealevelInterchainGasPaymasterIndexer { igp_account_locator: ContractLocator<'_>, ) -> ChainResult { // Set the `processed` commitment at rpc level - let rpc_client = RpcClientWithDebug::new_with_commitment( - conf.url.to_string(), - CommitmentConfig::processed(), - ); + let rpc_client = SealevelRpcClient::new(conf.url.to_string()); let igp = SealevelInterchainGasPaymaster::new(conf, &igp_account_locator).await?; Ok(Self { rpc_client, igp }) @@ -169,8 +158,7 @@ impl SealevelInterchainGasPaymasterIndexer { let accounts = self .rpc_client .get_program_accounts_with_config(&self.igp.program_id, config) - .await - .map_err(ChainCommunicationError::from_other)?; + .await?; tracing::debug!(accounts=?accounts, "Fetched program accounts"); @@ -202,13 +190,8 @@ impl SealevelInterchainGasPaymasterIndexer { // Now that we have the valid gas payment PDA pubkey, we can get the full account data. let account = self .rpc_client - .get_account_with_commitment(&valid_payment_pda_pubkey, CommitmentConfig::finalized()) - .await - .map_err(ChainCommunicationError::from_other)? - .value - .ok_or_else(|| { - ChainCommunicationError::from_other_str("Could not find account data") - })?; + .get_account_with_finalized_commitment(&valid_payment_pda_pubkey) + .await?; let gas_payment_account = GasPaymentAccount::fetch(&mut account.data.as_ref()) .map_err(ChainCommunicationError::from_other)? .into_inner(); @@ -274,7 +257,7 @@ impl Indexer for SealevelInterchainGasPaymasterIndexer { #[instrument(level = "debug", err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { - get_finalized_block_number(&self.rpc_client).await + self.rpc_client.get_block_height().await } } @@ -285,13 +268,8 @@ impl SequenceAwareIndexer for SealevelInterchainGasPaymast async fn latest_sequence_count_and_tip(&self) -> ChainResult<(Option, u32)> { let program_data_account = self .rpc_client - .get_account_with_commitment(&self.igp.data_pda_pubkey, CommitmentConfig::finalized()) - .await - .map_err(ChainCommunicationError::from_other)? - .value - .ok_or_else(|| { - ChainCommunicationError::from_other_str("Could not find account data") - })?; + .get_account_with_finalized_commitment(&self.igp.data_pda_pubkey) + .await?; let program_data = ProgramDataAccount::fetch(&mut program_data_account.data.as_ref()) .map_err(ChainCommunicationError::from_other)? .into_inner(); @@ -299,7 +277,7 @@ impl SequenceAwareIndexer for SealevelInterchainGasPaymast .payment_count .try_into() .map_err(StrOrIntParseError::from)?; - let tip = get_finalized_block_number(&self.rpc_client).await?; + let tip = self.rpc_client.get_block_height().await?; Ok((Some(payment_count), tip)) } } diff --git a/rust/main/chains/hyperlane-sealevel/src/interchain_security_module.rs b/rust/main/chains/hyperlane-sealevel/src/interchain_security_module.rs index 0f92432eb..aaf2683fd 100644 --- a/rust/main/chains/hyperlane-sealevel/src/interchain_security_module.rs +++ b/rust/main/chains/hyperlane-sealevel/src/interchain_security_module.rs @@ -10,7 +10,7 @@ use hyperlane_core::{ use hyperlane_sealevel_interchain_security_module_interface::InterchainSecurityModuleInstruction; use serializable_account_meta::SimulationReturnData; -use crate::{utils::simulate_instruction, ConnectionConf, RpcClientWithDebug, SealevelProvider}; +use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; /// A reference to an InterchainSecurityModule contract on some Sealevel chain #[derive(Debug)] @@ -32,7 +32,7 @@ impl SealevelInterchainSecurityModule { } } - fn rpc(&self) -> &RpcClientWithDebug { + fn rpc(&self) -> &SealevelRpcClient { self.provider.rpc() } } @@ -64,18 +64,19 @@ impl InterchainSecurityModule for SealevelInterchainSecurityModule { vec![], ); - let module = simulate_instruction::>( - self.rpc(), - self.payer - .as_ref() - .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, - instruction, - ) - .await? - .ok_or_else(|| { - ChainCommunicationError::from_other_str("No return data was returned from the ISM") - })? - .return_data; + let module = self + .rpc() + .simulate_instruction::>( + self.payer + .as_ref() + .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, + instruction, + ) + .await? + .ok_or_else(|| { + ChainCommunicationError::from_other_str("No return data was returned from the ISM") + })? + .return_data; if let Some(module_type) = ModuleType::from_u32(module) { Ok(module_type) diff --git a/rust/main/chains/hyperlane-sealevel/src/lib.rs b/rust/main/chains/hyperlane-sealevel/src/lib.rs index 8cd8830f5..04e2218c6 100644 --- a/rust/main/chains/hyperlane-sealevel/src/lib.rs +++ b/rust/main/chains/hyperlane-sealevel/src/lib.rs @@ -5,12 +5,12 @@ #![deny(warnings)] pub use crate::multisig_ism::*; -pub(crate) use client::RpcClientWithDebug; pub use interchain_gas::*; pub use interchain_security_module::*; pub use mailbox::*; pub use merkle_tree_hook::*; pub use provider::*; +pub(crate) use rpc::SealevelRpcClient; pub use solana_sdk::signer::keypair::Keypair; pub use trait_builder::*; pub use validator_announce::*; @@ -22,8 +22,6 @@ mod mailbox; mod merkle_tree_hook; mod multisig_ism; mod provider; +mod rpc; mod trait_builder; -mod utils; - -mod client; mod validator_announce; diff --git a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs index f101435c2..952599c42 100644 --- a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs @@ -8,11 +8,12 @@ use jsonrpc_core::futures_util::TryFutureExt; use tracing::{debug, info, instrument, warn}; use hyperlane_core::{ - accumulator::incremental::IncrementalMerkle, BatchItem, ChainCommunicationError, ChainResult, - Checkpoint, ContractLocator, Decode as _, Encode as _, FixedPointNumber, HyperlaneAbi, - HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, - Indexed, Indexer, KnownHyperlaneDomain, LogMeta, Mailbox, MerkleTreeHook, SequenceAwareIndexer, - TxCostEstimate, TxOutcome, H256, H512, U256, + accumulator::incremental::IncrementalMerkle, BatchItem, ChainCommunicationError, + ChainCommunicationError::ContractError, ChainResult, Checkpoint, ContractLocator, Decode as _, + Encode as _, FixedPointNumber, HyperlaneAbi, HyperlaneChain, HyperlaneContract, + HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Indexed, Indexer, KnownHyperlaneDomain, + LogMeta, Mailbox, MerkleTreeHook, SequenceAwareIndexer, TxCostEstimate, TxOutcome, H256, H512, + U256, }; use hyperlane_sealevel_interchain_security_module_interface::{ InterchainSecurityModuleInstruction, VerifyInstruction, @@ -54,11 +55,7 @@ use solana_transaction_status::{ UiTransaction, UiTransactionReturnData, UiTransactionStatusMeta, }; -use crate::RpcClientWithDebug; -use crate::{ - utils::{get_account_metas, get_finalized_block_number, simulate_instruction}, - ConnectionConf, SealevelProvider, -}; +use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; const SYSTEM_PROGRAM: &str = "11111111111111111111111111111111"; const SPL_NOOP: &str = "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV"; @@ -128,7 +125,7 @@ impl SealevelMailbox { self.outbox } - pub fn rpc(&self) -> &RpcClientWithDebug { + pub fn rpc(&self) -> &SealevelRpcClient { self.provider.rpc() } @@ -140,14 +137,14 @@ impl SealevelMailbox { &self, instruction: Instruction, ) -> ChainResult> { - simulate_instruction( - &self.rpc(), - self.payer - .as_ref() - .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, - instruction, - ) - .await + self.rpc() + .simulate_instruction( + self.payer + .as_ref() + .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, + instruction, + ) + .await } /// Simulates an Instruction that will return a list of AccountMetas. @@ -155,14 +152,14 @@ impl SealevelMailbox { &self, instruction: Instruction, ) -> ChainResult> { - get_account_metas( - &self.rpc(), - self.payer - .as_ref() - .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, - instruction, - ) - .await + self.rpc() + .get_account_metas( + self.payer + .as_ref() + .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, + instruction, + ) + .await } /// Gets the recipient ISM given a recipient program id and the ISM getter account metas. @@ -293,7 +290,6 @@ impl SealevelMailbox { .rpc() .send_and_confirm_transaction(transaction) .await - .map_err(ChainCommunicationError::from_other) } } @@ -343,13 +339,10 @@ impl SealevelMailbox { ); let recent_blockhash = if transaction.uses_durable_nonce() { - let (recent_blockhash, ..) = self - .provider + self.provider .rpc() .get_latest_blockhash_with_commitment(CommitmentConfig::processed()) - .await - .map_err(ChainCommunicationError::from_other)?; - recent_blockhash + .await? } else { *transaction.get_recent_blockhash() }; @@ -359,8 +352,7 @@ impl SealevelMailbox { .provider .rpc() .get_signature_statuses(&[*signature]) - .await - .map_err(ChainCommunicationError::from_other)?; + .await?; let signature_status = signature_statuses.value.first().cloned().flatten(); match signature_status { Some(_) => return Ok(*signature), @@ -368,9 +360,8 @@ impl SealevelMailbox { if !self .provider .rpc() - .is_blockhash_valid(&recent_blockhash, CommitmentConfig::processed()) - .await - .map_err(ChainCommunicationError::from_other)? + .is_blockhash_valid(&recent_blockhash) + .await? { // Block hash is not found by some reason break 'sending; @@ -439,23 +430,15 @@ impl Mailbox for SealevelMailbox { let account = self .rpc() - .get_account_with_commitment( - &processed_message_account_key, - CommitmentConfig::finalized(), - ) - .await - .map_err(ChainCommunicationError::from_other)?; + .get_possible_account_with_finalized_commitment(&processed_message_account_key) + .await?; - Ok(account.value.is_some()) + Ok(account.is_some()) } #[instrument(err, ret, skip(self))] async fn default_ism(&self) -> ChainResult { - let inbox_account = self - .rpc() - .get_account(&self.inbox.0) - .await - .map_err(ChainCommunicationError::from_other)?; + let inbox_account = self.rpc().get_account(&self.inbox.0).await?; let inbox = InboxAccount::fetch(&mut inbox_account.data.as_ref()) .map_err(ChainCommunicationError::from_other)? .into_inner(); @@ -591,11 +574,10 @@ impl Mailbox for SealevelMailbox { accounts, }; instructions.push(inbox_instruction); - let (recent_blockhash, _) = self + let recent_blockhash = self .rpc() .get_latest_blockhash_with_commitment(commitment) - .await - .map_err(ChainCommunicationError::from_other)?; + .await?; let txn = Transaction::new_signed_with_payer( &instructions, @@ -615,7 +597,6 @@ impl Mailbox for SealevelMailbox { .confirm_transaction_with_commitment(&signature, commitment) .await .map_err(|err| warn!("Failed to confirm inbox process transaction: {}", err)) - .map(|ctx| ctx.value) .unwrap_or(false); let txid = signature.into(); @@ -664,20 +645,12 @@ impl SealevelMailboxIndexer { }) } - fn rpc(&self) -> &RpcClientWithDebug { + fn rpc(&self) -> &SealevelRpcClient { &self.mailbox.rpc() } async fn get_finalized_block_number(&self) -> ChainResult { - let height = self - .rpc() - .get_block_height() - .await - .map_err(ChainCommunicationError::from_other)? - .try_into() - // FIXME solana block height is u64... - .expect("sealevel block height exceeds u32::MAX"); - Ok(height) + self.rpc().get_block_height().await } async fn get_message_with_nonce( @@ -718,8 +691,7 @@ impl SealevelMailboxIndexer { let accounts = self .rpc() .get_program_accounts_with_config(&self.mailbox.program_id, config) - .await - .map_err(ChainCommunicationError::from_other)?; + .await?; // Now loop through matching accounts and find the one with a valid account pubkey // that proves it's an actual message storage PDA. @@ -752,16 +724,8 @@ impl SealevelMailboxIndexer { // Now that we have the valid message storage PDA pubkey, we can get the full account data. let account = self .rpc() - .get_account_with_commitment( - &valid_message_storage_pda_pubkey, - CommitmentConfig::finalized(), - ) - .await - .map_err(ChainCommunicationError::from_other)? - .value - .ok_or_else(|| { - ChainCommunicationError::from_other_str("Could not find account data") - })?; + .get_account_with_finalized_commitment(&valid_message_storage_pda_pubkey) + .await?; let dispatched_message_account = DispatchedMessageAccount::fetch(&mut account.data.as_ref()) .map_err(ChainCommunicationError::from_other)? @@ -816,7 +780,7 @@ impl Indexer for SealevelMailboxIndexer { } async fn get_finalized_block_number(&self) -> ChainResult { - get_finalized_block_number(&self.rpc()).await + self.get_finalized_block_number().await } } diff --git a/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs b/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs index 3778627b2..947f7e70a 100644 --- a/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs @@ -8,7 +8,6 @@ use hyperlane_core::{ MerkleTreeInsertion, SequenceAwareIndexer, }; use hyperlane_sealevel_mailbox::accounts::OutboxAccount; -use solana_sdk::commitment_config::CommitmentConfig; use tracing::instrument; use crate::{SealevelMailbox, SealevelMailboxIndexer}; @@ -25,13 +24,8 @@ impl MerkleTreeHook for SealevelMailbox { let outbox_account = self .rpc() - .get_account_with_commitment(&self.outbox.0, CommitmentConfig::finalized()) - .await - .map_err(ChainCommunicationError::from_other)? - .value - .ok_or_else(|| { - ChainCommunicationError::from_other_str("Could not find account data") - })?; + .get_account_with_finalized_commitment(&self.outbox.0) + .await?; let outbox = OutboxAccount::fetch(&mut outbox_account.data.as_ref()) .map_err(ChainCommunicationError::from_other)? .into_inner(); diff --git a/rust/main/chains/hyperlane-sealevel/src/multisig_ism.rs b/rust/main/chains/hyperlane-sealevel/src/multisig_ism.rs index 794e19c14..a3cdb1273 100644 --- a/rust/main/chains/hyperlane-sealevel/src/multisig_ism.rs +++ b/rust/main/chains/hyperlane-sealevel/src/multisig_ism.rs @@ -1,9 +1,9 @@ use async_trait::async_trait; - use hyperlane_core::{ ChainCommunicationError, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, MultisigIsm, RawHyperlaneMessage, H256, }; +use hyperlane_sealevel_multisig_ism_message_id::instruction::ValidatorsAndThreshold; use serializable_account_meta::SimulationReturnData; use solana_sdk::{ instruction::{AccountMeta, Instruction}, @@ -11,12 +11,8 @@ use solana_sdk::{ signature::Keypair, }; -use crate::{ - utils::{get_account_metas, simulate_instruction}, - ConnectionConf, RpcClientWithDebug, SealevelProvider, -}; +use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; -use hyperlane_sealevel_multisig_ism_message_id::instruction::ValidatorsAndThreshold; use multisig_ism::interface::{ MultisigIsmInstruction, VALIDATORS_AND_THRESHOLD_ACCOUNT_METAS_PDA_SEEDS, }; @@ -44,7 +40,7 @@ impl SealevelMultisigIsm { } } - fn rpc(&self) -> &RpcClientWithDebug { + fn rpc(&self) -> &SealevelRpcClient { self.provider.rpc() } } @@ -86,9 +82,9 @@ impl MultisigIsm for SealevelMultisigIsm { account_metas, ); - let validators_and_threshold = - simulate_instruction::>( - self.rpc(), + let validators_and_threshold = self + .rpc() + .simulate_instruction::>( self.payer .as_ref() .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, @@ -135,13 +131,13 @@ impl SealevelMultisigIsm { vec![AccountMeta::new_readonly(account_metas_pda_key, false)], ); - get_account_metas( - self.rpc(), - self.payer - .as_ref() - .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, - instruction, - ) - .await + self.rpc() + .get_account_metas( + self.payer + .as_ref() + .ok_or_else(|| ChainCommunicationError::SignerUnavailable)?, + instruction, + ) + .await } } diff --git a/rust/main/chains/hyperlane-sealevel/src/provider.rs b/rust/main/chains/hyperlane-sealevel/src/provider.rs index 42b266550..b292d9594 100644 --- a/rust/main/chains/hyperlane-sealevel/src/provider.rs +++ b/rust/main/chains/hyperlane-sealevel/src/provider.rs @@ -6,44 +6,30 @@ use hyperlane_core::{ BlockInfo, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, TxnInfo, H256, U256, }; -use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey}; +use solana_sdk::pubkey::Pubkey; -use crate::{client::RpcClientWithDebug, error::HyperlaneSealevelError, ConnectionConf}; +use crate::{error::HyperlaneSealevelError, ConnectionConf, SealevelRpcClient}; /// A wrapper around a Sealevel provider to get generic blockchain information. #[derive(Debug)] pub struct SealevelProvider { domain: HyperlaneDomain, - rpc_client: Arc, + rpc_client: Arc, } impl SealevelProvider { /// Create a new Sealevel provider. pub fn new(domain: HyperlaneDomain, conf: &ConnectionConf) -> Self { // Set the `processed` commitment at rpc level - let rpc_client = Arc::new(RpcClientWithDebug::new_with_commitment( - conf.url.to_string(), - CommitmentConfig::processed(), - )); + let rpc_client = Arc::new(SealevelRpcClient::new(conf.url.to_string())); SealevelProvider { domain, rpc_client } } /// Get an rpc client - pub fn rpc(&self) -> &RpcClientWithDebug { + pub fn rpc(&self) -> &SealevelRpcClient { &self.rpc_client } - - /// Get the balance of an address - pub async fn get_balance(&self, address: String) -> ChainResult { - let pubkey = Pubkey::from_str(&address).map_err(Into::::into)?; - let balance = self - .rpc_client - .get_balance(&pubkey) - .await - .map_err(Into::::into)?; - Ok(balance.into()) - } } impl HyperlaneChain for SealevelProvider { @@ -75,7 +61,8 @@ impl HyperlaneProvider for SealevelProvider { } async fn get_balance(&self, address: String) -> ChainResult { - self.get_balance(address).await + let pubkey = Pubkey::from_str(&address).map_err(Into::::into)?; + self.rpc_client.get_balance(&pubkey).await } async fn get_chain_metrics(&self) -> ChainResult> { diff --git a/rust/main/chains/hyperlane-sealevel/src/rpc.rs b/rust/main/chains/hyperlane-sealevel/src/rpc.rs new file mode 100644 index 000000000..1c82b77c0 --- /dev/null +++ b/rust/main/chains/hyperlane-sealevel/src/rpc.rs @@ -0,0 +1,3 @@ +pub use client::SealevelRpcClient; + +mod client; diff --git a/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs b/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs new file mode 100644 index 000000000..77f21ee1f --- /dev/null +++ b/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs @@ -0,0 +1,242 @@ +use base64::Engine; +use borsh::{BorshDeserialize, BorshSerialize}; +use hyperlane_core::{ChainCommunicationError, ChainResult, U256}; +use serializable_account_meta::{SerializableAccountMeta, SimulationReturnData}; +use solana_client::{ + nonblocking::rpc_client::RpcClient, rpc_config::RpcProgramAccountsConfig, + rpc_response::Response, +}; +use solana_sdk::{ + account::Account, + commitment_config::CommitmentConfig, + hash::Hash, + instruction::{AccountMeta, Instruction}, + message::Message, + pubkey::Pubkey, + signature::{Keypair, Signature, Signer}, + transaction::Transaction, +}; +use solana_transaction_status::{TransactionStatus, UiReturnDataEncoding, UiTransactionReturnData}; + +use crate::error::HyperlaneSealevelError; + +pub struct SealevelRpcClient(RpcClient); + +impl SealevelRpcClient { + pub fn new(rpc_endpoint: String) -> Self { + Self(RpcClient::new_with_commitment( + rpc_endpoint, + CommitmentConfig::processed(), + )) + } + + pub async fn confirm_transaction_with_commitment( + &self, + signature: &Signature, + commitment: CommitmentConfig, + ) -> ChainResult { + self.0 + .confirm_transaction_with_commitment(signature, commitment) + .await + .map(|ctx| ctx.value) + .map_err(HyperlaneSealevelError::ClientError) + .map_err(Into::into) + } + + pub async fn get_account(&self, pubkey: &Pubkey) -> ChainResult { + self.0 + .get_account(pubkey) + .await + .map_err(ChainCommunicationError::from_other) + } + + /// Simulates an Instruction that will return a list of AccountMetas. + pub async fn get_account_metas( + &self, + payer: &Keypair, + instruction: Instruction, + ) -> ChainResult> { + // If there's no data at all, default to an empty vec. + let account_metas = self + .simulate_instruction::>>( + payer, + instruction, + ) + .await? + .map(|serializable_account_metas| { + serializable_account_metas + .return_data + .into_iter() + .map(|serializable_account_meta| serializable_account_meta.into()) + .collect() + }) + .unwrap_or_else(Vec::new); + + Ok(account_metas) + } + + pub async fn get_account_with_finalized_commitment( + &self, + pubkey: &Pubkey, + ) -> ChainResult { + self.get_possible_account_with_finalized_commitment(pubkey) + .await? + .ok_or_else(|| ChainCommunicationError::from_other_str("Could not find account data")) + } + + pub async fn get_possible_account_with_finalized_commitment( + &self, + pubkey: &Pubkey, + ) -> ChainResult> { + let account = self + .0 + .get_account_with_commitment(pubkey, CommitmentConfig::finalized()) + .await + .map_err(ChainCommunicationError::from_other)? + .value; + Ok(account) + } + + pub async fn get_block_height(&self) -> ChainResult { + let height = self + .0 + .get_block_height_with_commitment(CommitmentConfig::finalized()) + .await + .map_err(ChainCommunicationError::from_other)? + .try_into() + // FIXME solana block height is u64... + .expect("sealevel block height exceeds u32::MAX"); + Ok(height) + } + + pub async fn get_multiple_accounts_with_finalized_commitment( + &self, + pubkeys: &[Pubkey], + ) -> ChainResult>> { + let accounts = self + .0 + .get_multiple_accounts_with_commitment(pubkeys, CommitmentConfig::finalized()) + .await + .map_err(ChainCommunicationError::from_other)? + .value; + + Ok(accounts) + } + + pub async fn get_latest_blockhash_with_commitment( + &self, + commitment: CommitmentConfig, + ) -> ChainResult { + self.0 + .get_latest_blockhash_with_commitment(commitment) + .await + .map_err(ChainCommunicationError::from_other) + .map(|(blockhash, _)| blockhash) + } + + pub async fn get_program_accounts_with_config( + &self, + pubkey: &Pubkey, + config: RpcProgramAccountsConfig, + ) -> ChainResult> { + self.0 + .get_program_accounts_with_config(pubkey, config) + .await + .map_err(ChainCommunicationError::from_other) + } + + pub async fn get_signature_statuses( + &self, + signatures: &[Signature], + ) -> ChainResult>>> { + self.0 + .get_signature_statuses(signatures) + .await + .map_err(ChainCommunicationError::from_other) + } + + pub async fn get_balance(&self, pubkey: &Pubkey) -> ChainResult { + let balance = self + .0 + .get_balance(pubkey) + .await + .map_err(Into::::into) + .map_err(ChainCommunicationError::from)?; + + Ok(balance.into()) + } + + pub async fn is_blockhash_valid(&self, hash: &Hash) -> ChainResult { + self.0 + .is_blockhash_valid(hash, CommitmentConfig::processed()) + .await + .map_err(ChainCommunicationError::from_other) + } + + pub async fn send_and_confirm_transaction( + &self, + transaction: &Transaction, + ) -> ChainResult { + self.0 + .send_and_confirm_transaction(transaction) + .await + .map_err(ChainCommunicationError::from_other) + } + + /// Simulates an instruction, and attempts to deserialize it into a T. + /// If no return data at all was returned, returns Ok(None). + /// If some return data was returned but deserialization was unsuccessful, + /// an Err is returned. + pub async fn simulate_instruction( + &self, + payer: &Keypair, + instruction: Instruction, + ) -> ChainResult> { + let commitment = CommitmentConfig::finalized(); + let recent_blockhash = self + .get_latest_blockhash_with_commitment(commitment) + .await?; + let transaction = Transaction::new_unsigned(Message::new_with_blockhash( + &[instruction], + Some(&payer.pubkey()), + &recent_blockhash, + )); + let return_data = self.simulate_transaction(&transaction).await?; + + if let Some(return_data) = return_data { + let bytes = match return_data.data.1 { + UiReturnDataEncoding::Base64 => base64::engine::general_purpose::STANDARD + .decode(return_data.data.0) + .map_err(ChainCommunicationError::from_other)?, + }; + + let decoded_data = + T::try_from_slice(bytes.as_slice()).map_err(ChainCommunicationError::from_other)?; + + return Ok(Some(decoded_data)); + } + + Ok(None) + } + + async fn simulate_transaction( + &self, + transaction: &Transaction, + ) -> ChainResult> { + let return_data = self + .0 + .simulate_transaction(transaction) + .await + .map_err(ChainCommunicationError::from_other)? + .value + .return_data; + + Ok(return_data) + } +} + +impl std::fmt::Debug for SealevelRpcClient { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("RpcClient { ... }") + } +} diff --git a/rust/main/chains/hyperlane-sealevel/src/utils.rs b/rust/main/chains/hyperlane-sealevel/src/utils.rs deleted file mode 100644 index 56bec9e51..000000000 --- a/rust/main/chains/hyperlane-sealevel/src/utils.rs +++ /dev/null @@ -1,93 +0,0 @@ -use base64::Engine; -use borsh::{BorshDeserialize, BorshSerialize}; -use hyperlane_core::{ChainCommunicationError, ChainResult}; - -use serializable_account_meta::{SerializableAccountMeta, SimulationReturnData}; -use solana_client::nonblocking::rpc_client::RpcClient; -use solana_sdk::{ - commitment_config::CommitmentConfig, - instruction::{AccountMeta, Instruction}, - message::Message, - signature::{Keypair, Signer}, - transaction::Transaction, -}; -use solana_transaction_status::UiReturnDataEncoding; - -use crate::client::RpcClientWithDebug; - -/// Simulates an instruction, and attempts to deserialize it into a T. -/// If no return data at all was returned, returns Ok(None). -/// If some return data was returned but deserialization was unsuccessful, -/// an Err is returned. -pub async fn simulate_instruction( - rpc_client: &RpcClient, - payer: &Keypair, - instruction: Instruction, -) -> ChainResult> { - let commitment = CommitmentConfig::finalized(); - let (recent_blockhash, _) = rpc_client - .get_latest_blockhash_with_commitment(commitment) - .await - .map_err(ChainCommunicationError::from_other)?; - let return_data = rpc_client - .simulate_transaction(&Transaction::new_unsigned(Message::new_with_blockhash( - &[instruction], - Some(&payer.pubkey()), - &recent_blockhash, - ))) - .await - .map_err(ChainCommunicationError::from_other)? - .value - .return_data; - - if let Some(return_data) = return_data { - let bytes = match return_data.data.1 { - UiReturnDataEncoding::Base64 => base64::engine::general_purpose::STANDARD - .decode(return_data.data.0) - .map_err(ChainCommunicationError::from_other)?, - }; - - let decoded_data = - T::try_from_slice(bytes.as_slice()).map_err(ChainCommunicationError::from_other)?; - - return Ok(Some(decoded_data)); - } - - Ok(None) -} - -/// Simulates an Instruction that will return a list of AccountMetas. -pub async fn get_account_metas( - rpc_client: &RpcClient, - payer: &Keypair, - instruction: Instruction, -) -> ChainResult> { - // If there's no data at all, default to an empty vec. - let account_metas = simulate_instruction::>>( - rpc_client, - payer, - instruction, - ) - .await? - .map(|serializable_account_metas| { - serializable_account_metas - .return_data - .into_iter() - .map(|serializable_account_meta| serializable_account_meta.into()) - .collect() - }) - .unwrap_or_else(Vec::new); - - Ok(account_metas) -} - -pub async fn get_finalized_block_number(rpc_client: &RpcClientWithDebug) -> ChainResult { - let height = rpc_client - .get_block_height() - .await - .map_err(ChainCommunicationError::from_other)? - .try_into() - // FIXME solana block height is u64... - .expect("sealevel block height exceeds u32::MAX"); - Ok(height) -} diff --git a/rust/main/chains/hyperlane-sealevel/src/validator_announce.rs b/rust/main/chains/hyperlane-sealevel/src/validator_announce.rs index 52b19495a..3edfa0d06 100644 --- a/rust/main/chains/hyperlane-sealevel/src/validator_announce.rs +++ b/rust/main/chains/hyperlane-sealevel/src/validator_announce.rs @@ -1,17 +1,15 @@ use async_trait::async_trait; -use tracing::{info, instrument, warn}; - use hyperlane_core::{ - Announcement, ChainCommunicationError, ChainResult, ContractLocator, HyperlaneChain, - HyperlaneContract, HyperlaneDomain, SignedType, TxOutcome, ValidatorAnnounce, H160, H256, H512, - U256, + Announcement, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, + SignedType, TxOutcome, ValidatorAnnounce, H160, H256, H512, U256, }; -use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey}; - -use crate::{ConnectionConf, RpcClientWithDebug, SealevelProvider}; use hyperlane_sealevel_validator_announce::{ accounts::ValidatorStorageLocationsAccount, validator_storage_locations_pda_seeds, }; +use solana_sdk::pubkey::Pubkey; +use tracing::{info, instrument, warn}; + +use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; /// A reference to a ValidatorAnnounce contract on some Sealevel chain #[derive(Debug)] @@ -33,7 +31,7 @@ impl SealevelValidatorAnnounce { } } - fn rpc(&self) -> &RpcClientWithDebug { + fn rpc(&self) -> &SealevelRpcClient { self.provider.rpc() } } @@ -79,10 +77,8 @@ impl ValidatorAnnounce for SealevelValidatorAnnounce { // If an account doesn't exist, it will be returned as None. let accounts = self .rpc() - .get_multiple_accounts_with_commitment(&account_pubkeys, CommitmentConfig::finalized()) - .await - .map_err(ChainCommunicationError::from_other)? - .value; + .get_multiple_accounts_with_finalized_commitment(&account_pubkeys) + .await?; // Parse the storage locations from each account. // If a validator's account doesn't exist, its storage locations will From 7bfc7ec81c21ba64c3462445113fa58946bd28e2 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:40:06 -0400 Subject: [PATCH 160/224] chore: remove old e2e cli tests (#4711) ### Description Removes the tests from workflow. We now use ts e2e tests ### Related issues - Fixes #4417 --- .github/workflows/test.yml | 34 ---- typescript/cli/ci-advanced-test.sh | 270 ----------------------------- 2 files changed, 304 deletions(-) delete mode 100755 typescript/cli/ci-advanced-test.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e1b7d7694..b37075002 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -234,40 +234,6 @@ jobs: RUST_BACKTRACE: 'full' SEALEVEL_ENABLED: ${{ steps.check-rust-changes.outputs.rust_changes }} - cli-advanced-e2e: - runs-on: ubuntu-latest - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.base_ref == 'main' || github.base_ref == 'cli-2.0') || github.event_name == 'merge_group' - needs: [yarn-install] - strategy: - matrix: - include: - - test-type: preset_hook_enabled - - test-type: configure_hook_enabled - - test-type: pi_with_core_chain - steps: - - uses: actions/setup-node@v4 - with: - node-version: 18 - - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - submodules: recursive - - - name: foundry-install - uses: foundry-rs/foundry-toolchain@v1 - - - name: yarn-build - uses: ./.github/actions/yarn-build-with-cache - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - - - name: Checkout registry - uses: ./.github/actions/checkout-registry - - - name: cli e2e tests - run: ./typescript/cli/ci-advanced-test.sh ${{ matrix.test-type }} - env-test: runs-on: ubuntu-latest env: diff --git a/typescript/cli/ci-advanced-test.sh b/typescript/cli/ci-advanced-test.sh deleted file mode 100755 index 5fd16676f..000000000 --- a/typescript/cli/ci-advanced-test.sh +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env bash - -_main() { - export LOG_LEVEL=DEBUG - - # set script location as repo root - cd "$(dirname "$0")/../.." - - TEST_TYPE_PRESET_HOOK="preset_hook_enabled" - TEST_TYPE_CONFIGURED_HOOK="configure_hook_enabled" - TEST_TYPE_PI_CORE="pi_with_core_chain" - - # set the first arg to 'configured_hook' to set the hook config as part of core deployment - # motivation is to test both the bare bone deployment (included in the docs) and the deployment - # with the routing over igp hook (which is closer to production deployment) - TEST_TYPE=$1 - if [ -z "$TEST_TYPE" ]; then - echo "Usage: ci-advanced-test.sh <$TEST_TYPE_PRESET_HOOK | $TEST_TYPE_CONFIGURED_HOOK | $TEST_TYPE_PI_CORE>" - exit 1 - fi - - prepare_environment_vars; - - prepare_anvil; - - DEPLOYER=$(cast rpc eth_accounts | jq -r '.[0]'); - - # TODO: fix `resetFork` after a dry-run. Related: https://github.com/foundry-rs/foundry/pull/8768 - # run_hyperlane_deploy_core_dry_run; - # run_hyperlane_deploy_warp_dry_run; - # reset_anvil; - - run_hyperlane_deploy_core; - run_hyperlane_deploy_warp; - run_hyperlane_send_message; - - kill_anvil; - - echo "Done"; -} - -prepare_environment_vars() { - ANVIL_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 - CHAIN1=anvil1 - CHAIN2=anvil2 - EXAMPLES_PATH=./examples - TEST_CONFIGS_PATH=./test-configs - CLI_PATH=./typescript/cli - REGISTRY_PATH="$TEST_CONFIGS_PATH/anvil" - CORE_ISM_PATH="$EXAMPLES_PATH/ism.yaml" - WARP_DEPLOY_CONFIG_PATH="$EXAMPLES_PATH/warp-route-deployment.yaml" - DEPLOY_ERC20_PATH=./src/tests/deployTestErc20.ts - - # use different chain names and config for pi<>core test - if [ "$TEST_TYPE" == $TEST_TYPE_PI_CORE ]; then - CHAIN2=ethereum - REGISTRY_PATH="$TEST_CONFIGS_PATH/fork" - CORE_ISM_PATH="$REGISTRY_PATH/ism.yaml" - WARP_DEPLOY_CONFIG_PATH="$REGISTRY_PATH/warp-route-deployment.yaml" - fi - - CHAIN1_CAPS=$(echo "${CHAIN1}" | tr '[:lower:]' '[:upper:]') - CHAIN2_CAPS=$(echo "${CHAIN2}" | tr '[:lower:]' '[:upper:]') - - HOOK_FLAG=false - if [ "$TEST_TYPE" == $TEST_TYPE_CONFIGURED_HOOK ]; then - HOOK_FLAG=true - fi -} - -prepare_anvil() { - - CHAIN1_PORT=8545 - CHAIN2_PORT=8555 - - # Optional cleanup for previous runs, useful when running locally - pkill -f anvil - rm -rf /tmp/${CHAIN1}* - rm -rf /tmp/${CHAIN2}* - rm -rf /tmp/relayer - rm -f $CLI_PATH/$TEST_CONFIGS_PATH/*/chains/*/addresses.yaml - rm -rf $CLI_PATH/$TEST_CONFIGS_PATH/*/deployments - - if [[ $OSTYPE == 'darwin'* ]]; then - # kill child processes on exit, but only locally because - # otherwise it causes the script exit code to be non-zero - trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT - fi - - # Setup directories for anvil chains - for CHAIN in ${CHAIN1} ${CHAIN2} - do - mkdir -p /tmp/$CHAIN /tmp/$CHAIN/state /tmp/$CHAIN/validator /tmp/relayer - chmod -R 777 /tmp/relayer /tmp/$CHAIN - done - - # run the PI chain - anvil --chain-id 31337 -p ${CHAIN1_PORT} --state /tmp/${CHAIN1}/state --gas-price 1 > /dev/null & - sleep 1 - - # use different chain names for pi<>core test - if [ "$TEST_TYPE" == $TEST_TYPE_PI_CORE ]; then - # Fetch the RPC of chain to fork - cd typescript/infra - RPC_URL=$(LOG_LEVEL=error yarn tsx scripts/print-chain-metadatas.ts -e mainnet3 | jq -r ".${CHAIN2}.rpcUrls[0].http") - cd ../../ - - # run the fork chain - anvil -p ${CHAIN2_PORT} --state /tmp/${CHAIN2}/state --gas-price 1 --fork-url $RPC_URL --fork-retry-backoff 3 --compute-units-per-second 200 > /dev/null & - - # wait for fork to be ready - while ! cast bn --rpc-url http://127.0.0.1:${CHAIN2_PORT} &> /dev/null; do - sleep 1 - done - else - # run a second PI chain - anvil --chain-id 31338 -p ${CHAIN2_PORT} --state /tmp/${CHAIN2}/state --gas-price 1 > /dev/null & - sleep 1 - fi - - set -e -} - -reset_anvil() { - prepare_anvil -} - -kill_anvil() { - pkill -f anvil -} - -run_hyperlane_deploy_core_dry_run() { - if [ "$TEST_TYPE" == $TEST_TYPE_PI_CORE ]; then - return; - fi - - update_deployer_balance; - - echo -e "\nDry-running contract deployments to Alfajores" - yarn workspace @hyperlane-xyz/cli run hyperlane core deploy \ - --dry-run alfajores \ - --registry ${TEST_CONFIGS_PATH}/dry-run \ - --overrides " " \ - --config ${EXAMPLES_PATH}/core-config.yaml \ - --from-address 0xfaD1C94469700833717Fa8a3017278BC1cA8031C \ - --yes - - check_deployer_balance; -} - -run_hyperlane_deploy_warp_dry_run() { - if [ "$TEST_TYPE" == $TEST_TYPE_PI_CORE ]; then - return; - fi - - update_deployer_balance; - - echo -e "\nDry-running warp route deployments to Alfajores" - yarn workspace @hyperlane-xyz/cli run hyperlane warp deploy \ - --dry-run alfajores \ - --overrides ${TEST_CONFIGS_PATH}/dry-run \ - --config ${TEST_CONFIGS_PATH}/dry-run/warp-route-deployment.yaml \ - --from-address 0xfaD1C94469700833717Fa8a3017278BC1cA8031C \ - --yes - - check_deployer_balance; -} - -run_hyperlane_deploy_core() { - update_deployer_balance; - - echo -e "\nDeploying contracts to ${CHAIN1}" - yarn workspace @hyperlane-xyz/cli run hyperlane core deploy \ - --registry $REGISTRY_PATH \ - --overrides " " \ - --config ${EXAMPLES_PATH}/core-config.yaml \ - --chain $CHAIN1 \ - --key $ANVIL_KEY \ - --yes - - echo -e "\nDeploying contracts to ${CHAIN2}" - yarn workspace @hyperlane-xyz/cli run hyperlane core deploy \ - --registry $REGISTRY_PATH \ - --overrides " " \ - --config ${EXAMPLES_PATH}/core-config.yaml \ - --chain $CHAIN2 \ - --key $ANVIL_KEY \ - --yes - - check_deployer_balance; -} - -run_hyperlane_deploy_warp() { - update_deployer_balance; - - echo -e "\nDeploying hypNative warp route" - yarn workspace @hyperlane-xyz/cli run hyperlane warp deploy \ - --registry $REGISTRY_PATH \ - --overrides " " \ - --config $WARP_DEPLOY_CONFIG_PATH \ - --key $ANVIL_KEY \ - --yes - - yarn workspace @hyperlane-xyz/cli run tsx $DEPLOY_ERC20_PATH \ - http://127.0.0.1:$CHAIN1_PORT \ - $CHAIN1 $CHAIN2 $ANVIL_KEY \ - /tmp/warp-collateral-deployment.json \ - - echo "Deploying hypCollateral warp route" - yarn workspace @hyperlane-xyz/cli run hyperlane warp deploy \ - --registry $REGISTRY_PATH \ - --overrides " " \ - --config /tmp/warp-collateral-deployment.json \ - --key $ANVIL_KEY \ - --yes - - check_deployer_balance; -} - -run_hyperlane_send_message() { - update_deployer_balance; - - echo -e "\nSending test message" - yarn workspace @hyperlane-xyz/cli run hyperlane send message \ - --registry $REGISTRY_PATH \ - --overrides " " \ - --origin ${CHAIN1} \ - --destination ${CHAIN2} \ - --body "Howdy!" \ - --quick \ - --key $ANVIL_KEY \ - | tee /tmp/message1 - - check_deployer_balance; - - MESSAGE1_ID=`cat /tmp/message1 | grep "Message ID" | grep -E -o '0x[0-9a-f]+'` - echo "Message 1 ID: $MESSAGE1_ID" - - WARP_CONFIG_FILE="$REGISTRY_PATH/deployments/warp_routes/FAKE/${CHAIN1}-${CHAIN2}-config.yaml" - - echo -e "\nSending test warp transfer" - yarn workspace @hyperlane-xyz/cli run hyperlane warp send \ - --registry $REGISTRY_PATH \ - --overrides " " \ - --origin ${CHAIN1} \ - --destination ${CHAIN2} \ - --warp ${WARP_CONFIG_FILE} \ - --quick \ - --relay \ - --key $ANVIL_KEY \ - | tee /tmp/message2 - - MESSAGE2_ID=`cat /tmp/message2 | grep "Message ID" | grep -E -o '0x[0-9a-f]+'` - echo "Message 2 ID: $MESSAGE2_ID" -} - -update_deployer_balance() { - OLD_BALANCE=$(cast balance $DEPLOYER --rpc-url http://127.0.0.1:${CHAIN1_PORT}); -} - -check_deployer_balance() { - NEW_BALANCE=$(cast balance $DEPLOYER --rpc-url http://127.0.0.1:${CHAIN1_PORT}) - GAS_PRICE=$(cast gas-price --rpc-url http://127.0.0.1:${CHAIN1_PORT}) - GAS_USED=$(bc <<< "($OLD_BALANCE - $NEW_BALANCE) / $GAS_PRICE") - echo "Gas used: $GAS_USED" -} - -_main "$@"; - -exit; From 32d0a67c2130f5f893bd824ccfb05007418cf191 Mon Sep 17 00:00:00 2001 From: xeno097 Date: Mon, 21 Oct 2024 18:37:00 -0400 Subject: [PATCH 161/224] feat: cli warp route checker (#4667) ### Description This PR implements the `warp check` command to compare on-chain warp deployments with provided configuration files ### Drive-by changes - updated the `inputFileCommandOption` to be a function for defining cli input file args - defined the `DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH` to avoid hardcoding the `./configs/warp-route-deployment.yaml` file path - implemented the `logCommandHeader` function to format the command header and avoid always having to manually log the `---` separator in command outputs - implements the `getWarpCoreConfigOrExit` to get the warp core configuration from either the registry or a user-defined path and exit early if no input value is provided - Updated the `IsmConfigSchema`s to include the `BaseIsmConfigSchema` because when parsing config files the address field was not included in the parsed object as it wasn't defined on the type Example output ![image](https://github.com/user-attachments/assets/07821a13-d2e2-4b73-b493-9a2c2829a7b3) ![image](https://github.com/user-attachments/assets/768d724f-c96e-4ff5-9c4d-332560c57626) ![image](https://github.com/user-attachments/assets/f92df7c5-acac-4ff7-974b-0334e4a221ab) ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4666 ### Backward compatibility - Yes ### Testing - Manual --- .changeset/grumpy-ears-relate.md | 6 + typescript/cli/src/check/warp.ts | 41 ++++++ typescript/cli/src/commands/config.ts | 8 +- typescript/cli/src/commands/options.ts | 26 +++- typescript/cli/src/commands/warp.ts | 186 ++++++++++--------------- typescript/cli/src/logger.ts | 4 + typescript/cli/src/read/warp.ts | 117 ++++++++++++++++ typescript/cli/src/utils/input.ts | 35 ++++- typescript/cli/src/utils/output.ts | 56 ++++++++ typescript/sdk/src/index.ts | 2 +- typescript/utils/src/index.ts | 2 + typescript/utils/src/objects.test.ts | 136 +++++++++++++++++- typescript/utils/src/objects.ts | 101 ++++++++++++++ 13 files changed, 596 insertions(+), 124 deletions(-) create mode 100644 .changeset/grumpy-ears-relate.md create mode 100644 typescript/cli/src/check/warp.ts create mode 100644 typescript/cli/src/read/warp.ts create mode 100644 typescript/cli/src/utils/output.ts diff --git a/.changeset/grumpy-ears-relate.md b/.changeset/grumpy-ears-relate.md new file mode 100644 index 000000000..8dbc0a515 --- /dev/null +++ b/.changeset/grumpy-ears-relate.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Adds the warp check command to compare warp routes config files with on chain warp route deployments diff --git a/typescript/cli/src/check/warp.ts b/typescript/cli/src/check/warp.ts new file mode 100644 index 000000000..a31fac62e --- /dev/null +++ b/typescript/cli/src/check/warp.ts @@ -0,0 +1,41 @@ +import { stringify as yamlStringify } from 'yaml'; + +import { WarpRouteDeployConfig, normalizeConfig } from '@hyperlane-xyz/sdk'; +import { ObjectDiff, diffObjMerge } from '@hyperlane-xyz/utils'; + +import { log, logGreen } from '../logger.js'; +import '../utils/output.js'; +import { formatYamlViolationsOutput } from '../utils/output.js'; + +export async function runWarpRouteCheck({ + warpRouteConfig, + onChainWarpConfig, +}: { + warpRouteConfig: WarpRouteDeployConfig; + onChainWarpConfig: WarpRouteDeployConfig; +}): Promise { + // Go through each chain and only add to the output the chains that have mismatches + const [violations, isInvalid] = Object.keys(warpRouteConfig).reduce( + (acc, chain) => { + const { mergedObject, isInvalid } = diffObjMerge( + normalizeConfig(onChainWarpConfig[chain]), + normalizeConfig(warpRouteConfig[chain]), + ); + + if (isInvalid) { + acc[0][chain] = mergedObject; + acc[1] ||= isInvalid; + } + + return acc; + }, + [{}, false] as [{ [index: string]: ObjectDiff }, boolean], + ); + + if (isInvalid) { + log(formatYamlViolationsOutput(yamlStringify(violations, null, 2))); + process.exit(1); + } + + logGreen(`No violations found`); +} diff --git a/typescript/cli/src/commands/config.ts b/typescript/cli/src/commands/config.ts index 7b145ca44..e72b72452 100644 --- a/typescript/cli/src/commands/config.ts +++ b/typescript/cli/src/commands/config.ts @@ -41,7 +41,7 @@ const validateChainCommand: CommandModuleWithContext<{ path: string }> = { command: 'chain', describe: 'Validate a chain config file', builder: { - path: inputFileCommandOption, + path: inputFileCommandOption(), }, handler: async ({ path }) => { readChainConfigs(path); @@ -54,7 +54,7 @@ const validateIsmCommand: CommandModuleWithContext<{ path: string }> = { command: 'ism', describe: 'Validate the basic ISM config file', builder: { - path: inputFileCommandOption, + path: inputFileCommandOption(), }, handler: async ({ path }) => { readMultisigConfig(path); @@ -67,7 +67,7 @@ const validateIsmAdvancedCommand: CommandModuleWithContext<{ path: string }> = { command: 'ism-advanced', describe: 'Validate the advanced ISM config file', builder: { - path: inputFileCommandOption, + path: inputFileCommandOption(), }, handler: async ({ path }) => { readIsmConfig(path); @@ -80,7 +80,7 @@ const validateWarpCommand: CommandModuleWithContext<{ path: string }> = { command: 'warp', describe: 'Validate a Warp Route deployment config file', builder: { - path: inputFileCommandOption, + path: inputFileCommandOption(), }, handler: async ({ path }) => { await readWarpRouteDeployConfig(path); diff --git a/typescript/cli/src/commands/options.ts b/typescript/cli/src/commands/options.ts index a251445be..218671509 100644 --- a/typescript/cli/src/commands/options.ts +++ b/typescript/cli/src/commands/options.ts @@ -91,11 +91,14 @@ export const hookCommandOption: Options = { 'A path to a JSON or YAML file with Hook configs (for every chain)', }; +export const DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH = + './configs/warp-route-deployment.yaml'; + export const warpDeploymentConfigCommandOption: Options = { type: 'string', description: 'A path to a JSON or YAML file with a warp route deployment config.', - default: './configs/warp-route-deployment.yaml', + default: DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH, alias: 'wd', }; @@ -134,12 +137,23 @@ export const outputFileCommandOption = ( demandOption, }); -export const inputFileCommandOption: Options = { +interface InputFileCommandOptionConfig + extends Pick { + defaultPath?: string; +} + +export const inputFileCommandOption = ({ + defaultPath, + demandOption = true, + description = 'Input file path', + alias = 'i', +}: InputFileCommandOptionConfig = {}): Options => ({ type: 'string', - description: 'Input file path', - alias: 'i', - demandOption: true, -}; + description, + default: defaultPath, + alias, + demandOption, +}); export const fromAddressCommandOption: Options = { type: 'string', diff --git a/typescript/cli/src/commands/warp.ts b/typescript/cli/src/commands/warp.ts index 107db6850..b7fb45624 100644 --- a/typescript/cli/src/commands/warp.ts +++ b/typescript/cli/src/commands/warp.ts @@ -1,24 +1,11 @@ -import { ethers } from 'ethers'; import { stringify as yamlStringify } from 'yaml'; import { CommandModule } from 'yargs'; -import { - HypXERC20Lockbox__factory, - HypXERC20__factory, - IXERC20__factory, -} from '@hyperlane-xyz/core'; -import { - ChainMap, - ChainSubmissionStrategySchema, - EvmERC20WarpRouteReader, - TokenStandard, - WarpCoreConfig, -} from '@hyperlane-xyz/sdk'; -import { objMap, promiseObjAll } from '@hyperlane-xyz/utils'; +import { ChainSubmissionStrategySchema } from '@hyperlane-xyz/sdk'; +import { runWarpRouteCheck } from '../check/warp.js'; import { createWarpRouteDeployConfig, - readWarpCoreConfig, readWarpRouteDeployConfig, } from '../config/warp.js'; import { @@ -27,7 +14,8 @@ import { } from '../context/types.js'; import { evaluateIfDryRunFailure } from '../deploy/dry-run.js'; import { runWarpRouteApply, runWarpRouteDeploy } from '../deploy/warp.js'; -import { log, logGray, logGreen, logRed, logTable } from '../logger.js'; +import { log, logCommandHeader, logGreen } from '../logger.js'; +import { runWarpRouteRead } from '../read/warp.js'; import { sendTestTransfer } from '../send/transfer.js'; import { indentYamlOrJson, @@ -35,13 +23,15 @@ import { removeEndingSlash, writeYamlOrJson, } from '../utils/files.js'; -import { selectRegistryWarpRoute } from '../utils/tokens.js'; +import { getWarpCoreConfigOrExit } from '../utils/input.js'; import { + DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH, addressCommandOption, chainCommandOption, dryRunCommandOption, fromAddressCommandOption, + inputFileCommandOption, outputFileCommandOption, strategyCommandOption, symbolCommandOption, @@ -59,6 +49,7 @@ export const warpCommand: CommandModule = { builder: (yargs) => yargs .command(apply) + .command(check) .command(deploy) .command(init) .command(read) @@ -104,17 +95,14 @@ export const apply: CommandModuleWithWriteContext<{ strategy: strategyUrl, receiptsDir, }) => { - logGray(`Hyperlane Warp Apply`); - logGray('--------------------'); // @TODO consider creating a helper function for these dashes - let warpCoreConfig: WarpCoreConfig; - if (symbol) { - warpCoreConfig = await selectRegistryWarpRoute(context.registry, symbol); - } else if (warp) { - warpCoreConfig = readWarpCoreConfig(warp); - } else { - logRed(`Please specify either a symbol or warp config`); - process.exit(0); - } + logCommandHeader('Hyperlane Warp Apply'); + + const warpCoreConfig = await getWarpCoreConfigOrExit({ + symbol, + warp, + context, + }); + if (strategyUrl) ChainSubmissionStrategySchema.parse(readYamlOrJson(strategyUrl)); const warpDeployConfig = await readWarpRouteDeployConfig(config); @@ -143,8 +131,9 @@ export const deploy: CommandModuleWithWriteContext<{ 'from-address': fromAddressCommandOption, }, handler: async ({ context, config, dryRun }) => { - logGray(`Hyperlane Warp Route Deployment${dryRun ? ' Dry-Run' : ''}`); - logGray('------------------------------------------------'); + logCommandHeader( + `Hyperlane Warp Route Deployment${dryRun ? ' Dry-Run' : ''}`, + ); try { await runWarpRouteDeploy({ @@ -171,11 +160,10 @@ export const init: CommandModuleWithContext<{ describe: 'Create an advanced ISM', default: false, }, - out: outputFileCommandOption('./configs/warp-route-deployment.yaml'), + out: outputFileCommandOption(DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH), }, handler: async ({ context, advanced, out }) => { - logGray('Hyperlane Warp Configure'); - logGray('------------------------'); + logCommandHeader('Hyperlane Warp Configure'); await createWarpRouteDeployConfig({ context, @@ -208,7 +196,7 @@ export const read: CommandModuleWithContext<{ false, ), config: outputFileCommandOption( - './configs/warp-route-deployment.yaml', + DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH, false, 'The path to output a Warp Config JSON or YAML file.', ), @@ -220,75 +208,14 @@ export const read: CommandModuleWithContext<{ config: configFilePath, symbol, }) => { - logGray('Hyperlane Warp Reader'); - logGray('---------------------'); - - const { multiProvider } = context; - - let addresses: ChainMap; - if (symbol) { - const warpCoreConfig = await selectRegistryWarpRoute( - context.registry, - symbol, - ); - - // TODO: merge with XERC20TokenAdapter and WarpRouteReader - const xerc20Limits = await Promise.all( - warpCoreConfig.tokens - .filter( - (t) => - t.standard === TokenStandard.EvmHypXERC20 || - t.standard === TokenStandard.EvmHypXERC20Lockbox, - ) - .map(async (t) => { - const provider = multiProvider.getProvider(t.chainName); - const router = t.addressOrDenom!; - const xerc20Address = - t.standard === TokenStandard.EvmHypXERC20Lockbox - ? await HypXERC20Lockbox__factory.connect( - router, - provider, - ).xERC20() - : await HypXERC20__factory.connect( - router, - provider, - ).wrappedToken(); + logCommandHeader('Hyperlane Warp Reader'); - const xerc20 = IXERC20__factory.connect(xerc20Address, provider); - const mint = await xerc20.mintingCurrentLimitOf(router); - const burn = await xerc20.burningCurrentLimitOf(router); - - const formattedLimits = objMap({ mint, burn }, (_, v) => - ethers.utils.formatUnits(v, t.decimals), - ); - - return [t.chainName, formattedLimits]; - }), - ); - if (xerc20Limits.length > 0) { - logGray('xERC20 Limits:'); - logTable(Object.fromEntries(xerc20Limits)); - } - - addresses = Object.fromEntries( - warpCoreConfig.tokens.map((t) => [t.chainName, t.addressOrDenom!]), - ); - } else if (chain && address) { - addresses = { - [chain]: address, - }; - } else { - logGreen(`Please specify either a symbol or chain and address`); - process.exit(0); - } - - const config = await promiseObjAll( - objMap(addresses, async (chain, address) => - new EvmERC20WarpRouteReader(multiProvider, chain).deriveWarpRouteConfig( - address, - ), - ), - ); + const config = await runWarpRouteRead({ + context, + chain, + address, + symbol, + }); if (configFilePath) { writeYamlOrJson(configFilePath, config, 'yaml'); @@ -346,15 +273,11 @@ const send: CommandModuleWithWriteContext< amount, recipient, }) => { - let warpCoreConfig: WarpCoreConfig; - if (symbol) { - warpCoreConfig = await selectRegistryWarpRoute(context.registry, symbol); - } else if (warp) { - warpCoreConfig = readWarpCoreConfig(warp); - } else { - logRed(`Please specify either a symbol or warp config`); - process.exit(0); - } + const warpCoreConfig = await getWarpCoreConfigOrExit({ + symbol, + warp, + context, + }); await sendTestTransfer({ context, @@ -370,3 +293,44 @@ const send: CommandModuleWithWriteContext< process.exit(0); }, }; + +export const check: CommandModuleWithContext<{ + config: string; + symbol?: string; + warp?: string; +}> = { + command: 'check', + describe: + 'Verifies that a warp route configuration matches the on chain configuration.', + builder: { + symbol: { + ...symbolCommandOption, + demandOption: false, + }, + warp: { + ...warpCoreConfigCommandOption, + demandOption: false, + }, + config: inputFileCommandOption({ + defaultPath: DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH, + description: 'The path to a warp route deployment configuration file', + }), + }, + handler: async ({ context, config, symbol, warp }) => { + logCommandHeader('Hyperlane Warp Check'); + + const warpRouteConfig = await readWarpRouteDeployConfig(config, context); + const onChainWarpConfig = await runWarpRouteRead({ + context, + warp, + symbol, + }); + + await runWarpRouteCheck({ + onChainWarpConfig, + warpRouteConfig, + }); + + process.exit(0); + }, +}; diff --git a/typescript/cli/src/logger.ts b/typescript/cli/src/logger.ts index d5347c66d..621d70e4d 100644 --- a/typescript/cli/src/logger.ts +++ b/typescript/cli/src/logger.ts @@ -57,5 +57,9 @@ export const errorRed = (...args: any) => logColor('error', chalk.red, ...args); export const logDebug = (msg: string, ...args: any) => logger.debug(msg, ...args); +export const logCommandHeader = (msg: string) => { + logGray(`${msg}\n${'_'.repeat(msg.length)}`); +}; + // No support for table in pino so print directly to console export const logTable = (...args: any) => console.table(...args); diff --git a/typescript/cli/src/read/warp.ts b/typescript/cli/src/read/warp.ts new file mode 100644 index 000000000..9139d890c --- /dev/null +++ b/typescript/cli/src/read/warp.ts @@ -0,0 +1,117 @@ +import { ethers } from 'ethers'; + +import { + HypXERC20Lockbox__factory, + HypXERC20__factory, + IXERC20__factory, +} from '@hyperlane-xyz/core'; +import { + ChainMap, + ChainName, + EvmERC20WarpRouteReader, + TokenStandard, +} from '@hyperlane-xyz/sdk'; +import { isAddressEvm, objMap, promiseObjAll } from '@hyperlane-xyz/utils'; + +import { CommandContext } from '../context/types.js'; +import { logGray, logRed, logTable } from '../logger.js'; +import { getWarpCoreConfigOrExit } from '../utils/input.js'; + +export async function runWarpRouteRead({ + context, + chain, + address, + warp, + symbol, +}: { + context: CommandContext; + chain?: ChainName; + warp?: string; + address?: string; + symbol?: string; +}): Promise> { + const { multiProvider } = context; + + let addresses: ChainMap; + if (symbol || warp) { + const warpCoreConfig = await getWarpCoreConfigOrExit({ + context, + warp, + symbol, + }); + + // TODO: merge with XERC20TokenAdapter and WarpRouteReader + const xerc20Limits = await Promise.all( + warpCoreConfig.tokens + .filter( + (t) => + t.standard === TokenStandard.EvmHypXERC20 || + t.standard === TokenStandard.EvmHypXERC20Lockbox, + ) + .map(async (t) => { + const provider = multiProvider.getProvider(t.chainName); + const router = t.addressOrDenom!; + const xerc20Address = + t.standard === TokenStandard.EvmHypXERC20Lockbox + ? await HypXERC20Lockbox__factory.connect( + router, + provider, + ).xERC20() + : await HypXERC20__factory.connect( + router, + provider, + ).wrappedToken(); + + const xerc20 = IXERC20__factory.connect(xerc20Address, provider); + const mint = await xerc20.mintingCurrentLimitOf(router); + const burn = await xerc20.burningCurrentLimitOf(router); + + const formattedLimits = objMap({ mint, burn }, (_, v) => + ethers.utils.formatUnits(v, t.decimals), + ); + + return [t.chainName, formattedLimits]; + }), + ); + + if (xerc20Limits.length > 0) { + logGray('xERC20 Limits:'); + logTable(Object.fromEntries(xerc20Limits)); + } + + addresses = Object.fromEntries( + warpCoreConfig.tokens.map((t) => [t.chainName, t.addressOrDenom!]), + ); + } else if (chain && address) { + addresses = { + [chain]: address, + }; + } else { + logRed(`Please specify either a symbol, chain and address or warp file`); + process.exit(1); + } + + // Check if there any non-EVM chains in the config and exit + const nonEvmChains = Object.entries(addresses) + .filter(([_, address]) => !isAddressEvm(address)) + .map(([chain]) => chain); + if (nonEvmChains.length > 0) { + const chainList = nonEvmChains.join(', '); + logRed( + `${chainList} ${ + nonEvmChains.length > 1 ? 'are' : 'is' + } non-EVM and not compatible with the cli`, + ); + process.exit(1); + } + + const config = await promiseObjAll( + objMap(addresses, async (chain, address) => + new EvmERC20WarpRouteReader(multiProvider, chain).deriveWarpRouteConfig( + address, + ), + ), + ); + + return config; +} diff --git a/typescript/cli/src/utils/input.ts b/typescript/cli/src/utils/input.ts index 4b54c4f3e..251c6c0c5 100644 --- a/typescript/cli/src/utils/input.ts +++ b/typescript/cli/src/utils/input.ts @@ -18,9 +18,14 @@ import type { PartialDeep } from '@inquirer/type'; import ansiEscapes from 'ansi-escapes'; import chalk from 'chalk'; -import { logGray } from '../logger.js'; +import { WarpCoreConfig } from '@hyperlane-xyz/sdk'; + +import { readWarpCoreConfig } from '../config/warp.js'; +import { CommandContext } from '../context/types.js'; +import { logGray, logRed } from '../logger.js'; import { indentYamlOrJson } from './files.js'; +import { selectRegistryWarpRoute } from './tokens.js'; export async function detectAndConfirmOrPrompt( detect: () => Promise, @@ -72,6 +77,34 @@ export async function inputWithInfo({ return answer; } +/** + * Gets a {@link WarpCoreConfig} based on the provided path or prompts the user to choose one: + * - if `symbol` is provided the user will have to select one of the available warp routes. + * - if `warp` is provided the config will be read by the provided file path. + * - if none is provided the CLI will exit. + */ +export async function getWarpCoreConfigOrExit({ + context, + symbol, + warp, +}: { + context: CommandContext; + symbol?: string; + warp?: string; +}): Promise { + let warpCoreConfig: WarpCoreConfig; + if (symbol) { + warpCoreConfig = await selectRegistryWarpRoute(context.registry, symbol); + } else if (warp) { + warpCoreConfig = readWarpCoreConfig(warp); + } else { + logRed(`Please specify either a symbol or warp config`); + process.exit(0); + } + + return warpCoreConfig; +} + /** * Searchable checkbox code * diff --git a/typescript/cli/src/utils/output.ts b/typescript/cli/src/utils/output.ts new file mode 100644 index 000000000..442b8a090 --- /dev/null +++ b/typescript/cli/src/utils/output.ts @@ -0,0 +1,56 @@ +import chalk from 'chalk'; + +export enum ViolationDiffType { + None, + Expected, + Actual, +} + +type FormatterByDiffType = Record string>; + +const defaultDiffFormatter: FormatterByDiffType = { + [ViolationDiffType.Actual]: chalk.red, + [ViolationDiffType.Expected]: chalk.green, + [ViolationDiffType.None]: (text: string) => text, +}; + +/** + * Takes a yaml formatted string and highlights differences by looking at `expected` and `actual` properties. + */ +export function formatYamlViolationsOutput( + yamlString: string, + formatters: FormatterByDiffType = defaultDiffFormatter, +): string { + const lines = yamlString.split('\n'); + + let curr: ViolationDiffType = ViolationDiffType.None; + let lastDiffIndent = 0; + const highlightedLines = lines.map((line) => { + // Get how many white space/tabs we have before the property name + const match = line.match(/^(\s*)/); + const currentIndent = match ? match[0].length : 0; + + let formattedLine = line; + // if the current indentation is smaller than the previous diff one + // we just got out of a diff property and we reset the formatting + if (currentIndent < lastDiffIndent) { + curr = ViolationDiffType.None; + } + + if (line.includes('expected:')) { + lastDiffIndent = currentIndent; + curr = ViolationDiffType.Expected; + formattedLine = line.replace('expected:', 'EXPECTED:'); + } + + if (line.includes('actual:')) { + lastDiffIndent = currentIndent; + curr = ViolationDiffType.Actual; + formattedLine = line.replace('actual:', 'ACTUAL:'); + } + + return formatters[curr](formattedLine); + }); + + return highlightedLines.join('\n'); +} diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index e80ad1f3e..415a11d26 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -487,7 +487,7 @@ export { setFork, stopImpersonatingAccount, } from './utils/fork.js'; -export { multisigIsmVerificationCost } from './utils/ism.js'; +export { multisigIsmVerificationCost, normalizeConfig } from './utils/ism.js'; export { MultiGeneric } from './utils/MultiGeneric.js'; export { SealevelAccountDataWrapper, diff --git a/typescript/utils/src/index.ts b/typescript/utils/src/index.ts index e45994f8f..0c18543dd 100644 --- a/typescript/utils/src/index.ts +++ b/typescript/utils/src/index.ts @@ -119,6 +119,8 @@ export { pick, promiseObjAll, stringifyObject, + diffObjMerge, + ObjectDiff, } from './objects.js'; export { Result, failure, success } from './result.js'; export { difference, setEquality, symmetricDifference } from './sets.js'; diff --git a/typescript/utils/src/objects.test.ts b/typescript/utils/src/objects.test.ts index b6fd1d012..d5ed72a6b 100644 --- a/typescript/utils/src/objects.test.ts +++ b/typescript/utils/src/objects.test.ts @@ -1,6 +1,12 @@ import { expect } from 'chai'; -import { deepCopy, deepEquals, objMerge, objOmit } from './objects.js'; +import { + deepCopy, + deepEquals, + diffObjMerge, + objMerge, + objOmit, +} from './objects.js'; describe('Object utilities', () => { it('deepEquals', () => { @@ -67,4 +73,132 @@ describe('Object utilities', () => { const omitted1_2 = objOmit(obj1, obj2, 10, false); expect(omitted1_2).to.eql({ a: 1, b: { d: 'string' } }); }); + + describe('diffObjMerge', () => { + it('should merge objects with equal values', () => { + const actual = { a: 1, b: 2 }; + const expected = { a: 1, b: 2 }; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: false, + mergedObject: { a: 1, b: 2 }, + }); + }); + + it('should return a diff for objects with different values', () => { + const actual = { a: 1, b: 2 }; + const expected = { a: 1, b: 3 }; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: true, + mergedObject: { + a: 1, + b: { actual: 2, expected: 3 }, + }, + }); + }); + + it('should detect missing fields in the top level object', () => { + const actual = { a: 1 }; + const expected = { a: 1, b: 3 }; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: true, + mergedObject: { + a: 1, + b: { actual: '', expected: 3 }, + }, + }); + }); + + it('should detect extra fields in the top level object', () => { + const actual = { a: 1, b: 2 }; + const expected = { a: 1 }; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: true, + mergedObject: { + a: 1, + b: { actual: 2, expected: '' }, + }, + }); + }); + + it('should merge nested objects and show differences', () => { + const actual = { a: 1, b: { c: 2, d: 4 } }; + const expected = { a: 1, b: { c: 2, d: 3 } }; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: true, + mergedObject: { + a: 1, + b: { + c: 2, + d: { actual: 4, expected: 3 }, + }, + }, + }); + }); + + it('should throw an error when maxDepth is exceeded', () => { + const actual = { a: { b: { c: { d: { e: 5 } } } } }; + const expected = { a: { b: { c: { d: { e: 5 } } } } }; + + expect(() => diffObjMerge(actual, expected, 3)).to.Throw( + 'diffObjMerge tried to go too deep', + ); + }); + + it('should merge arrays of equal length and show the diffs', () => { + const actual = [1, 2, 3]; + const expected = [1, 2, 4]; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: true, + mergedObject: [1, 2, { actual: 3, expected: 4 }], + }); + }); + + it('should return a diff for arrays of different lengths', () => { + const actual = [1, 2]; + const expected = [1, 2, 3]; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: true, + mergedObject: { + actual, + expected, + }, + }); + }); + + it('should handle null and undefined values properly', () => { + const actual = { a: null, b: 2 }; + const expected = { a: undefined, b: 2 }; + + const result = diffObjMerge(actual, expected); + + expect(result).to.eql({ + isInvalid: false, + mergedObject: { + a: undefined, + b: 2, + }, + }); + }); + }); }); diff --git a/typescript/utils/src/objects.ts b/typescript/utils/src/objects.ts index 680c5d579..403caa849 100644 --- a/typescript/utils/src/objects.ts +++ b/typescript/utils/src/objects.ts @@ -2,6 +2,7 @@ import { cloneDeep, isEqual } from 'lodash-es'; import { stringify as yamlStringify } from 'yaml'; import { ethersBigNumberSerializer } from './logging.js'; +import { isNullish } from './typeof.js'; import { assert } from './validation.js'; export function isObject(item: any) { @@ -216,3 +217,103 @@ export function stringifyObject( } return yamlStringify(JSON.parse(json), null, space); } + +interface ObjectDiffOutput { + actual: any; + expected: any; +} + +export type ObjectDiff = + | { + [key: string]: ObjectDiffOutput | ObjectDiff; + } + | ObjectDiff[] + | undefined; + +/** + * Merges 2 objects showing any difference in value for common fields. + */ +export function diffObjMerge( + actual: Record, + expected: Record, + maxDepth = 10, +): { + mergedObject: ObjectDiff; + isInvalid: boolean; +} { + if (maxDepth === 0) { + throw new Error('diffObjMerge tried to go too deep'); + } + + let isDiff = false; + if (!isObject(actual) && !isObject(expected) && actual === expected) { + return { + isInvalid: isDiff, + mergedObject: actual, + }; + } + + if (isNullish(actual) && isNullish(expected)) { + return { mergedObject: undefined, isInvalid: isDiff }; + } + + if (isObject(actual) && isObject(expected)) { + const ret: Record = {}; + + const actualKeys = new Set(Object.keys(actual)); + const expectedKeys = new Set(Object.keys(expected)); + const allKeys = new Set([...actualKeys, ...expectedKeys]); + for (const key of allKeys.values()) { + if (actualKeys.has(key) && expectedKeys.has(key)) { + const { mergedObject, isInvalid } = + diffObjMerge(actual[key], expected[key], maxDepth - 1) ?? {}; + ret[key] = mergedObject; + isDiff ||= isInvalid; + } else if (actualKeys.has(key) && !isNullish(actual[key])) { + ret[key] = { + actual: actual[key], + expected: '' as any, + }; + isDiff = true; + } else if (!isNullish(expected[key])) { + ret[key] = { + actual: '' as any, + expected: expected[key], + }; + isDiff = true; + } + } + return { + isInvalid: isDiff, + mergedObject: ret, + }; + } + + // Merge the elements of the array to see if there are any differences + if ( + Array.isArray(actual) && + Array.isArray(expected) && + actual.length === expected.length + ) { + const merged = actual.reduce( + (acc: [ObjectDiff[], boolean], curr, idx) => { + const { isInvalid, mergedObject } = diffObjMerge(curr, expected[idx]); + + acc[0].push(mergedObject); + acc[1] ||= isInvalid; + + return acc; + }, + [[], isDiff], + ); + return { + isInvalid: merged[1], + mergedObject: merged[0], + }; + } + + return { + mergedObject: { expected: expected ?? '', actual: actual ?? '' }, + isInvalid: true, + }; +} From c9085afd96c61a74207feff2dc5dbd86ec37ff95 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:38:32 +0530 Subject: [PATCH 162/224] fix: add fix for checking for correct messageId in `OPL2ToL1Ism` and `ArbL2ToL1Ism` via external call (#4437) ### Description - In agreement with Chainlight team's recommendation, added a second isVerified() check after portal call to make sure an arbitrary call which passes the check for metadata length and messageId cannot be verified without calling is verifyMessageId(messageId) in `OPL2ToL1Ism` and `ArbL2ToL1` ### Drive-by changes None ### Related issues - fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/2 ### Backward compatibility No, but the contracts aren't deployed anywhere ### Testing Unit testing --- .changeset/itchy-singers-hang.md | 5 +++++ solidity/contracts/isms/hook/ArbL2ToL1Ism.sol | 1 + solidity/contracts/isms/hook/OPL2ToL1Ism.sol | 4 ++-- solidity/test/isms/ERC5164ISM.t.sol | 2 ++ solidity/test/isms/ExternalBridgeTest.sol | 20 +++++++++++++++++-- solidity/test/isms/OPStackIsm.t.sol | 10 ++++++---- 6 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 .changeset/itchy-singers-hang.md diff --git a/.changeset/itchy-singers-hang.md b/.changeset/itchy-singers-hang.md new file mode 100644 index 000000000..97096ff1a --- /dev/null +++ b/.changeset/itchy-singers-hang.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': patch +--- + +Patched OPL2ToL1Ism to check for correct messageId for external call in verify diff --git a/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol b/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol index a7bd71447..98b5f9bd6 100644 --- a/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol +++ b/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol @@ -63,6 +63,7 @@ contract ArbL2ToL1Ism is ) external override returns (bool) { if (!isVerified(message)) { _verifyWithOutboxCall(metadata, message); + require(isVerified(message), "ArbL2ToL1Ism: message not verified"); } releaseValueToRecipient(message); return true; diff --git a/solidity/contracts/isms/hook/OPL2ToL1Ism.sol b/solidity/contracts/isms/hook/OPL2ToL1Ism.sol index b333b15cd..ef3986861 100644 --- a/solidity/contracts/isms/hook/OPL2ToL1Ism.sol +++ b/solidity/contracts/isms/hook/OPL2ToL1Ism.sol @@ -66,9 +66,9 @@ contract OPL2ToL1Ism is bytes calldata metadata, bytes calldata message ) external override returns (bool) { - bool verified = isVerified(message); - if (!verified) { + if (!isVerified(message)) { _verifyWithPortalCall(metadata, message); + require(isVerified(message), "OPL2ToL1Ism: message not verified"); } releaseValueToRecipient(message); return true; diff --git a/solidity/test/isms/ERC5164ISM.t.sol b/solidity/test/isms/ERC5164ISM.t.sol index 75c79fb82..8063979f4 100644 --- a/solidity/test/isms/ERC5164ISM.t.sol +++ b/solidity/test/isms/ERC5164ISM.t.sol @@ -150,6 +150,8 @@ contract ERC5164IsmTest is ExternalBridgeTest { function test_verify_valueAlreadyClaimed(uint256) public override {} + function test_verify_false_arbitraryCall() public override {} + /* ============ helper functions ============ */ function _externalBridgeDestinationCall( diff --git a/solidity/test/isms/ExternalBridgeTest.sol b/solidity/test/isms/ExternalBridgeTest.sol index 8db043fcf..344e001af 100644 --- a/solidity/test/isms/ExternalBridgeTest.sol +++ b/solidity/test/isms/ExternalBridgeTest.sol @@ -135,14 +135,14 @@ abstract contract ExternalBridgeTest is Test { 1 ether, messageId ); - ism.verify(externalCalldata, encodedMessage); + assertTrue(ism.verify(externalCalldata, encodedMessage)); assertEq(address(testRecipient).balance, 1 ether); } function test_verify_revertsWhen_invalidIsm() public virtual { bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( address(hook), - address(this), + address(hook), 0, messageId ); @@ -217,6 +217,19 @@ abstract contract ExternalBridgeTest is Test { assertEq(address(testRecipient).balance, _msgValue); } + function test_verify_false_arbitraryCall() public virtual { + bytes memory incorrectCalldata = _encodeExternalDestinationBridgeCall( + address(hook), + address(this), + 0, + messageId + ); + + vm.expectRevert(); + ism.verify(incorrectCalldata, encodedMessage); + assertFalse(ism.isVerified(encodedMessage)); + } + /* ============ helper functions ============ */ function _encodeTestMessage() internal view returns (bytes memory) { @@ -265,4 +278,7 @@ abstract contract ExternalBridgeTest is Test { function _setExternalOriginSender( address _sender ) internal virtual returns (bytes memory) {} + + // meant to mock an arbitrary successful call made by the external bridge + function verifyMessageId(bytes32 /*messageId*/) public payable {} } diff --git a/solidity/test/isms/OPStackIsm.t.sol b/solidity/test/isms/OPStackIsm.t.sol index 45c818ec3..3230e59b8 100644 --- a/solidity/test/isms/OPStackIsm.t.sol +++ b/solidity/test/isms/OPStackIsm.t.sol @@ -133,10 +133,10 @@ contract OPStackIsmTest is ExternalBridgeTest { } function _encodeExternalDestinationBridgeCall( - address _from, - address _to, - uint256 _msgValue, - bytes32 _messageId + address /*_from*/, + address /*_to*/, + uint256 /*_msgValue*/, + bytes32 /*_messageId*/ ) internal pure override returns (bytes memory) { return new bytes(0); } @@ -148,6 +148,8 @@ contract OPStackIsmTest is ExternalBridgeTest { function test_verify_revertsWhen_invalidIsm() public override {} + function test_verify_false_arbitraryCall() public override {} + /* ============ ISM.verifyMessageId ============ */ function test_verify_revertsWhen_notAuthorizedHook() public override { From 2760da1ded71159d8b681b75a3d2a797586e81d4 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:40:09 +0530 Subject: [PATCH 163/224] fix: ensure no duplicate signatures verified for `AbstractWeightedMultisigIsm.verify()` (#4468) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description - There's a bug in the verify function of `AbstractWeightedMultisigIsm` that an attacker might use to bypass the verification of multiple signatures. The code tried to check the duplication of the signers if not found, but the code does not increment validatorIndex when the recovered signer matches to the stored signer. For instance: - validatorsAndThresholdWeight returns [A, B, C, D] - an attacker uses signatures as [sig from A, sig from A, sig from A, sig from A, ...] or [sig from B, sig from B, …] Fix is to add a ++validatorIndex at the end of the for loop implies we don't allow the next signer to be the same as the signer we just verified. ### Drive-by changes None ### Related issues From Chainlight's audit findings ### Backward compatibility We haven't deployed these contracts yet on testnet/mainnet ### Testing Fuzz testing --- .../multisig/AbstractWeightedMultisigIsm.sol | 12 ++- solidity/test/isms/MultisigIsm.t.sol | 26 +++++++ solidity/test/isms/WeightedMultisigIsm.t.sol | 75 ++++++++++++++++++- 3 files changed, 107 insertions(+), 6 deletions(-) diff --git a/solidity/contracts/isms/multisig/AbstractWeightedMultisigIsm.sol b/solidity/contracts/isms/multisig/AbstractWeightedMultisigIsm.sol index 2264b192c..8b7fee049 100644 --- a/solidity/contracts/isms/multisig/AbstractWeightedMultisigIsm.sol +++ b/solidity/contracts/isms/multisig/AbstractWeightedMultisigIsm.sol @@ -73,11 +73,14 @@ abstract contract AbstractStaticWeightedMultisigIsm is // assumes that signatures are ordered by validator for ( - uint256 i = 0; - _totalWeight < _thresholdWeight && i < _validatorCount; - ++i + uint256 signatureIndex = 0; + _totalWeight < _thresholdWeight && signatureIndex < _validatorCount; + ++signatureIndex ) { - address _signer = ECDSA.recover(_digest, signatureAt(_metadata, i)); + address _signer = ECDSA.recover( + _digest, + signatureAt(_metadata, signatureIndex) + ); // loop through remaining validators until we find a match while ( _validatorIndex < _validatorCount && @@ -90,6 +93,7 @@ abstract contract AbstractStaticWeightedMultisigIsm is // add the weight of the current validator _totalWeight += _validators[_validatorIndex].weight; + ++_validatorIndex; } require( _totalWeight >= _thresholdWeight, diff --git a/solidity/test/isms/MultisigIsm.t.sol b/solidity/test/isms/MultisigIsm.t.sol index 8c0b61d38..29098475f 100644 --- a/solidity/test/isms/MultisigIsm.t.sol +++ b/solidity/test/isms/MultisigIsm.t.sol @@ -186,6 +186,32 @@ abstract contract AbstractMultisigIsmTest is Test { metadata[index] = ~metadata[index]; assertFalse(ism.verify(metadata, message)); } + + function test_verify_revertWhen_duplicateSignatures( + uint32 destination, + bytes32 recipient, + bytes calldata body, + uint8 m, + uint8 n, + bytes32 seed + ) public virtual { + vm.assume(1 < m && m <= n && n < 10); + bytes memory message = getMessage(destination, recipient, body); + bytes memory metadata = getMetadata(m, n, seed, message); + + bytes memory duplicateMetadata = new bytes(metadata.length); + for (uint256 i = 0; i < metadata.length - 65; i++) { + duplicateMetadata[i] = metadata[i]; + } + for (uint256 i = 0; i < 65; i++) { + duplicateMetadata[metadata.length - 65 + i] = metadata[ + metadata.length - 130 + i + ]; + } + + vm.expectRevert("!threshold"); + ism.verify(duplicateMetadata, message); + } } contract MerkleRootMultisigIsmTest is AbstractMultisigIsmTest { diff --git a/solidity/test/isms/WeightedMultisigIsm.t.sol b/solidity/test/isms/WeightedMultisigIsm.t.sol index df2a3d0ea..0c5fd7ee4 100644 --- a/solidity/test/isms/WeightedMultisigIsm.t.sol +++ b/solidity/test/isms/WeightedMultisigIsm.t.sol @@ -65,7 +65,6 @@ abstract contract AbstractStaticWeightedMultisigIsmTest is } } - // ism = IInterchainSecurityModule(deployedIsm); ism = IInterchainSecurityModule( weightedFactory.deploy(validators, threshold) ); @@ -136,7 +135,7 @@ abstract contract AbstractStaticWeightedMultisigIsmTest is return metadata; } - function testVerify_revertInsufficientWeight( + function test_verify_revertInsufficientWeight( uint32 destination, bytes32 recipient, bytes calldata body, @@ -161,6 +160,34 @@ abstract contract AbstractStaticWeightedMultisigIsmTest is vm.expectRevert("Insufficient validator weight"); ism.verify(insufficientMetadata, message); } + + function test_verify_revertWhen_duplicateSignatures( + uint32 destination, + bytes32 recipient, + bytes calldata body, + uint8 m, + uint8 n, + bytes32 seed + ) public virtual override { + vm.assume(1 < m && m <= n && n < 10); + bytes memory message = getMessage(destination, recipient, body); + bytes memory metadata = getMetadata(m, n, seed, message); + + bytes memory duplicateMetadata = new bytes(metadata.length); + for (uint256 i = 0; i < metadata.length - 65; i++) { + duplicateMetadata[i] = metadata[i]; + } + for (uint256 i = 0; i < 65; i++) { + duplicateMetadata[metadata.length - 65 + i] = metadata[ + metadata.length - 130 + i + ]; + } + + if (weightedIsm.signatureCount(metadata) >= 2) { + vm.expectRevert("Invalid signer"); + ism.verify(duplicateMetadata, message); + } + } } contract StaticMerkleRootWeightedMultisigIsmTest is @@ -194,6 +221,28 @@ contract StaticMerkleRootWeightedMultisigIsmTest is message ); } + + function test_verify_revertWhen_duplicateSignatures( + uint32 destination, + bytes32 recipient, + bytes calldata body, + uint8 m, + uint8 n, + bytes32 seed + ) + public + override(AbstractMultisigIsmTest, AbstractStaticWeightedMultisigIsmTest) + { + AbstractStaticWeightedMultisigIsmTest + .test_verify_revertWhen_duplicateSignatures( + destination, + recipient, + body, + m, + n, + seed + ); + } } contract StaticMessageIdWeightedMultisigIsmTest is @@ -227,4 +276,26 @@ contract StaticMessageIdWeightedMultisigIsmTest is message ); } + + function test_verify_revertWhen_duplicateSignatures( + uint32 destination, + bytes32 recipient, + bytes calldata body, + uint8 m, + uint8 n, + bytes32 seed + ) + public + override(AbstractMultisigIsmTest, AbstractStaticWeightedMultisigIsmTest) + { + AbstractStaticWeightedMultisigIsmTest + .test_verify_revertWhen_duplicateSignatures( + destination, + recipient, + body, + m, + n, + seed + ); + } } From ec6b874b15fcdee8ddbd189fb714866f2c5df6be Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:42:06 +0530 Subject: [PATCH 164/224] feat(contracts): add nonce for monotonically increasing delivery ordering for `HypERC4626` (#4534) ### Description - Added a `rateUpdateNonce` in `HypERC4626Collateral` and `previousNonce` in `HypERC4626` to ensure we only update the exchangeRate on the synthetic asset if the update was after the last recorded update. This is to make sure we don't update it to a stale exchange rate which may cause losses to users using the synthetic asset. ### Drive-by changes - `processInboundMessage` in MockMailbox` to simulate processing of messages out of order. ### Related issues - fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/12 ### Backward compatibility Yes ### Testing Unit test --- .changeset/red-actors-shop.md | 5 ++ solidity/contracts/mock/MockMailbox.sol | 5 ++ .../contracts/token/extensions/HypERC4626.sol | 14 +++- .../token/extensions/HypERC4626Collateral.sol | 9 ++- solidity/test/token/HypERC4626Test.t.sol | 69 +++++++++++++++++-- 5 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 .changeset/red-actors-shop.md diff --git a/.changeset/red-actors-shop.md b/.changeset/red-actors-shop.md new file mode 100644 index 000000000..0ee301e90 --- /dev/null +++ b/.changeset/red-actors-shop.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': patch +--- + +Added nonce to HypERC4626 diff --git a/solidity/contracts/mock/MockMailbox.sol b/solidity/contracts/mock/MockMailbox.sol index ad212dcef..c4b4b63e9 100644 --- a/solidity/contracts/mock/MockMailbox.sol +++ b/solidity/contracts/mock/MockMailbox.sol @@ -77,4 +77,9 @@ contract MockMailbox is Mailbox { Mailbox(address(this)).process{value: msg.value}("", _message); inboundProcessedNonce++; } + + function processInboundMessage(uint32 _nonce) public { + bytes memory _message = inboundMessages[_nonce]; + Mailbox(address(this)).process("", _message); + } } diff --git a/solidity/contracts/token/extensions/HypERC4626.sol b/solidity/contracts/token/extensions/HypERC4626.sol index 2252696fa..141b081ba 100644 --- a/solidity/contracts/token/extensions/HypERC4626.sol +++ b/solidity/contracts/token/extensions/HypERC4626.sol @@ -17,9 +17,12 @@ contract HypERC4626 is HypERC20 { using Message for bytes; using TokenMessage for bytes; + event ExchangeRateUpdated(uint256 newExchangeRate, uint32 rateUpdateNonce); + uint256 public constant PRECISION = 1e10; uint32 public immutable collateralDomain; uint256 public exchangeRate; // 1e10 + uint32 public previousNonce; constructor( uint8 _decimals, @@ -66,7 +69,16 @@ contract HypERC4626 is HypERC20 { bytes calldata _message ) internal virtual override { if (_origin == collateralDomain) { - exchangeRate = abi.decode(_message.metadata(), (uint256)); + (uint256 newExchangeRate, uint32 rateUpdateNonce) = abi.decode( + _message.metadata(), + (uint256, uint32) + ); + // only update if the nonce is greater than the previous nonce + if (rateUpdateNonce > previousNonce) { + exchangeRate = newExchangeRate; + previousNonce = rateUpdateNonce; + emit ExchangeRateUpdated(exchangeRate, rateUpdateNonce); + } } super._handle(_origin, _sender, _message); } diff --git a/solidity/contracts/token/extensions/HypERC4626Collateral.sol b/solidity/contracts/token/extensions/HypERC4626Collateral.sol index 8a084134c..0ae32ab2f 100644 --- a/solidity/contracts/token/extensions/HypERC4626Collateral.sol +++ b/solidity/contracts/token/extensions/HypERC4626Collateral.sol @@ -20,6 +20,8 @@ contract HypERC4626Collateral is HypERC20Collateral { uint256 public constant PRECISION = 1e10; bytes32 public constant NULL_RECIPIENT = 0x0000000000000000000000000000000000000000000000000000000000000001; + // Nonce for the rate update, to ensure sequential updates + uint32 public rateUpdateNonce; constructor( ERC4626 _vault, @@ -52,7 +54,12 @@ contract HypERC4626Collateral is HypERC20Collateral { vault.totalSupply(), Math.Rounding.Down ); - bytes memory _tokenMetadata = abi.encode(_exchangeRate); + + rateUpdateNonce++; + bytes memory _tokenMetadata = abi.encode( + _exchangeRate, + rateUpdateNonce + ); bytes memory _tokenMessage = TokenMessage.format( _recipient, diff --git a/solidity/test/token/HypERC4626Test.t.sol b/solidity/test/token/HypERC4626Test.t.sol index d09e0aae6..338d39b75 100644 --- a/solidity/test/token/HypERC4626Test.t.sol +++ b/solidity/test/token/HypERC4626Test.t.sol @@ -43,6 +43,8 @@ contract HypERC4626CollateralTest is HypTokenTest { HypERC4626 remoteRebasingToken; HypERC4626 peerRebasingToken; + event ExchangeRateUpdated(uint256 newExchangeRate, uint32 rateUpdateNonce); + function setUp() public override { super.setUp(); @@ -95,6 +97,7 @@ contract HypERC4626CollateralTest is HypTokenTest { peerRebasingToken = HypERC4626(address(peerToken)); primaryToken.transfer(ALICE, 1000e18); + primaryToken.transfer(BOB, 1000e18); uint32[] memory domains = new uint32[](3); domains[0] = ORIGIN; @@ -146,6 +149,47 @@ contract HypERC4626CollateralTest is HypTokenTest { ); } + function testRebase_exchangeRateUpdateInSequence() public { + _performRemoteTransferWithoutExpectation(0, transferAmount); + _accrueYield(); + + uint256 exchangeRateInitially = remoteRebasingToken.exchangeRate(); + + vm.startPrank(BOB); + primaryToken.approve(address(localToken), transferAmount); + localToken.transferRemote( + DESTINATION, + BOB.addressToBytes32(), + transferAmount + ); + vm.stopPrank(); + + _accrueYield(); + + vm.startPrank(ALICE); + primaryToken.approve(address(localToken), transferAmount); + localToken.transferRemote( + DESTINATION, + BOB.addressToBytes32(), + transferAmount + ); + vm.stopPrank(); + + // process ALICE's transfer + + vm.expectEmit(true, true, true, true); + emit ExchangeRateUpdated(10721400472, 3); + remoteMailbox.processInboundMessage(2); + uint256 exchangeRateBefore = remoteRebasingToken.exchangeRate(); + + // process BOB's transfer + remoteMailbox.processInboundMessage(1); + uint256 exchangeRateAfter = remoteRebasingToken.exchangeRate(); + + assertLt(exchangeRateInitially, exchangeRateBefore); // updates bc nonce=2 is after nonce=0 + assertEq(exchangeRateBefore, exchangeRateAfter); // doesn't update bc nonce=1 is before nonce=0 + } + function testSyntheticTransfers_withRebase() public { _performRemoteTransferWithoutExpectation(0, transferAmount); assertEq(remoteToken.balanceOf(BOB), transferAmount); @@ -173,6 +217,7 @@ contract HypERC4626CollateralTest is HypTokenTest { } function testWithdrawalWithoutYield() public { + uint256 bobPrimaryBefore = primaryToken.balanceOf(BOB); _performRemoteTransferWithoutExpectation(0, transferAmount); assertEq(remoteToken.balanceOf(BOB), transferAmount); @@ -183,10 +228,14 @@ contract HypERC4626CollateralTest is HypTokenTest { transferAmount ); localMailbox.processNextInboundMessage(); - assertEq(primaryToken.balanceOf(BOB), transferAmount); + assertEq( + primaryToken.balanceOf(BOB) - bobPrimaryBefore, + transferAmount + ); } function testWithdrawalWithYield() public { + uint256 bobPrimaryBefore = primaryToken.balanceOf(BOB); _performRemoteTransferWithoutExpectation(0, transferAmount); assertEq(remoteToken.balanceOf(BOB), transferAmount); @@ -205,13 +254,22 @@ contract HypERC4626CollateralTest is HypTokenTest { uint256 _expectedBal = transferAmount + _discountedYield(); // BOB gets the yield even though it didn't rebase - assertApproxEqRelDecimal(_bobBal, _expectedBal, 1e14, 0); - assertTrue(_bobBal < _expectedBal, "Transfer remote should round down"); + assertApproxEqRelDecimal( + _bobBal - bobPrimaryBefore, + _expectedBal, + 1e14, + 0 + ); + assertTrue( + _bobBal - bobPrimaryBefore < _expectedBal, + "Transfer remote should round down" + ); assertEq(vault.accumulatedFees(), YIELD / 10); } function testWithdrawalAfterYield() public { + uint256 bobPrimaryBefore = primaryToken.balanceOf(BOB); _performRemoteTransferWithoutExpectation(0, transferAmount); assertEq(remoteToken.balanceOf(BOB), transferAmount); @@ -230,7 +288,7 @@ contract HypERC4626CollateralTest is HypTokenTest { ); localMailbox.processNextInboundMessage(); assertApproxEqRelDecimal( - primaryToken.balanceOf(BOB), + primaryToken.balanceOf(BOB) - bobPrimaryBefore, transferAmount + _discountedYield(), 1e14, 0 @@ -287,6 +345,7 @@ contract HypERC4626CollateralTest is HypTokenTest { } function testWithdrawalAfterDrawdown() public { + uint256 bobPrimaryBefore = primaryToken.balanceOf(BOB); _performRemoteTransferWithoutExpectation(0, transferAmount); assertEq(remoteToken.balanceOf(BOB), transferAmount); @@ -306,7 +365,7 @@ contract HypERC4626CollateralTest is HypTokenTest { ); localMailbox.processNextInboundMessage(); assertApproxEqRelDecimal( - primaryToken.balanceOf(BOB), + primaryToken.balanceOf(BOB) - bobPrimaryBefore, transferAmount - drawdown, 1e14, 0 From 3e1ab756433479602e719fd0cd56979156cbde78 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:44:38 +0530 Subject: [PATCH 165/224] fix(contracts): add check for valid mailbox and relayer in `TrustedRelayerIsm` (#4553) ### Description - minor fix: add an isContract check for mailbox and non-zero check for relayer when instantiating TrustedRelayerIsm ### Drive-by changes None ### Related issues - partly fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/14 ### Backward compatibility Yes ### Testing Unit --- solidity/contracts/isms/TrustedRelayerIsm.sol | 9 +++++++++ solidity/test/isms/TrustedRelayerIsm.t.sol | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/solidity/contracts/isms/TrustedRelayerIsm.sol b/solidity/contracts/isms/TrustedRelayerIsm.sol index aba894a94..87da1bb60 100644 --- a/solidity/contracts/isms/TrustedRelayerIsm.sol +++ b/solidity/contracts/isms/TrustedRelayerIsm.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.0; // ============ Internal Imports ============ import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {Message} from "../libs/Message.sol"; import {Mailbox} from "../Mailbox.sol"; import {PackageVersioned} from "contracts/PackageVersioned.sol"; @@ -15,6 +16,14 @@ contract TrustedRelayerIsm is IInterchainSecurityModule, PackageVersioned { address public immutable trustedRelayer; constructor(address _mailbox, address _trustedRelayer) { + require( + _trustedRelayer != address(0), + "TrustedRelayerIsm: invalid relayer" + ); + require( + Address.isContract(_mailbox), + "TrustedRelayerIsm: invalid mailbox" + ); mailbox = Mailbox(_mailbox); trustedRelayer = _trustedRelayer; } diff --git a/solidity/test/isms/TrustedRelayerIsm.t.sol b/solidity/test/isms/TrustedRelayerIsm.t.sol index 51c574ba1..f630b6474 100644 --- a/solidity/test/isms/TrustedRelayerIsm.t.sol +++ b/solidity/test/isms/TrustedRelayerIsm.t.sol @@ -29,6 +29,13 @@ contract TrustedRelayerIsmTest is Test { recipient.setInterchainSecurityModule(address(ism)); } + function test_revertsWhen_invalidMailboxOrRelayer() public { + vm.expectRevert("TrustedRelayerIsm: invalid relayer"); + new TrustedRelayerIsm(address(mailbox), address(0)); + vm.expectRevert("TrustedRelayerIsm: invalid mailbox"); + new TrustedRelayerIsm(relayer, relayer); + } + function test_verify( uint32 origin, bytes32 sender, From c9bd7c3c52416f1c65cb413f33d422dfcc974d0f Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:49:02 +0530 Subject: [PATCH 166/224] fix(contracts): `RateLimit` minor changes (#4575) ### Description - Added a check for invalid capacity and event for token level change ### Drive-by changes None ### Related issues - fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/14 ### Backward compatibility Yes ### Testing Unit tests --- solidity/contracts/libs/RateLimited.sol | 42 +++++++++++++++++----- solidity/test/lib/RateLimited.t.sol | 47 ++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 9 deletions(-) diff --git a/solidity/contracts/libs/RateLimited.sol b/solidity/contracts/libs/RateLimited.sol index 4dfb8b262..c58c60379 100644 --- a/solidity/contracts/libs/RateLimited.sol +++ b/solidity/contracts/libs/RateLimited.sol @@ -1,5 +1,19 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; + +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +// ============ External Imports ============ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** @@ -7,16 +21,26 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own * @notice A contract used to keep track of an address sender's token amount limits. * @dev Implements a modified token bucket algorithm where the bucket is full in the beginning and gradually refills * See: https://dev.to/satrobit/rate-limiting-using-the-token-bucket-algorithm-3cjh - **/ + * + */ contract RateLimited is OwnableUpgradeable { uint256 public constant DURATION = 1 days; // 86400 - uint256 public filledLevel; /// @notice Current filled level - uint256 public refillRate; /// @notice Tokens per second refill rate - uint256 public lastUpdated; /// @notice Timestamp of the last time an action has been taken TODO prob can be uint40 + /// @notice Current filled level + uint256 public filledLevel; + /// @notice Tokens per second refill rate + uint256 public refillRate; + /// @notice Timestamp of the last time an action has been taken + uint256 public lastUpdated; event RateLimitSet(uint256 _oldCapacity, uint256 _newCapacity); + event ConsumedFilledLevel(uint256 filledLevel, uint256 lastUpdated); + constructor(uint256 _capacity) { + require( + _capacity >= DURATION, + "Capacity must be greater than DURATION" + ); _transferOwnership(msg.sender); setRefillRate(_capacity); filledLevel = _capacity; @@ -88,20 +112,22 @@ contract RateLimited is OwnableUpgradeable { /** * Validate an amount and decreases the currentCapacity - * @param _newAmount The amount to consume the fill level + * @param _consumedAmount The amount to consume the fill level * @return The new filled level */ function validateAndConsumeFilledLevel( - uint256 _newAmount + uint256 _consumedAmount ) public returns (uint256) { uint256 adjustedFilledLevel = calculateCurrentLevel(); - require(_newAmount <= adjustedFilledLevel, "RateLimitExceeded"); + require(_consumedAmount <= adjustedFilledLevel, "RateLimitExceeded"); // Reduce the filledLevel and update lastUpdated - uint256 _filledLevel = adjustedFilledLevel - _newAmount; + uint256 _filledLevel = adjustedFilledLevel - _consumedAmount; filledLevel = _filledLevel; lastUpdated = block.timestamp; + emit ConsumedFilledLevel(filledLevel, lastUpdated); + return _filledLevel; } } diff --git a/solidity/test/lib/RateLimited.t.sol b/solidity/test/lib/RateLimited.t.sol index 1276c86af..d0ea273de 100644 --- a/solidity/test/lib/RateLimited.t.sol +++ b/solidity/test/lib/RateLimited.t.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT or Apache-2.0 pragma solidity ^0.8.13; + import {Test} from "forge-std/Test.sol"; import {RateLimited} from "../../contracts/libs/RateLimited.sol"; @@ -13,8 +14,13 @@ contract RateLimitLibTest is Test { rateLimited = new RateLimited(MAX_CAPACITY); } + function testConstructor_revertsWhen_lowCapacity() public { + vm.expectRevert("Capacity must be greater than DURATION"); + new RateLimited(1 days - 1); + } + function testRateLimited_setsNewLimit() external { - rateLimited.setRefillRate(2 ether); + assert(rateLimited.setRefillRate(2 ether) > 0); assertApproxEqRel(rateLimited.maxCapacity(), 2 ether, ONE_PERCENT); assertEq(rateLimited.refillRate(), uint256(2 ether) / 1 days); // 2 ether / 1 day } @@ -45,6 +51,25 @@ contract RateLimitLibTest is Test { rateLimited.setRefillRate(1 ether); } + function testConsumedFilledLevelEvent() public { + uint256 consumeAmount = 0.5 ether; + + vm.expectEmit(true, true, false, true); + emit RateLimited.ConsumedFilledLevel( + 499999999999993600, + block.timestamp + ); // precision loss + rateLimited.validateAndConsumeFilledLevel(consumeAmount); + + assertApproxEqRelDecimal( + rateLimited.filledLevel(), + MAX_CAPACITY - consumeAmount, + 1e14, + 0 + ); + assertEq(rateLimited.lastUpdated(), block.timestamp); + } + function testRateLimited_neverReturnsGtMaxLimit( uint256 _newAmount, uint40 _newTime @@ -104,4 +129,24 @@ contract RateLimitLibTest is Test { currentTargetLimit = rateLimited.calculateCurrentLevel(); assertApproxEqRel(currentTargetLimit, MAX_CAPACITY, ONE_PERCENT); } + + function testCalculateCurrentLevel_revertsWhenCapacityIsZero() public { + rateLimited.setRefillRate(0); + + vm.expectRevert("RateLimitNotSet"); + rateLimited.calculateCurrentLevel(); + } + + function testValidateAndConsumeFilledLevel_revertsWhenExceedingLimit() + public + { + vm.warp(1 days); + uint256 initialLevel = rateLimited.calculateCurrentLevel(); + + uint256 excessAmount = initialLevel + 1 ether; + + vm.expectRevert("RateLimitExceeded"); + rateLimited.validateAndConsumeFilledLevel(excessAmount); + assertEq(rateLimited.calculateCurrentLevel(), initialLevel); + } } From 72c23c0d636dd9dc659542e129ea2f836255c50f Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:23:22 +0530 Subject: [PATCH 167/224] fix(contracts): owner vault metadata compatibility (#4566) ### Description - Added PRECISION and rateUpdateNonce to ensure compatibility of HypERC4626 (even though this is not a useful warp route bc exchangeRate will stay at 1e10) ### Drive-by changes None ### Related issues - closes https://github.com/chainlight-io/2024-08-hyperlane/issues/9 ### Backward compatibility No ### Testing Unit test --- .changeset/sweet-humans-argue.md | 5 ++ .../contracts/token/extensions/HypERC4626.sol | 17 ++++++- .../token/extensions/HypERC4626Collateral.sol | 19 +++++++- .../extensions/HypERC4626OwnerCollateral.sol | 27 +++++++++-- .../HypERC20CollateralVaultDeposit.t.sol | 47 +++++++++++++++++++ 5 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 .changeset/sweet-humans-argue.md diff --git a/.changeset/sweet-humans-argue.md b/.changeset/sweet-humans-argue.md new file mode 100644 index 000000000..3a6ff4647 --- /dev/null +++ b/.changeset/sweet-humans-argue.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': minor +--- + +Added PRECISION and rateUpdateNonce to ensure compatibility of HypERC4626 diff --git a/solidity/contracts/token/extensions/HypERC4626.sol b/solidity/contracts/token/extensions/HypERC4626.sol index 141b081ba..9ceb5536b 100644 --- a/solidity/contracts/token/extensions/HypERC4626.sol +++ b/solidity/contracts/token/extensions/HypERC4626.sol @@ -1,13 +1,28 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +// ============ Internal Imports ============ import {IXERC20} from "../interfaces/IXERC20.sol"; import {HypERC20} from "../HypERC20.sol"; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {Message} from "../../libs/Message.sol"; import {TokenMessage} from "../libs/TokenMessage.sol"; import {TokenRouter} from "../libs/TokenRouter.sol"; +// ============ External Imports ============ +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; + /** * @title Hyperlane ERC20 Rebasing Token * @author Abacus Works diff --git a/solidity/contracts/token/extensions/HypERC4626Collateral.sol b/solidity/contracts/token/extensions/HypERC4626Collateral.sol index 0ae32ab2f..87528b109 100644 --- a/solidity/contracts/token/extensions/HypERC4626Collateral.sol +++ b/solidity/contracts/token/extensions/HypERC4626Collateral.sol @@ -1,11 +1,26 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0; -import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +// ============ Internal Imports ============ import {TokenMessage} from "../libs/TokenMessage.sol"; import {HypERC20Collateral} from "../HypERC20Collateral.sol"; import {TypeCasts} from "../../libs/TypeCasts.sol"; +// ============ External Imports ============ +import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; + /** * @title Hyperlane ERC4626 Token Collateral with deposits collateral to a vault * @author Abacus Works @@ -17,7 +32,9 @@ contract HypERC4626Collateral is HypERC20Collateral { // Address of the ERC4626 compatible vault ERC4626 public immutable vault; + // Precision for the exchange rate uint256 public constant PRECISION = 1e10; + // Null recipient for rebase transfer bytes32 public constant NULL_RECIPIENT = 0x0000000000000000000000000000000000000000000000000000000000000001; // Nonce for the rate update, to ensure sequential updates diff --git a/solidity/contracts/token/extensions/HypERC4626OwnerCollateral.sol b/solidity/contracts/token/extensions/HypERC4626OwnerCollateral.sol index 1d4d64b0b..42d52f42c 100644 --- a/solidity/contracts/token/extensions/HypERC4626OwnerCollateral.sol +++ b/solidity/contracts/token/extensions/HypERC4626OwnerCollateral.sol @@ -1,9 +1,24 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0; -import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +// ============ Internal Imports ============ import {HypERC20Collateral} from "../HypERC20Collateral.sol"; +// ============ External Imports ============ +import {ERC4626} from "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; + /** * @title Hyperlane ERC20 Token Collateral with deposits collateral to a vault, the yield goes to the owner * @author ltyu @@ -11,9 +26,12 @@ import {HypERC20Collateral} from "../HypERC20Collateral.sol"; contract HypERC4626OwnerCollateral is HypERC20Collateral { // Address of the ERC4626 compatible vault ERC4626 public immutable vault; - + // standby precision for exchange rate + uint256 public constant PRECISION = 1e10; // Internal balance of total asset deposited uint256 public assetDeposited; + // Nonce for the rate update, to ensure sequential updates (not necessary for Owner variant but for compatibility with HypERC4626) + uint32 public rateUpdateNonce; event ExcessSharesSwept(uint256 amount, uint256 assetsRedeemed); @@ -40,8 +58,11 @@ contract HypERC4626OwnerCollateral is HypERC20Collateral { function _transferFromSender( uint256 _amount ) internal override returns (bytes memory metadata) { - metadata = super._transferFromSender(_amount); + super._transferFromSender(_amount); _depositIntoVault(_amount); + rateUpdateNonce++; + + return abi.encode(PRECISION, rateUpdateNonce); } /** diff --git a/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol b/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol index 3dba941b3..8d2f9226e 100644 --- a/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol +++ b/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol @@ -16,8 +16,11 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {HypERC4626} from "../../contracts/token/extensions/HypERC4626.sol"; + import {ERC4626Test} from "../../contracts/test/ERC4626/ERC4626Test.sol"; import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; +import {TokenMessage} from "../../contracts/token/libs/TokenMessage.sol"; import {HypTokenTest} from "./HypERC20.t.sol"; import {HypERC4626OwnerCollateral} from "../../contracts/token/extensions/HypERC4626OwnerCollateral.sol"; @@ -227,6 +230,20 @@ contract HypERC4626OwnerCollateralTest is HypTokenTest { ); } + function testERC4626VaultDeposit_TransferFromSender_CorrectMetadata() + public + { + remoteToken = new HypERC4626(18, address(remoteMailbox), ORIGIN); + _enrollRemoteTokenRouter(); + vm.prank(ALICE); + + primaryToken.approve(address(localToken), TRANSFER_AMT); + _performRemoteTransfer(0, TRANSFER_AMT, 1); + + assertEq(HypERC4626(address(remoteToken)).exchangeRate(), 1e10); + assertEq(HypERC4626(address(remoteToken)).previousNonce(), 1); + } + function testBenchmark_overheadGasUsage() public override { vm.prank(ALICE); primaryToken.approve(address(localToken), TRANSFER_AMT); @@ -243,4 +260,34 @@ contract HypERC4626OwnerCollateralTest is HypTokenTest { uint256 gasAfter = gasleft(); console.log("Overhead gas usage: %d", gasBefore - gasAfter); } + + function _performRemoteTransfer( + uint256 _msgValue, + uint256 _amount, + uint32 _nonce + ) internal { + vm.prank(ALICE); + localToken.transferRemote{value: _msgValue}( + DESTINATION, + BOB.addressToBytes32(), + _amount + ); + + vm.expectEmit(true, true, false, true); + emit ReceivedTransferRemote(ORIGIN, BOB.addressToBytes32(), _amount); + bytes memory _tokenMessage = TokenMessage.format( + BOB.addressToBytes32(), + _amount, + abi.encode(uint256(1e10), _nonce) + ); + + vm.prank(address(remoteMailbox)); + remoteToken.handle( + ORIGIN, + address(localToken).addressToBytes32(), + _tokenMessage + ); + + assertEq(remoteToken.balanceOf(BOB), _amount); + } } From 013d3211c03bea0c554673f1e0969a205c7a865c Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Tue, 22 Oct 2024 12:13:14 +0100 Subject: [PATCH 168/224] fix: use hyp_message as tracing field instead of message (#4721) ### Description https://docs.rs/tracing/latest/tracing/#shorthand-macros > unlike other fields, `message`'s shorthand initialization is just the string itself. When using tracing::info etc, passing in an explicit `message` field takes precedence over the message string that's supplied as the second positional param! So we end up in situations where we see `message: HyperlaneMessage { id: ....` instead of the log message we want! e.g. https://cloudlogging.app.goo.gl/Nr8Q5W5KviD6sT8W9 Open to other field names, like `msg` or something, but this felt explicit ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/main/agents/relayer/src/msg/gas_payment/mod.rs | 10 +++++----- .../agents/relayer/src/msg/metadata/multisig/base.rs | 4 ++-- .../src/msg/metadata/multisig/merkle_root_multisig.rs | 2 +- .../src/msg/metadata/multisig/message_id_multisig.rs | 2 +- rust/main/agents/relayer/src/msg/processor.rs | 2 +- .../chains/hyperlane-cosmos/src/mailbox/contract.rs | 2 +- rust/main/chains/hyperlane-fuel/src/mailbox.rs | 2 +- rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/rust/main/agents/relayer/src/msg/gas_payment/mod.rs b/rust/main/agents/relayer/src/msg/gas_payment/mod.rs index a13d0d26e..fa9f40b45 100644 --- a/rust/main/agents/relayer/src/msg/gas_payment/mod.rs +++ b/rust/main/agents/relayer/src/msg/gas_payment/mod.rs @@ -105,7 +105,7 @@ impl GasPaymentEnforcer { for (policy, whitelist) in &self.policies { if !whitelist.msg_matches(message, true) { trace!( - msg=%message, + hyp_message=%message, ?policy, ?whitelist, "Message did not match whitelist for policy" @@ -114,13 +114,13 @@ impl GasPaymentEnforcer { } trace!( - msg=%message, + hyp_message=%message, ?policy, ?whitelist, "Message matched whitelist for policy" ); debug!( - msg=%message, + hyp_message=%message, ?policy, ?current_payment, ?current_expenditure, @@ -149,7 +149,7 @@ impl GasPaymentEnforcer { } error!( - msg=%message, + hyp_message=%message, policies=?self.policies, "No gas payment policy matched for message; consider adding a default policy to the end of the policies array which uses a wildcard whitelist." ); @@ -159,7 +159,7 @@ impl GasPaymentEnforcer { pub fn record_tx_outcome(&self, message: &HyperlaneMessage, outcome: TxOutcome) -> Result<()> { // This log is required in E2E, hence the use of a `const` debug!( - msg=%message, + hyp_message=%message, ?outcome, "{}", GAS_EXPENDITURE_LOG_MESSAGE, diff --git a/rust/main/agents/relayer/src/msg/metadata/multisig/base.rs b/rust/main/agents/relayer/src/msg/metadata/multisig/base.rs index 328b8848b..f7898c721 100644 --- a/rust/main/agents/relayer/src/msg/metadata/multisig/base.rs +++ b/rust/main/agents/relayer/src/msg/metadata/multisig/base.rs @@ -126,11 +126,11 @@ impl MetadataBuilder for T { .await .context(CTX)? { - debug!(?message, ?metadata.checkpoint, "Found checkpoint with quorum"); + debug!(hyp_message=?message, ?metadata.checkpoint, "Found checkpoint with quorum"); Ok(Some(self.format_metadata(metadata)?)) } else { info!( - ?message, ?validators, threshold, ism=%multisig_ism.address(), + hyp_message=?message, ?validators, threshold, ism=%multisig_ism.address(), "Could not fetch metadata: Unable to reach quorum" ); Ok(None) diff --git a/rust/main/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs b/rust/main/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs index b8bcca040..ea73c5537 100644 --- a/rust/main/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs +++ b/rust/main/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs @@ -45,7 +45,7 @@ impl MultisigIsmMetadataBuilder for MerkleRootMultisigMetadataBuilder { .await .context(CTX)?, debug!( - ?message, + hyp_message=?message, "No merkle leaf found for message id, must have not been enqueued in the tree" ) ); diff --git a/rust/main/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs b/rust/main/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs index 9866c98b0..ab920c326 100644 --- a/rust/main/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs +++ b/rust/main/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs @@ -42,7 +42,7 @@ impl MultisigIsmMetadataBuilder for MessageIdMultisigMetadataBuilder { .await .context(CTX)?, debug!( - ?message, + hyp_message=?message, "No merkle leaf found for message id, must have not been enqueued in the tree" ) ); diff --git a/rust/main/agents/relayer/src/msg/processor.rs b/rust/main/agents/relayer/src/msg/processor.rs index 43bd93c67..59ec32cb6 100644 --- a/rust/main/agents/relayer/src/msg/processor.rs +++ b/rust/main/agents/relayer/src/msg/processor.rs @@ -163,7 +163,7 @@ impl DirectionalNonceIterator { if let Some(message) = self.indexed_message_with_nonce()? { Self::update_max_nonce_gauge(&message, metrics); if !self.is_message_processed()? { - debug!(?message, iterator=?self, "Found processable message"); + debug!(hyp_message=?message, iterator=?self, "Found processable message"); return Ok(MessageStatus::Processable(message)); } else { return Ok(MessageStatus::Processed); diff --git a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs index 7c3f1c4ee..9c793c93e 100644 --- a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs +++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs @@ -176,7 +176,7 @@ impl Mailbox for CosmosMailbox { Ok(tx_response_to_outcome(response)?) } - #[instrument(err, ret, skip(self), fields(msg=%message, metadata=%bytes_to_hex(metadata)))] + #[instrument(err, ret, skip(self), fields(hyp_message=%message, metadata=%bytes_to_hex(metadata)))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn process_estimate_costs( &self, diff --git a/rust/main/chains/hyperlane-fuel/src/mailbox.rs b/rust/main/chains/hyperlane-fuel/src/mailbox.rs index 3df6bdc9e..1c78e839e 100644 --- a/rust/main/chains/hyperlane-fuel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-fuel/src/mailbox.rs @@ -185,7 +185,7 @@ impl Mailbox for FuelMailbox { } // Process cost of the `process` method - #[instrument(err, ret, skip(self), fields(msg=%message, metadata=%bytes_to_hex(metadata)))] + #[instrument(err, ret, skip(self), fields(hyp_message=%message, metadata=%bytes_to_hex(metadata)))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn process_estimate_costs( &self, diff --git a/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs b/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs index c99990b43..76a51bfe3 100644 --- a/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs +++ b/rust/main/hyperlane-base/src/db/rocks/hyperlane_db.rs @@ -87,12 +87,12 @@ impl HyperlaneRocksDB { dispatched_block_number: u64, ) -> DbResult { if let Ok(Some(_)) = self.retrieve_message_id_by_nonce(&message.nonce) { - trace!(msg=?message, "Message already stored in db"); + trace!(hyp_message=?message, "Message already stored in db"); return Ok(false); } let id = message.id(); - debug!(msg=?message, "Storing new message in db",); + debug!(hyp_message=?message, "Storing new message in db",); // - `id` --> `message` self.store_message_by_id(&id, message)?; From 9de66f02336d34aa7e4f34f1cff2bb3f6dd6053d Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:59:46 -0400 Subject: [PATCH 169/224] fix: deriving ISM is very slow (#4720) ### Description This PR adds concurrency back to the modules and use retryAsync. ### Drive-by changes Add `maxAliasCount` param to yaml reader to prevent `ReferenceError: Excessive alias count indicates a resource exhaustion attack` ### Backward compatibility Yes ### Testing Manual --- .changeset/fresh-donkeys-smile.md | 6 ++ typescript/cli/src/utils/files.ts | 7 +- typescript/sdk/src/consts/concurrency.ts | 2 +- typescript/sdk/src/hook/EvmHookReader.ts | 127 ++++++++++++----------- typescript/sdk/src/ism/EvmIsmReader.ts | 97 ++++++++--------- 5 files changed, 127 insertions(+), 112 deletions(-) create mode 100644 .changeset/fresh-donkeys-smile.md diff --git a/.changeset/fresh-donkeys-smile.md b/.changeset/fresh-donkeys-smile.md new file mode 100644 index 000000000..23339249a --- /dev/null +++ b/.changeset/fresh-donkeys-smile.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Enable concurrency for IsmModule diff --git a/typescript/cli/src/utils/files.ts b/typescript/cli/src/utils/files.ts index 9c7cb6216..17b115a98 100644 --- a/typescript/cli/src/utils/files.ts +++ b/typescript/cli/src/utils/files.ts @@ -15,6 +15,7 @@ import { objMerge } from '@hyperlane-xyz/utils'; import { log } from '../logger.js'; export const MAX_READ_LINE_OUTPUT = 250; +export const MAX_ALIAS_YAML = 100_000; // Used for yaml maxAliasCount. Ref: https://eemeli.org/yaml/#tojs-options export type FileFormat = 'yaml' | 'json'; @@ -92,7 +93,9 @@ export function mergeJson>( } export function readYaml(filepath: string): T { - return yamlParse(readFileAtPath(filepath)) as T; + return yamlParse(readFileAtPath(filepath), { + maxAliasCount: MAX_ALIAS_YAML, + }) as T; } export function tryReadYamlAtPath(filepath: string): T | null { @@ -250,7 +253,7 @@ export function logYamlIfUnderMaxLines( ): void { const asYamlString = yamlStringify(obj, null, margin); const lineCounter = new LineCounter(); - parse(asYamlString, { lineCounter }); + parse(asYamlString, { lineCounter, maxAliasCount: MAX_ALIAS_YAML }); log(lineCounter.lineStarts.length < maxLines ? asYamlString : ''); } diff --git a/typescript/sdk/src/consts/concurrency.ts b/typescript/sdk/src/consts/concurrency.ts index d9cc8fa7c..62e6c801c 100644 --- a/typescript/sdk/src/consts/concurrency.ts +++ b/typescript/sdk/src/consts/concurrency.ts @@ -1 +1 @@ -export const DEFAULT_CONTRACT_READ_CONCURRENCY = 1; +export const DEFAULT_CONTRACT_READ_CONCURRENCY = 20; diff --git a/typescript/sdk/src/hook/EvmHookReader.ts b/typescript/sdk/src/hook/EvmHookReader.ts index f54c4cf50..bfbfff56a 100644 --- a/typescript/sdk/src/hook/EvmHookReader.ts +++ b/typescript/sdk/src/hook/EvmHookReader.ts @@ -22,6 +22,7 @@ import { concurrentMap, eqAddress, getLogLevel, + retryAsync, rootLogger, } from '@hyperlane-xyz/utils'; @@ -95,71 +96,73 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { } async deriveHookConfig(address: Address): Promise { - let onchainHookType: OnchainHookType | undefined = undefined; - let derivedHookConfig: DerivedHookConfig; - try { - const hook = IPostDispatchHook__factory.connect(address, this.provider); - this.logger.debug('Deriving HookConfig:', { address }); - - // Temporarily turn off SmartProvider logging - // Provider errors are expected because deriving will call methods that may not exist in the Bytecode - this.setSmartProviderLogLevel('silent'); - onchainHookType = await hook.hookType(); - - switch (onchainHookType) { - case OnchainHookType.ROUTING: - derivedHookConfig = await this.deriveDomainRoutingConfig(address); - break; - case OnchainHookType.AGGREGATION: - derivedHookConfig = await this.deriveAggregationConfig(address); - break; - case OnchainHookType.MERKLE_TREE: - derivedHookConfig = await this.deriveMerkleTreeConfig(address); - break; - case OnchainHookType.INTERCHAIN_GAS_PAYMASTER: - derivedHookConfig = await this.deriveIgpConfig(address); - break; - case OnchainHookType.FALLBACK_ROUTING: - derivedHookConfig = await this.deriveFallbackRoutingConfig(address); - break; - case OnchainHookType.PAUSABLE: - derivedHookConfig = await this.derivePausableConfig(address); - break; - case OnchainHookType.PROTOCOL_FEE: - derivedHookConfig = await this.deriveProtocolFeeConfig(address); - break; - // ID_AUTH_ISM could be OPStackHook, ERC5164Hook or LayerZeroV2Hook - // For now assume it's OP_STACK - case OnchainHookType.ID_AUTH_ISM: - derivedHookConfig = await this.deriveOpStackConfig(address); - break; - case OnchainHookType.ARB_L2_TO_L1: - derivedHookConfig = await this.deriveArbL2ToL1Config(address); - break; - default: - throw new Error( - `Unsupported HookType: ${OnchainHookType[onchainHookType]}`, + return retryAsync(async () => { + let onchainHookType: OnchainHookType | undefined = undefined; + let derivedHookConfig: DerivedHookConfig; + try { + const hook = IPostDispatchHook__factory.connect(address, this.provider); + this.logger.debug('Deriving HookConfig:', { address }); + + // Temporarily turn off SmartProvider logging + // Provider errors are expected because deriving will call methods that may not exist in the Bytecode + this.setSmartProviderLogLevel('silent'); + onchainHookType = await hook.hookType(); + + switch (onchainHookType) { + case OnchainHookType.ROUTING: + derivedHookConfig = await this.deriveDomainRoutingConfig(address); + break; + case OnchainHookType.AGGREGATION: + derivedHookConfig = await this.deriveAggregationConfig(address); + break; + case OnchainHookType.MERKLE_TREE: + derivedHookConfig = await this.deriveMerkleTreeConfig(address); + break; + case OnchainHookType.INTERCHAIN_GAS_PAYMASTER: + derivedHookConfig = await this.deriveIgpConfig(address); + break; + case OnchainHookType.FALLBACK_ROUTING: + derivedHookConfig = await this.deriveFallbackRoutingConfig(address); + break; + case OnchainHookType.PAUSABLE: + derivedHookConfig = await this.derivePausableConfig(address); + break; + case OnchainHookType.PROTOCOL_FEE: + derivedHookConfig = await this.deriveProtocolFeeConfig(address); + break; + // ID_AUTH_ISM could be OPStackHook, ERC5164Hook or LayerZeroV2Hook + // For now assume it's OP_STACK + case OnchainHookType.ID_AUTH_ISM: + derivedHookConfig = await this.deriveOpStackConfig(address); + break; + case OnchainHookType.ARB_L2_TO_L1: + derivedHookConfig = await this.deriveArbL2ToL1Config(address); + break; + default: + throw new Error( + `Unsupported HookType: ${OnchainHookType[onchainHookType]}`, + ); + } + } catch (e: any) { + let customMessage: string = `Failed to derive ${onchainHookType} hook (${address})`; + if ( + !onchainHookType && + e.message.includes('Invalid response from provider') + ) { + customMessage = customMessage.concat( + ` [The provided hook contract might be outdated and not support hookType()]`, ); + this.logger.info(`${customMessage}:\n\t${e}`); + } else { + this.logger.debug(`${customMessage}:\n\t${e}`); + } + throw new Error(`${customMessage}:\n\t${e}`); + } finally { + this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger } - } catch (e: any) { - let customMessage: string = `Failed to derive ${onchainHookType} hook (${address})`; - if ( - !onchainHookType && - e.message.includes('Invalid response from provider') - ) { - customMessage = customMessage.concat( - ` [The provided hook contract might be outdated and not support hookType()]`, - ); - this.logger.info(`${customMessage}:\n\t${e}`); - } else { - this.logger.debug(`${customMessage}:\n\t${e}`); - } - throw new Error(`${customMessage}:\n\t${e}`); - } finally { - this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger - } - return derivedHookConfig; + return derivedHookConfig; + }); } async deriveMerkleTreeConfig( diff --git a/typescript/sdk/src/ism/EvmIsmReader.ts b/typescript/sdk/src/ism/EvmIsmReader.ts index c7d766e8c..6448cede4 100644 --- a/typescript/sdk/src/ism/EvmIsmReader.ts +++ b/typescript/sdk/src/ism/EvmIsmReader.ts @@ -17,6 +17,7 @@ import { assert, concurrentMap, getLogLevel, + retryAsync, rootLogger, } from '@hyperlane-xyz/utils'; @@ -71,55 +72,57 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { } async deriveIsmConfig(address: Address): Promise { - let moduleType: ModuleType | undefined = undefined; - let derivedIsmConfig: DerivedIsmConfig; - try { - const ism = IInterchainSecurityModule__factory.connect( - address, - this.provider, - ); - this.logger.debug('Deriving IsmConfig:', { address }); - - // Temporarily turn off SmartProvider logging - // Provider errors are expected because deriving will call methods that may not exist in the Bytecode - this.setSmartProviderLogLevel('silent'); - moduleType = await ism.moduleType(); - - switch (moduleType) { - case ModuleType.UNUSED: - throw new Error('UNUSED does not have a corresponding IsmType'); - case ModuleType.ROUTING: - // IsmType is either ROUTING or FALLBACK_ROUTING, but that's determined inside deriveRoutingConfig - derivedIsmConfig = await this.deriveRoutingConfig(address); - break; - case ModuleType.AGGREGATION: - derivedIsmConfig = await this.deriveAggregationConfig(address); - break; - case ModuleType.LEGACY_MULTISIG: - throw new Error('LEGACY_MULTISIG is deprecated and not supported'); - case ModuleType.MERKLE_ROOT_MULTISIG: - case ModuleType.MESSAGE_ID_MULTISIG: - derivedIsmConfig = await this.deriveMultisigConfig(address); - break; - case ModuleType.NULL: - derivedIsmConfig = await this.deriveNullConfig(address); - break; - case ModuleType.CCIP_READ: - throw new Error('CCIP_READ does not have a corresponding IsmType'); - case ModuleType.ARB_L2_TO_L1: - return this.deriveArbL2ToL1Config(address); - default: - throw new Error(`Unknown ISM ModuleType: ${moduleType}`); + return retryAsync(async () => { + let moduleType: ModuleType | undefined = undefined; + let derivedIsmConfig: DerivedIsmConfig; + try { + const ism = IInterchainSecurityModule__factory.connect( + address, + this.provider, + ); + this.logger.debug('Deriving IsmConfig:', { address }); + + // Temporarily turn off SmartProvider logging + // Provider errors are expected because deriving will call methods that may not exist in the Bytecode + this.setSmartProviderLogLevel('silent'); + moduleType = await ism.moduleType(); + + switch (moduleType) { + case ModuleType.UNUSED: + throw new Error('UNUSED does not have a corresponding IsmType'); + case ModuleType.ROUTING: + // IsmType is either ROUTING or FALLBACK_ROUTING, but that's determined inside deriveRoutingConfig + derivedIsmConfig = await this.deriveRoutingConfig(address); + break; + case ModuleType.AGGREGATION: + derivedIsmConfig = await this.deriveAggregationConfig(address); + break; + case ModuleType.LEGACY_MULTISIG: + throw new Error('LEGACY_MULTISIG is deprecated and not supported'); + case ModuleType.MERKLE_ROOT_MULTISIG: + case ModuleType.MESSAGE_ID_MULTISIG: + derivedIsmConfig = await this.deriveMultisigConfig(address); + break; + case ModuleType.NULL: + derivedIsmConfig = await this.deriveNullConfig(address); + break; + case ModuleType.CCIP_READ: + throw new Error('CCIP_READ does not have a corresponding IsmType'); + case ModuleType.ARB_L2_TO_L1: + return this.deriveArbL2ToL1Config(address); + default: + throw new Error(`Unknown ISM ModuleType: ${moduleType}`); + } + } catch (e: any) { + const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`; + this.logger.debug(errorMessage); + throw new Error(errorMessage); + } finally { + this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger } - } catch (e: any) { - const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`; - this.logger.debug(errorMessage); - throw new Error(errorMessage); - } finally { - this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger - } - return derivedIsmConfig; + return derivedIsmConfig; + }); } async deriveRoutingConfig( From e15dc267b806f349b98959b602e103c10c89b31e Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:29:59 +0100 Subject: [PATCH 170/224] feat: amphreth warp config (#4719) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../mainnet3/warp/AMPHRETH-deployments.yaml | 28 ++++++++++ ...bitrumEthereumZircuitAmphrETHWarpConfig.ts | 55 +++++++++++++++++++ .../environments/mainnet3/warp/warpIds.ts | 1 + typescript/infra/config/warp.ts | 3 + typescript/infra/src/config/warp.ts | 1 + typescript/infra/src/warp/helm.ts | 2 +- 6 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.ts diff --git a/typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml new file mode 100644 index 000000000..222a321c2 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml @@ -0,0 +1,28 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +description: Hyperlane Warp Route artifacts +timestamp: '2024-10-18T14:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + arbitrum: + protocolType: ethereum + type: synthetic + hypAddress: '0x6D251aADfc6Ff69031e01eA39bE3cb5BABf8438f' + name: Amphor Restaked ETH + symbol: AMPHRETH + decimals: 18 + ethereum: + protocolType: ethereum + type: collateral + hypAddress: '0xdc89990a6fdC1C922b841f1d977835628A24Ed57' + tokenAddress: '0x5fD13359Ba15A84B76f7F87568309040176167cd' + name: Amphor Restaked ETH + symbol: AMPHRETH + decimals: 18 + zircuit: + protocolType: ethereum + type: synthetic + hypAddress: '0x7D5a79539d7B1c9aE5e54d18EEE188840f1Fe4CC' + name: Amphor Restaked ETH + symbol: AMPHRETH + decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.ts new file mode 100644 index 000000000..1b81e8110 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.ts @@ -0,0 +1,55 @@ +import { ethers } from 'ethers'; + +import { + ChainMap, + RouterConfig, + TokenRouterConfig, + TokenType, +} from '@hyperlane-xyz/sdk'; + +import { tokens } from '../../../../../src/config/warp.js'; + +const arbitrumOwner = '0x008615770B588633265cB01Abd19740fAe67d0B9'; +const ethereumOwner = '0x008615770B588633265cB01Abd19740fAe67d0B9'; +const zircuitOwner = '0xD0673e7F3FB4037CA79F53d2d311D0e017d39963'; + +export const getArbitrumEthereumZircuitAmphrETHWarpConfig = async ( + routerConfig: ChainMap, +): Promise> => { + const arbitrum: TokenRouterConfig = { + ...routerConfig.arbitrum, + type: TokenType.synthetic, + interchainSecurityModule: ethers.constants.AddressZero, + owner: arbitrumOwner, + ownerOverrides: { + proxyAdmin: arbitrumOwner, + }, + }; + + const ethereum: TokenRouterConfig = { + ...routerConfig.ethereum, + type: TokenType.collateral, + token: tokens.ethereum.amphrETH, + owner: ethereumOwner, + interchainSecurityModule: ethers.constants.AddressZero, + ownerOverrides: { + proxyAdmin: ethereumOwner, + }, + }; + + const zircuit: TokenRouterConfig = { + ...routerConfig.zircuit, + type: TokenType.synthetic, + interchainSecurityModule: ethers.constants.AddressZero, + owner: zircuitOwner, + ownerOverrides: { + proxyAdmin: zircuitOwner, + }, + }; + + return { + arbitrum, + ethereum, + zircuit, + }; +}; diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index 9ff51677e..debc81326 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -1,6 +1,7 @@ export enum WarpRouteIds { Ancient8EthereumUSDC = 'USDC/ancient8-ethereum', ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-sei-taiko-zircuit', + ArbitrumEthereumZircuitAMPHRETH = 'AMPHRETH/arbitrum-ethereum-zircuit', ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron', ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet', diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 447183e8c..2b7c44ee4 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -9,6 +9,7 @@ import { getHyperlaneCore } from '../scripts/core-utils.js'; import { EnvironmentConfig } from '../src/config/environment.js'; import { getAncient8EthereumUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getAncient8EthereumUSDCWarpConfig.js'; +import { getArbitrumEthereumZircuitAmphrETHWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.js'; import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronEclipWarpConfig.js'; import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js'; import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js'; @@ -34,6 +35,8 @@ export const warpConfigGetterMap: Record< WarpConfigGetterWithConfig | WarpConfigGetterWithoutConfig > = { [WarpRouteIds.Ancient8EthereumUSDC]: getAncient8EthereumUSDCWarpConfig, + [WarpRouteIds.ArbitrumEthereumZircuitAMPHRETH]: + getArbitrumEthereumZircuitAmphrETHWarpConfig, [WarpRouteIds.EthereumInevmUSDC]: getEthereumInevmUSDCWarpConfig, [WarpRouteIds.EthereumInevmUSDT]: getEthereumInevmUSDTWarpConfig, [WarpRouteIds.ArbitrumNeutronEclip]: getArbitrumNeutronEclipWarpConfig, diff --git a/typescript/infra/src/config/warp.ts b/typescript/infra/src/config/warp.ts index 25bd40818..d66aed2fc 100644 --- a/typescript/infra/src/config/warp.ts +++ b/typescript/infra/src/config/warp.ts @@ -7,6 +7,7 @@ export const tokens: ChainMap> = { USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdac17f958d2ee523a2206206994597c13d831ec7', deUSD: '0x15700B564Ca08D9439C58cA5053166E8317aa138', + amphrETH: '0x5fD13359Ba15A84B76f7F87568309040176167cd', }, sei: { fastUSD: '0x37a4dD9CED2b19Cfe8FAC251cd727b5787E45269', diff --git a/typescript/infra/src/warp/helm.ts b/typescript/infra/src/warp/helm.ts index 4633ddd83..f5aa0e981 100644 --- a/typescript/infra/src/warp/helm.ts +++ b/typescript/infra/src/warp/helm.ts @@ -27,7 +27,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager { return { image: { repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: 'd4d5501-20240925-222735', + tag: '6945b20-20241022-155935', }, configFilePath: pathRelativeToMonorepoRoot, fullnameOverride: this.helmReleaseName, From 29341950e5f99567712cbddb63919b48888e97c5 Mon Sep 17 00:00:00 2001 From: xeno097 Date: Tue, 22 Oct 2024 12:35:33 -0400 Subject: [PATCH 171/224] feat: cli core checker (#4687) ### Description This PR implements a new `core check` command to allow comparing local core contract configuration with the on chain deployment and detect mismatches. Examples: ![image](https://github.com/user-attachments/assets/5f0cd24a-45b1-4999-92d2-aa75182f9ef7) ![image](https://github.com/user-attachments/assets/e6b00714-0234-4f54-b63d-69aebd8148e9) ### Drive-by changes - Defined the `DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH` to remove repeated and hardcoded './configs/core-config.yaml' strings - Implemented the `executeCoreRead` function to reuse it in the `core check` command logic. - Added memorization to the `EvmHookReader` because reading on chain configuration for chains like `arbitrum`, `ethereum` or `optimism` was taking more than 10 minutes to complete due to repeated hook config retrieval ### Related issues - https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4666 ### Backward compatibility - Yes ### Testing - Manual ### Notes - Please merge #4667 before this PR because this was built on top of it --- .changeset/flat-swans-help.md | 7 ++ typescript/cli/src/commands/core.ts | 105 +++++++++++++++-------- typescript/cli/src/commands/options.ts | 2 + typescript/cli/src/read/core.ts | 36 ++++++++ typescript/sdk/src/hook/EvmHookReader.ts | 76 +++++++++++++--- 5 files changed, 182 insertions(+), 44 deletions(-) create mode 100644 .changeset/flat-swans-help.md create mode 100644 typescript/cli/src/read/core.ts diff --git a/.changeset/flat-swans-help.md b/.changeset/flat-swans-help.md new file mode 100644 index 000000000..e5f0e2111 --- /dev/null +++ b/.changeset/flat-swans-help.md @@ -0,0 +1,7 @@ +--- +'@hyperlane-xyz/utils': minor +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation diff --git a/typescript/cli/src/commands/core.ts b/typescript/cli/src/commands/core.ts index f691de750..60d84f877 100644 --- a/typescript/cli/src/commands/core.ts +++ b/typescript/cli/src/commands/core.ts @@ -1,10 +1,13 @@ +import { stringify as yamlStringify } from 'yaml'; import { CommandModule } from 'yargs'; import { + CoreConfig, DeployedCoreAddresses, DeployedCoreAddressesSchema, - EvmCoreReader, + normalizeConfig, } from '@hyperlane-xyz/sdk'; +import { diffObjMerge } from '@hyperlane-xyz/utils'; import { createCoreDeployConfig, @@ -16,17 +19,21 @@ import { } from '../context/types.js'; import { runCoreApply, runCoreDeploy } from '../deploy/core.js'; import { evaluateIfDryRunFailure } from '../deploy/dry-run.js'; -import { errorRed, log, logGray, logGreen } from '../logger.js'; +import { log, logCommandHeader, logGreen } from '../logger.js'; +import { executeCoreRead } from '../read/core.js'; import { logYamlIfUnderMaxLines, readYamlOrJson, writeYamlOrJson, } from '../utils/files.js'; +import { formatYamlViolationsOutput } from '../utils/output.js'; import { + DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH, chainCommandOption, dryRunCommandOption, fromAddressCommandOption, + inputFileCommandOption, outputFileCommandOption, skipConfirmationOption, } from './options.js'; @@ -40,6 +47,7 @@ export const coreCommand: CommandModule = { builder: (yargs) => yargs .command(apply) + .command(check) .command(deploy) .command(init) .command(read) @@ -47,6 +55,7 @@ export const coreCommand: CommandModule = { .demandCommand(), handler: () => log('Command required'), }; + export const apply: CommandModuleWithWriteContext<{ chain: string; config: string; @@ -60,14 +69,13 @@ export const apply: CommandModuleWithWriteContext<{ demandOption: true, }, config: outputFileCommandOption( - './configs/core-config.yaml', + DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH, true, 'The path to output a Core Config JSON or YAML file.', ), }, handler: async ({ context, chain, config: configFilePath }) => { - logGray(`Hyperlane Core Apply`); - logGray('--------------------'); + logCommandHeader(`Hyperlane Core Apply`); const addresses = (await context.registry.getChainAddresses( chain, @@ -103,7 +111,7 @@ export const deploy: CommandModuleWithWriteContext<{ builder: { chain: chainCommandOption, config: outputFileCommandOption( - './configs/core-config.yaml', + DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH, false, 'The path to a JSON or YAML file with a core deployment config.', ), @@ -112,8 +120,7 @@ export const deploy: CommandModuleWithWriteContext<{ 'skip-confirmation': skipConfirmationOption, }, handler: async ({ context, chain, config: configFilePath, dryRun }) => { - logGray(`Hyperlane Core deployment${dryRun ? ' dry-run' : ''}`); - logGray(`------------------------------------------------`); + logCommandHeader(`Hyperlane Core deployment${dryRun ? ' dry-run' : ''}`); try { await runCoreDeploy({ @@ -142,14 +149,13 @@ export const init: CommandModuleWithContext<{ default: false, }, config: outputFileCommandOption( - './configs/core-config.yaml', + DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH, false, 'The path to output a Core Config JSON or YAML file.', ), }, handler: async ({ context, advanced, config: configFilePath }) => { - logGray('Hyperlane Core Configure'); - logGray('------------------------'); + logCommandHeader('Hyperlane Core Configure'); await createCoreDeployConfig({ context, @@ -178,39 +184,70 @@ export const read: CommandModuleWithContext<{ description: 'Mailbox address used to derive the core config', }, config: outputFileCommandOption( - './configs/core-config.yaml', + DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH, false, 'The path to output a Core Config JSON or YAML file.', ), }, handler: async ({ context, chain, mailbox, config: configFilePath }) => { - if (!mailbox) { - const addresses = await context.registry.getChainAddresses(chain); - mailbox = addresses?.mailbox; - if (!mailbox) { - throw new Error( - `${chain} mailbox not provided and none found in registry.`, - ); - } - } + logCommandHeader('Hyperlane Core Read'); - logGray('Hyperlane Core Read'); - logGray('-------------------'); + const coreConfig = await executeCoreRead({ context, chain, mailbox }); - const evmCoreReader = new EvmCoreReader(context.multiProvider, chain); - try { - const coreConfig = await evmCoreReader.deriveCoreConfig(mailbox); - writeYamlOrJson(configFilePath, coreConfig, 'yaml'); - logGreen(`✅ Core config written successfully to ${configFilePath}:\n`); - logYamlIfUnderMaxLines(coreConfig); - } catch (e: any) { - errorRed( - `❌ Failed to read core config for mailbox ${mailbox} on ${chain}:`, - e, - ); + writeYamlOrJson(configFilePath, coreConfig, 'yaml'); + logGreen(`✅ Core config written successfully to ${configFilePath}:\n`); + logYamlIfUnderMaxLines(coreConfig); + + process.exit(0); + }, +}; + +export const check: CommandModuleWithContext<{ + chain: string; + config: string; + mailbox?: string; +}> = { + command: 'check', + describe: + 'Reads onchain Core configuration for a given mailbox address and compares it with a provided file', + builder: { + chain: { + ...chainCommandOption, + demandOption: true, + }, + mailbox: { + type: 'string', + description: + 'Mailbox address used to derive the core config. If not provided it will be inferred from the registry', + }, + config: inputFileCommandOption({ + defaultPath: DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH, + description: 'The path to a a Core Config JSON or YAML file.', + demandOption: false, + }), + }, + handler: async ({ context, chain, mailbox, config: configFilePath }) => { + logCommandHeader('Hyperlane Core Check'); + + const expectedCoreConfig: CoreConfig = await readYamlOrJson(configFilePath); + const onChainCoreConfig = await executeCoreRead({ + context, + chain, + mailbox, + }); + + const { mergedObject, isInvalid } = diffObjMerge( + normalizeConfig(onChainCoreConfig), + normalizeConfig(expectedCoreConfig), + ); + + if (isInvalid) { + log(formatYamlViolationsOutput(yamlStringify(mergedObject, null, 2))); process.exit(1); } + logGreen(`No violations found`); + process.exit(0); }, }; diff --git a/typescript/cli/src/commands/options.ts b/typescript/cli/src/commands/options.ts index 218671509..f23194c80 100644 --- a/typescript/cli/src/commands/options.ts +++ b/typescript/cli/src/commands/options.ts @@ -94,6 +94,8 @@ export const hookCommandOption: Options = { export const DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH = './configs/warp-route-deployment.yaml'; +export const DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH = './configs/core-config.yaml'; + export const warpDeploymentConfigCommandOption: Options = { type: 'string', description: diff --git a/typescript/cli/src/read/core.ts b/typescript/cli/src/read/core.ts new file mode 100644 index 000000000..b7f1f94b2 --- /dev/null +++ b/typescript/cli/src/read/core.ts @@ -0,0 +1,36 @@ +import { ChainName, CoreConfig, EvmCoreReader } from '@hyperlane-xyz/sdk'; +import { Address, assert } from '@hyperlane-xyz/utils'; + +import { CommandContext } from '../context/types.js'; +import { errorRed } from '../logger.js'; + +export async function executeCoreRead({ + context, + chain, + mailbox, +}: { + context: CommandContext; + chain: ChainName; + mailbox?: Address; +}): Promise { + if (!mailbox) { + const addresses = await context.registry.getChainAddresses(chain); + mailbox = addresses?.mailbox; + + assert( + mailbox, + `${chain} mailbox not provided and none found in registry.`, + ); + } + + const evmCoreReader = new EvmCoreReader(context.multiProvider, chain); + try { + return evmCoreReader.deriveCoreConfig(mailbox); + } catch (e: any) { + errorRed( + `❌ Failed to read core config for mailbox ${mailbox} on ${chain}:`, + e, + ); + process.exit(1); + } +} diff --git a/typescript/sdk/src/hook/EvmHookReader.ts b/typescript/sdk/src/hook/EvmHookReader.ts index bfbfff56a..a98e72b1b 100644 --- a/typescript/sdk/src/hook/EvmHookReader.ts +++ b/typescript/sdk/src/hook/EvmHookReader.ts @@ -84,6 +84,12 @@ export interface HookReader { export class EvmHookReader extends HyperlaneReader implements HookReader { protected readonly logger = rootLogger.child({ module: 'EvmHookReader' }); + /** + * HookConfig cache for already retrieved configs. Useful to avoid recomputing configs + * when they have already been retrieved in previous calls where `deriveHookConfig` was called by + * the specific hook methods. + */ + private _cache: Map = new Map(); constructor( protected readonly multiProvider: MultiProvider, @@ -96,12 +102,25 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { } async deriveHookConfig(address: Address): Promise { + this.logger.debug('Deriving HookConfig:', { address }); + + const cachedValue = this._cache.get(address); + if (cachedValue) { + this.logger.debug( + `Cache hit for HookConfig on chain ${this.chain} at: ${address}`, + ); + return cachedValue; + } + + this.logger.debug( + `Cache miss for HookConfig on chain ${this.chain} at: ${address}`, + ); + return retryAsync(async () => { let onchainHookType: OnchainHookType | undefined = undefined; let derivedHookConfig: DerivedHookConfig; try { const hook = IPostDispatchHook__factory.connect(address, this.provider); - this.logger.debug('Deriving HookConfig:', { address }); // Temporarily turn off SmartProvider logging // Provider errors are expected because deriving will call methods that may not exist in the Bytecode @@ -171,10 +190,14 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const hook = MerkleTreeHook__factory.connect(address, this.provider); this.assertHookType(await hook.hookType(), OnchainHookType.MERKLE_TREE); - return { + const config: WithAddress = { address, type: HookType.MERKLE_TREE, }; + + this._cache.set(address, config); + + return config; } async deriveAggregationConfig( @@ -190,11 +213,15 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { (hook) => this.deriveHookConfig(hook), ); - return { + const config: WithAddress = { address, type: HookType.AGGREGATION, hooks: hookConfigs, }; + + this._cache.set(address, config); + + return config; } async deriveIgpConfig(address: Address): Promise> { @@ -262,7 +289,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { oracleKey = resolvedOracleKeys[0]; } - return { + const config: WithAddress = { owner, address, type: HookType.INTERCHAIN_GAS_PAYMASTER, @@ -271,6 +298,10 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { overhead, oracleConfig, }; + + this._cache.set(address, config); + + return config; } async deriveProtocolFeeConfig( @@ -284,7 +315,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const protocolFee = await hook.protocolFee(); const beneficiary = await hook.beneficiary(); - return { + const config: WithAddress = { owner, address, type: HookType.PROTOCOL_FEE, @@ -292,6 +323,10 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { protocolFee: protocolFee.toString(), beneficiary, }; + + this._cache.set(address, config); + + return config; } async deriveOpStackConfig( @@ -306,13 +341,17 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const destinationChainName = this.multiProvider.getChainName(destinationDomain); - return { + const config: WithAddress = { owner, address, type: HookType.OP_STACK, nativeBridge: messengerContract, destinationChain: destinationChainName, }; + + this._cache.set(address, config); + + return config; } async deriveArbL2ToL1Config( @@ -324,12 +363,17 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const destinationDomain = await hook.destinationDomain(); const destinationChainName = this.multiProvider.getChainName(destinationDomain); - return { + + const config: WithAddress = { address, type: HookType.ARB_L2_TO_L1, destinationChain: destinationChainName, arbSys, }; + + this._cache.set(address, config); + + return config; } async deriveDomainRoutingConfig( @@ -341,12 +385,16 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const owner = await hook.owner(); const domainHooks = await this.fetchDomainHooks(hook); - return { + const config: WithAddress = { owner, address, type: HookType.ROUTING, domains: domainHooks, }; + + this._cache.set(address, config); + + return config; } async deriveFallbackRoutingConfig( @@ -367,13 +415,17 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const fallbackHook = await hook.fallbackHook(); const fallbackHookConfig = await this.deriveHookConfig(fallbackHook); - return { + const config: WithAddress = { owner, address, type: HookType.FALLBACK_ROUTING, domains: domainHooks, fallback: fallbackHookConfig, }; + + this._cache.set(address, config); + + return config; } private async fetchDomainHooks( @@ -409,12 +461,16 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const owner = await hook.owner(); const paused = await hook.paused(); - return { + const config: WithAddress = { owner, address, paused, type: HookType.PAUSABLE, }; + + this._cache.set(address, config); + + return config; } assertHookType( From cd7a263eb6eb7bfb3b771c16cba94c3351640790 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:41:08 -0400 Subject: [PATCH 172/224] fix: revert concurrency in Modules (#4730) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Reverts https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4720 Reasons: - Many of the public RPCs don't allow concurrency reads. The ones that do don't tell us how much they allow so no point in defaulting to some assumed number (20) - retryAsync doesn't do anything here as the SmartProvider knows what to do if a provider fails (retries with cooldown). SmartProvider has it's own retryAsync - Concurrency is configurable in the metadata. so configure for each provider, as intended. Screenshot 2024-10-22 at 4 11 02 PM --- .changeset/fresh-donkeys-smile.md | 6 -- typescript/cli/src/utils/files.ts | 7 +- typescript/sdk/src/consts/concurrency.ts | 2 +- typescript/sdk/src/hook/EvmHookReader.ts | 127 +++++++++++------------ typescript/sdk/src/ism/EvmIsmReader.ts | 97 +++++++++-------- 5 files changed, 113 insertions(+), 126 deletions(-) delete mode 100644 .changeset/fresh-donkeys-smile.md diff --git a/.changeset/fresh-donkeys-smile.md b/.changeset/fresh-donkeys-smile.md deleted file mode 100644 index 23339249a..000000000 --- a/.changeset/fresh-donkeys-smile.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Enable concurrency for IsmModule diff --git a/typescript/cli/src/utils/files.ts b/typescript/cli/src/utils/files.ts index 17b115a98..9c7cb6216 100644 --- a/typescript/cli/src/utils/files.ts +++ b/typescript/cli/src/utils/files.ts @@ -15,7 +15,6 @@ import { objMerge } from '@hyperlane-xyz/utils'; import { log } from '../logger.js'; export const MAX_READ_LINE_OUTPUT = 250; -export const MAX_ALIAS_YAML = 100_000; // Used for yaml maxAliasCount. Ref: https://eemeli.org/yaml/#tojs-options export type FileFormat = 'yaml' | 'json'; @@ -93,9 +92,7 @@ export function mergeJson>( } export function readYaml(filepath: string): T { - return yamlParse(readFileAtPath(filepath), { - maxAliasCount: MAX_ALIAS_YAML, - }) as T; + return yamlParse(readFileAtPath(filepath)) as T; } export function tryReadYamlAtPath(filepath: string): T | null { @@ -253,7 +250,7 @@ export function logYamlIfUnderMaxLines( ): void { const asYamlString = yamlStringify(obj, null, margin); const lineCounter = new LineCounter(); - parse(asYamlString, { lineCounter, maxAliasCount: MAX_ALIAS_YAML }); + parse(asYamlString, { lineCounter }); log(lineCounter.lineStarts.length < maxLines ? asYamlString : ''); } diff --git a/typescript/sdk/src/consts/concurrency.ts b/typescript/sdk/src/consts/concurrency.ts index 62e6c801c..d9cc8fa7c 100644 --- a/typescript/sdk/src/consts/concurrency.ts +++ b/typescript/sdk/src/consts/concurrency.ts @@ -1 +1 @@ -export const DEFAULT_CONTRACT_READ_CONCURRENCY = 20; +export const DEFAULT_CONTRACT_READ_CONCURRENCY = 1; diff --git a/typescript/sdk/src/hook/EvmHookReader.ts b/typescript/sdk/src/hook/EvmHookReader.ts index a98e72b1b..518b63e58 100644 --- a/typescript/sdk/src/hook/EvmHookReader.ts +++ b/typescript/sdk/src/hook/EvmHookReader.ts @@ -22,7 +22,6 @@ import { concurrentMap, eqAddress, getLogLevel, - retryAsync, rootLogger, } from '@hyperlane-xyz/utils'; @@ -116,72 +115,72 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { `Cache miss for HookConfig on chain ${this.chain} at: ${address}`, ); - return retryAsync(async () => { - let onchainHookType: OnchainHookType | undefined = undefined; - let derivedHookConfig: DerivedHookConfig; - try { - const hook = IPostDispatchHook__factory.connect(address, this.provider); - - // Temporarily turn off SmartProvider logging - // Provider errors are expected because deriving will call methods that may not exist in the Bytecode - this.setSmartProviderLogLevel('silent'); - onchainHookType = await hook.hookType(); - - switch (onchainHookType) { - case OnchainHookType.ROUTING: - derivedHookConfig = await this.deriveDomainRoutingConfig(address); - break; - case OnchainHookType.AGGREGATION: - derivedHookConfig = await this.deriveAggregationConfig(address); - break; - case OnchainHookType.MERKLE_TREE: - derivedHookConfig = await this.deriveMerkleTreeConfig(address); - break; - case OnchainHookType.INTERCHAIN_GAS_PAYMASTER: - derivedHookConfig = await this.deriveIgpConfig(address); - break; - case OnchainHookType.FALLBACK_ROUTING: - derivedHookConfig = await this.deriveFallbackRoutingConfig(address); - break; - case OnchainHookType.PAUSABLE: - derivedHookConfig = await this.derivePausableConfig(address); - break; - case OnchainHookType.PROTOCOL_FEE: - derivedHookConfig = await this.deriveProtocolFeeConfig(address); - break; - // ID_AUTH_ISM could be OPStackHook, ERC5164Hook or LayerZeroV2Hook - // For now assume it's OP_STACK - case OnchainHookType.ID_AUTH_ISM: - derivedHookConfig = await this.deriveOpStackConfig(address); - break; - case OnchainHookType.ARB_L2_TO_L1: - derivedHookConfig = await this.deriveArbL2ToL1Config(address); - break; - default: - throw new Error( - `Unsupported HookType: ${OnchainHookType[onchainHookType]}`, - ); - } - } catch (e: any) { - let customMessage: string = `Failed to derive ${onchainHookType} hook (${address})`; - if ( - !onchainHookType && - e.message.includes('Invalid response from provider') - ) { - customMessage = customMessage.concat( - ` [The provided hook contract might be outdated and not support hookType()]`, + let onchainHookType: OnchainHookType | undefined = undefined; + let derivedHookConfig: DerivedHookConfig; + + try { + const hook = IPostDispatchHook__factory.connect(address, this.provider); + this.logger.debug('Deriving HookConfig:', { address }); + + // Temporarily turn off SmartProvider logging + // Provider errors are expected because deriving will call methods that may not exist in the Bytecode + this.setSmartProviderLogLevel('silent'); + onchainHookType = await hook.hookType(); + + switch (onchainHookType) { + case OnchainHookType.ROUTING: + derivedHookConfig = await this.deriveDomainRoutingConfig(address); + break; + case OnchainHookType.AGGREGATION: + derivedHookConfig = await this.deriveAggregationConfig(address); + break; + case OnchainHookType.MERKLE_TREE: + derivedHookConfig = await this.deriveMerkleTreeConfig(address); + break; + case OnchainHookType.INTERCHAIN_GAS_PAYMASTER: + derivedHookConfig = await this.deriveIgpConfig(address); + break; + case OnchainHookType.FALLBACK_ROUTING: + derivedHookConfig = await this.deriveFallbackRoutingConfig(address); + break; + case OnchainHookType.PAUSABLE: + derivedHookConfig = await this.derivePausableConfig(address); + break; + case OnchainHookType.PROTOCOL_FEE: + derivedHookConfig = await this.deriveProtocolFeeConfig(address); + break; + // ID_AUTH_ISM could be OPStackHook, ERC5164Hook or LayerZeroV2Hook + // For now assume it's OP_STACK + case OnchainHookType.ID_AUTH_ISM: + derivedHookConfig = await this.deriveOpStackConfig(address); + break; + case OnchainHookType.ARB_L2_TO_L1: + derivedHookConfig = await this.deriveArbL2ToL1Config(address); + break; + default: + throw new Error( + `Unsupported HookType: ${OnchainHookType[onchainHookType]}`, ); - this.logger.info(`${customMessage}:\n\t${e}`); - } else { - this.logger.debug(`${customMessage}:\n\t${e}`); - } - throw new Error(`${customMessage}:\n\t${e}`); - } finally { - this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger } + } catch (e: any) { + let customMessage: string = `Failed to derive ${onchainHookType} hook (${address})`; + if ( + !onchainHookType && + e.message.includes('Invalid response from provider') + ) { + customMessage = customMessage.concat( + ` [The provided hook contract might be outdated and not support hookType()]`, + ); + this.logger.info(`${customMessage}:\n\t${e}`); + } else { + this.logger.debug(`${customMessage}:\n\t${e}`); + } + throw new Error(`${customMessage}:\n\t${e}`); + } finally { + this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger + } - return derivedHookConfig; - }); + return derivedHookConfig; } async deriveMerkleTreeConfig( diff --git a/typescript/sdk/src/ism/EvmIsmReader.ts b/typescript/sdk/src/ism/EvmIsmReader.ts index 6448cede4..c7d766e8c 100644 --- a/typescript/sdk/src/ism/EvmIsmReader.ts +++ b/typescript/sdk/src/ism/EvmIsmReader.ts @@ -17,7 +17,6 @@ import { assert, concurrentMap, getLogLevel, - retryAsync, rootLogger, } from '@hyperlane-xyz/utils'; @@ -72,57 +71,55 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { } async deriveIsmConfig(address: Address): Promise { - return retryAsync(async () => { - let moduleType: ModuleType | undefined = undefined; - let derivedIsmConfig: DerivedIsmConfig; - try { - const ism = IInterchainSecurityModule__factory.connect( - address, - this.provider, - ); - this.logger.debug('Deriving IsmConfig:', { address }); - - // Temporarily turn off SmartProvider logging - // Provider errors are expected because deriving will call methods that may not exist in the Bytecode - this.setSmartProviderLogLevel('silent'); - moduleType = await ism.moduleType(); - - switch (moduleType) { - case ModuleType.UNUSED: - throw new Error('UNUSED does not have a corresponding IsmType'); - case ModuleType.ROUTING: - // IsmType is either ROUTING or FALLBACK_ROUTING, but that's determined inside deriveRoutingConfig - derivedIsmConfig = await this.deriveRoutingConfig(address); - break; - case ModuleType.AGGREGATION: - derivedIsmConfig = await this.deriveAggregationConfig(address); - break; - case ModuleType.LEGACY_MULTISIG: - throw new Error('LEGACY_MULTISIG is deprecated and not supported'); - case ModuleType.MERKLE_ROOT_MULTISIG: - case ModuleType.MESSAGE_ID_MULTISIG: - derivedIsmConfig = await this.deriveMultisigConfig(address); - break; - case ModuleType.NULL: - derivedIsmConfig = await this.deriveNullConfig(address); - break; - case ModuleType.CCIP_READ: - throw new Error('CCIP_READ does not have a corresponding IsmType'); - case ModuleType.ARB_L2_TO_L1: - return this.deriveArbL2ToL1Config(address); - default: - throw new Error(`Unknown ISM ModuleType: ${moduleType}`); - } - } catch (e: any) { - const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`; - this.logger.debug(errorMessage); - throw new Error(errorMessage); - } finally { - this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger + let moduleType: ModuleType | undefined = undefined; + let derivedIsmConfig: DerivedIsmConfig; + try { + const ism = IInterchainSecurityModule__factory.connect( + address, + this.provider, + ); + this.logger.debug('Deriving IsmConfig:', { address }); + + // Temporarily turn off SmartProvider logging + // Provider errors are expected because deriving will call methods that may not exist in the Bytecode + this.setSmartProviderLogLevel('silent'); + moduleType = await ism.moduleType(); + + switch (moduleType) { + case ModuleType.UNUSED: + throw new Error('UNUSED does not have a corresponding IsmType'); + case ModuleType.ROUTING: + // IsmType is either ROUTING or FALLBACK_ROUTING, but that's determined inside deriveRoutingConfig + derivedIsmConfig = await this.deriveRoutingConfig(address); + break; + case ModuleType.AGGREGATION: + derivedIsmConfig = await this.deriveAggregationConfig(address); + break; + case ModuleType.LEGACY_MULTISIG: + throw new Error('LEGACY_MULTISIG is deprecated and not supported'); + case ModuleType.MERKLE_ROOT_MULTISIG: + case ModuleType.MESSAGE_ID_MULTISIG: + derivedIsmConfig = await this.deriveMultisigConfig(address); + break; + case ModuleType.NULL: + derivedIsmConfig = await this.deriveNullConfig(address); + break; + case ModuleType.CCIP_READ: + throw new Error('CCIP_READ does not have a corresponding IsmType'); + case ModuleType.ARB_L2_TO_L1: + return this.deriveArbL2ToL1Config(address); + default: + throw new Error(`Unknown ISM ModuleType: ${moduleType}`); } + } catch (e: any) { + const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`; + this.logger.debug(errorMessage); + throw new Error(errorMessage); + } finally { + this.setSmartProviderLogLevel(getLogLevel()); // returns to original level defined by rootLogger + } - return derivedIsmConfig; - }); + return derivedIsmConfig; } async deriveRoutingConfig( From c3e9268f1e2a4f69bd430e85a889a128957ca9fe Mon Sep 17 00:00:00 2001 From: Alexander Pastushenka Date: Wed, 23 Oct 2024 15:09:56 +0400 Subject: [PATCH 173/224] feat: Add block tag support in `reorgPeriod` parameter (#4629) ### Description Allows setting an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. Currently, only the Ethereum connector supports this feature with the following tags: - finalized - safe - pending - latest - earliest This is currently useful for EVM-compatible chains that don't have a fixed reorganization period, but instead rely on the block tag `Finalized` to indicate finality. For such chains, you should set `reorgPeriod` to `finalized` instead of a number of blocks. ### Drive-by changes ### Related issues ### Backward compatibility Yes ### Testing --------- Co-authored-by: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> --- .changeset/strange-beers-buy.md | 7 ++ rust/main/agents/validator/src/settings.rs | 12 +- rust/main/agents/validator/src/submit.rs | 26 ++-- rust/main/agents/validator/src/validator.rs | 17 ++- .../hyperlane-cosmos/src/mailbox/contract.rs | 9 +- .../hyperlane-cosmos/src/merkle_tree_hook.rs | 22 ++-- .../main/chains/hyperlane-cosmos/src/utils.rs | 25 ++-- .../chains/hyperlane-ethereum/src/config.rs | 34 +++++- .../src/contracts/interchain_gas.rs | 28 ++--- .../src/contracts/mailbox.rs | 37 +++--- .../src/contracts/merkle_tree_hook.rs | 51 ++++---- .../hyperlane-ethereum/src/contracts/mod.rs | 2 + .../hyperlane-ethereum/src/contracts/utils.rs | 35 +++++- rust/main/chains/hyperlane-ethereum/src/tx.rs | 24 ++-- .../main/chains/hyperlane-fuel/src/mailbox.rs | 9 +- .../chains/hyperlane-sealevel/src/mailbox.rs | 10 +- .../src/merkle_tree_hook.rs | 18 +-- .../hyperlane-base/src/settings/chains.rs | 42 ++++--- .../src/settings/checkpoint_syncer.rs | 8 +- .../hyperlane-base/src/settings/parser/mod.rs | 6 +- rust/main/hyperlane-core/src/chain.rs | 114 +++++++++++++++++- rust/main/hyperlane-core/src/error.rs | 9 +- .../main/hyperlane-core/src/traits/mailbox.rs | 7 +- .../src/traits/merkle_tree_hook.rs | 14 +-- rust/main/hyperlane-core/src/types/reorg.rs | 6 +- rust/main/hyperlane-test/src/mocks/mailbox.rs | 12 +- typescript/cli/src/config/chain.ts | 13 +- typescript/infra/config/registry.ts | 2 +- .../infra/src/config/agent/validator.ts | 4 +- .../sdk/src/metadata/chainMetadata.test.ts | 10 ++ .../sdk/src/metadata/chainMetadataTypes.ts | 11 +- 31 files changed, 421 insertions(+), 203 deletions(-) create mode 100644 .changeset/strange-beers-buy.md diff --git a/.changeset/strange-beers-buy.md b/.changeset/strange-beers-buy.md new file mode 100644 index 000000000..3ad5bc57e --- /dev/null +++ b/.changeset/strange-beers-buy.md @@ -0,0 +1,7 @@ +--- +'@hyperlane-xyz/infra': minor +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. diff --git a/rust/main/agents/validator/src/settings.rs b/rust/main/agents/validator/src/settings.rs index 02dc87cb1..d464be5a9 100644 --- a/rust/main/agents/validator/src/settings.rs +++ b/rust/main/agents/validator/src/settings.rs @@ -15,7 +15,9 @@ use hyperlane_base::{ CheckpointSyncerConf, Settings, SignerConf, }, }; -use hyperlane_core::{cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol}; +use hyperlane_core::{ + cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol, ReorgPeriod, +}; use serde::Deserialize; use serde_json::Value; @@ -36,8 +38,8 @@ pub struct ValidatorSettings { pub validator: SignerConf, /// The checkpoint syncer configuration pub checkpoint_syncer: CheckpointSyncerConf, - /// The reorg_period in blocks - pub reorg_period: u64, + /// The reorg configuration + pub reorg_period: ReorgPeriod, /// How frequently to check for new checkpoints pub interval: Duration, } @@ -122,8 +124,8 @@ impl FromRawConf for ValidatorSettings { .get_key(origin_chain_name) .get_opt_key("blocks") .get_opt_key("reorgPeriod") - .parse_u64() - .unwrap_or(1); + .parse_value("Invalid reorgPeriod") + .unwrap_or(ReorgPeriod::from_blocks(1)); cfg_unwrap_all!(cwp, err: [base, origin_chain, validator, checkpoint_syncer]); diff --git a/rust/main/agents/validator/src/submit.rs b/rust/main/agents/validator/src/submit.rs index 94d596467..954b8d0d9 100644 --- a/rust/main/agents/validator/src/submit.rs +++ b/rust/main/agents/validator/src/submit.rs @@ -1,4 +1,3 @@ -use std::num::NonZeroU64; use std::sync::Arc; use std::time::{Duration, Instant}; use std::vec; @@ -14,13 +13,13 @@ use hyperlane_core::{ accumulator::incremental::IncrementalMerkle, Checkpoint, CheckpointWithMessageId, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSignerExt, }; -use hyperlane_core::{ChainResult, MerkleTreeHook, ReorgEvent}; +use hyperlane_core::{ChainResult, MerkleTreeHook, ReorgEvent, ReorgPeriod}; use hyperlane_ethereum::SingletonSignerHandle; #[derive(Clone)] pub(crate) struct ValidatorSubmitter { interval: Duration, - reorg_period: Option, + reorg_period: ReorgPeriod, signer: SingletonSignerHandle, merkle_tree_hook: Arc, checkpoint_syncer: Arc, @@ -31,7 +30,7 @@ pub(crate) struct ValidatorSubmitter { impl ValidatorSubmitter { pub(crate) fn new( interval: Duration, - reorg_period: u64, + reorg_period: ReorgPeriod, merkle_tree_hook: Arc, signer: SingletonSignerHandle, checkpoint_syncer: Arc, @@ -39,7 +38,7 @@ impl ValidatorSubmitter { metrics: ValidatorSubmitterMetrics, ) -> Self { Self { - reorg_period: NonZeroU64::new(reorg_period), + reorg_period, interval, merkle_tree_hook, signer, @@ -94,7 +93,8 @@ impl ValidatorSubmitter { // Lag by reorg period because this is our correctness checkpoint. let latest_checkpoint = call_and_retry_indefinitely(|| { let merkle_tree_hook = self.merkle_tree_hook.clone(); - Box::pin(async move { merkle_tree_hook.latest_checkpoint(self.reorg_period).await }) + let reorg_period = self.reorg_period.clone(); + Box::pin(async move { merkle_tree_hook.latest_checkpoint(&reorg_period).await }) }) .await; @@ -211,7 +211,7 @@ impl ValidatorSubmitter { correctness_checkpoint.root, checkpoint.index, chrono::Utc::now().timestamp() as u64, - self.reorg_period.map(|x| x.get()).unwrap_or(0), + self.reorg_period.clone(), ); error!( ?checkpoint, @@ -486,9 +486,9 @@ mod test { #[async_trait] impl MerkleTreeHook for MerkleTreeHook { - async fn tree(&self, lag: Option) -> ChainResult; - async fn count(&self, lag: Option) -> ChainResult; - async fn latest_checkpoint(&self, lag: Option) -> ChainResult; + async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult; + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult; + async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult; } } @@ -532,7 +532,7 @@ mod test { expected_local_merkle_tree: &IncrementalMerkle, mock_onchain_merkle_tree: &IncrementalMerkle, unix_timestamp: u64, - expected_reorg_period: u64, + expected_reorg_period: ReorgPeriod, ) { assert_eq!( reorg_event.canonical_merkle_root, @@ -617,7 +617,7 @@ mod test { &expected_local_merkle_tree, &mock_onchain_merkle_tree_clone, unix_timestamp, - expected_reorg_period, + ReorgPeriod::from_blocks(expected_reorg_period), ); Ok(()) }); @@ -625,7 +625,7 @@ mod test { // instantiate the validator submitter let validator_submitter = ValidatorSubmitter::new( Duration::from_secs(1), - expected_reorg_period, + ReorgPeriod::from_blocks(expected_reorg_period), Arc::new(mock_merkle_tree_hook), dummy_singleton_handle(), Arc::new(mock_checkpoint_syncer), diff --git a/rust/main/agents/validator/src/validator.rs b/rust/main/agents/validator/src/validator.rs index 31fe809b4..2d09bd93f 100644 --- a/rust/main/agents/validator/src/validator.rs +++ b/rust/main/agents/validator/src/validator.rs @@ -1,4 +1,4 @@ -use std::{num::NonZeroU64, sync::Arc, time::Duration}; +use std::{sync::Arc, time::Duration}; use crate::server as validator_server; use async_trait::async_trait; @@ -19,8 +19,8 @@ use hyperlane_base::{ use hyperlane_core::{ Announcement, ChainResult, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSigner, - HyperlaneSignerExt, Mailbox, MerkleTreeHook, MerkleTreeInsertion, TxOutcome, ValidatorAnnounce, - H256, U256, + HyperlaneSignerExt, Mailbox, MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod, TxOutcome, + ValidatorAnnounce, H256, U256, }; use hyperlane_ethereum::{SingletonSigner, SingletonSignerHandle}; @@ -44,7 +44,7 @@ pub struct Validator { signer: SingletonSignerHandle, // temporary holder until `run` is called signer_instance: Option>, - reorg_period: u64, + reorg_period: ReorgPeriod, interval: Duration, checkpoint_syncer: Arc, core_metrics: Arc, @@ -184,12 +184,10 @@ impl BaseAgent for Validator { // announce the validator after spawning the signer task self.announce().await.expect("Failed to announce validator"); - let reorg_period = NonZeroU64::new(self.reorg_period); - // Ensure that the merkle tree hook has count > 0 before we begin indexing // messages or submitting checkpoints. loop { - match self.merkle_tree_hook.count(reorg_period).await { + match self.merkle_tree_hook.count(&self.reorg_period).await { Ok(0) => { info!("Waiting for first message in merkle tree hook"); sleep(self.interval).await; @@ -241,7 +239,7 @@ impl Validator { async fn run_checkpoint_submitters(&self) -> Vec>> { let submitter = ValidatorSubmitter::new( self.interval, - self.reorg_period, + self.reorg_period.clone(), self.merkle_tree_hook.clone(), self.signer.clone(), self.checkpoint_syncer.clone(), @@ -249,10 +247,9 @@ impl Validator { ValidatorSubmitterMetrics::new(&self.core.metrics, &self.origin_chain), ); - let reorg_period = NonZeroU64::new(self.reorg_period); let tip_tree = self .merkle_tree_hook - .tree(reorg_period) + .tree(&self.reorg_period) .await .expect("failed to get merkle tree"); // This function is only called after we have already checked that the diff --git a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs index 9c793c93e..5a998aac5 100644 --- a/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs +++ b/rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs @@ -8,7 +8,7 @@ use tracing::instrument; use hyperlane_core::{ utils::bytes_to_hex, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Mailbox, RawHyperlaneMessage, - TxCostEstimate, TxOutcome, H256, U256, + ReorgPeriod, TxCostEstimate, TxOutcome, H256, U256, }; use crate::grpc::WasmProvider; @@ -17,7 +17,7 @@ use crate::payloads::mailbox::{ GeneralMailboxQuery, ProcessMessageRequest, ProcessMessageRequestInner, }; use crate::types::tx_response_to_outcome; -use crate::utils::get_block_height_for_lag; +use crate::utils::get_block_height_for_reorg_period; use crate::{payloads, ConnectionConf, CosmosAddress, CosmosProvider, Signer}; #[derive(Clone, Debug)] @@ -82,8 +82,9 @@ impl HyperlaneChain for CosmosMailbox { impl Mailbox for CosmosMailbox { #[instrument(level = "debug", err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn count(&self, lag: Option) -> ChainResult { - let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?; + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { + let block_height = + get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?; self.nonce_at_block(block_height).await } diff --git a/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs index c9e48c59f..b9acdd357 100644 --- a/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs @@ -10,15 +10,15 @@ use hyperlane_core::accumulator::incremental::IncrementalMerkle; use hyperlane_core::{ ChainCommunicationError, ChainResult, Checkpoint, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, LogMeta, - MerkleTreeHook, MerkleTreeInsertion, SequenceAwareIndexer, H256, H512, + MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod, SequenceAwareIndexer, H256, H512, }; use crate::grpc::WasmProvider; use crate::payloads::{general, merkle_tree_hook}; use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; use crate::utils::{ - execute_and_parse_log_futures, get_block_height_for_lag, parse_logs_in_range, parse_logs_in_tx, - CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, + execute_and_parse_log_futures, get_block_height_for_reorg_period, parse_logs_in_range, + parse_logs_in_tx, CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64, }; use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError, Signer}; @@ -76,12 +76,13 @@ impl MerkleTreeHook for CosmosMerkleTreeHook { /// Return the incremental merkle tree in storage #[instrument(level = "debug", err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn tree(&self, lag: Option) -> ChainResult { + async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult { let payload = merkle_tree_hook::MerkleTreeRequest { tree: general::EmptyStruct {}, }; - let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?; + let block_height = + get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?; let data = self .provider @@ -110,23 +111,26 @@ impl MerkleTreeHook for CosmosMerkleTreeHook { } /// Gets the current leaf count of the merkle tree - async fn count(&self, lag: Option) -> ChainResult { + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { let payload = merkle_tree_hook::MerkleTreeCountRequest { count: general::EmptyStruct {}, }; - let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?; + let block_height = + get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?; self.count_at_block(block_height).await } + #[instrument(level = "debug", err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn latest_checkpoint(&self, lag: Option) -> ChainResult { + async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult { let payload = merkle_tree_hook::CheckPointRequest { check_point: general::EmptyStruct {}, }; - let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?; + let block_height = + get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?; let data = self .provider diff --git a/rust/main/chains/hyperlane-cosmos/src/utils.rs b/rust/main/chains/hyperlane-cosmos/src/utils.rs index 74cb75a27..f792090e6 100644 --- a/rust/main/chains/hyperlane-cosmos/src/utils.rs +++ b/rust/main/chains/hyperlane-cosmos/src/utils.rs @@ -11,7 +11,7 @@ use tendermint::Hash; use tokio::task::JoinHandle; use tracing::warn; -use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta, H256}; +use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta, ReorgPeriod, H256}; use crate::grpc::{WasmGrpcProvider, WasmProvider}; use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider}; @@ -24,20 +24,25 @@ pub(crate) const CONTRACT_ADDRESS_ATTRIBUTE_KEY: &str = "_contract_address"; pub(crate) static CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64: Lazy = Lazy::new(|| BASE64.encode(CONTRACT_ADDRESS_ATTRIBUTE_KEY)); -/// Given a lag, returns the block height at the moment. -/// If the lag is None, a block height of None is given, indicating that the -/// tip directly can be used. -pub(crate) async fn get_block_height_for_lag( +/// Given a `reorg_period`, returns the block height at the moment. +/// If the `reorg_period` is None, a block height of None is given, +/// indicating that the tip directly can be used. +pub(crate) async fn get_block_height_for_reorg_period( provider: &WasmGrpcProvider, - lag: Option, + reorg_period: &ReorgPeriod, ) -> ChainResult> { - let block_height = match lag { - Some(lag) => { + let block_height = match reorg_period { + ReorgPeriod::Blocks(blocks) => { let tip = provider.latest_block_height().await?; - let block_height = tip - lag.get(); + let block_height = tip - blocks.get() as u64; Some(block_height) } - None => None, + ReorgPeriod::None => None, + ReorgPeriod::Tag(_) => { + return Err(ChainCommunicationError::InvalidReorgPeriod( + reorg_period.clone(), + )) + } }; Ok(block_height) diff --git a/rust/main/chains/hyperlane-ethereum/src/config.rs b/rust/main/chains/hyperlane-ethereum/src/config.rs index 8735b5fd2..0e2a2a13a 100644 --- a/rust/main/chains/hyperlane-ethereum/src/config.rs +++ b/rust/main/chains/hyperlane-ethereum/src/config.rs @@ -1,4 +1,5 @@ -use hyperlane_core::{config::OperationBatchConfig, U256}; +use ethers_core::types::{BlockId, BlockNumber}; +use hyperlane_core::{config::OperationBatchConfig, ChainCommunicationError, ReorgPeriod, U256}; use url::Url; /// Ethereum RPC connection configuration @@ -52,3 +53,34 @@ pub struct TransactionOverrides { /// Max priority fee per gas to use for EIP-1559 transactions. pub max_priority_fee_per_gas: Option, } + +/// Ethereum reorg period +#[derive(Copy, Clone, Debug)] +pub enum EthereumReorgPeriod { + /// Number of blocks + Blocks(u32), + /// A block tag + Tag(BlockId), +} + +impl TryFrom<&ReorgPeriod> for EthereumReorgPeriod { + type Error = ChainCommunicationError; + + fn try_from(value: &ReorgPeriod) -> Result { + match value { + ReorgPeriod::None => Ok(EthereumReorgPeriod::Blocks(0)), + ReorgPeriod::Blocks(blocks) => Ok(EthereumReorgPeriod::Blocks(blocks.get())), + ReorgPeriod::Tag(tag) => { + let tag = match tag.as_str() { + "latest" => BlockNumber::Latest, + "finalized" => BlockNumber::Finalized, + "safe" => BlockNumber::Safe, + "earliest" => BlockNumber::Earliest, + "pending" => BlockNumber::Pending, + _ => return Err(ChainCommunicationError::InvalidReorgPeriod(value.clone())), + }; + Ok(EthereumReorgPeriod::Tag(tag.into())) + } + } + } +} diff --git a/rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs index b14903a64..d7cf37e81 100644 --- a/rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs @@ -9,18 +9,18 @@ use async_trait::async_trait; use ethers::prelude::Middleware; use hyperlane_core::rpc_clients::call_and_retry_indefinitely; use hyperlane_core::{ - ChainCommunicationError, ChainResult, ContractLocator, HyperlaneAbi, HyperlaneChain, - HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, - InterchainGasPaymaster, InterchainGasPayment, LogMeta, SequenceAwareIndexer, H160, H256, H512, + ChainResult, ContractLocator, HyperlaneAbi, HyperlaneChain, HyperlaneContract, HyperlaneDomain, + HyperlaneProvider, Indexed, Indexer, InterchainGasPaymaster, InterchainGasPayment, LogMeta, + SequenceAwareIndexer, H160, H256, H512, }; use tracing::instrument; -use super::utils::fetch_raw_logs_and_meta; +use super::utils::{fetch_raw_logs_and_meta, get_finalized_block_number}; use crate::interfaces::i_interchain_gas_paymaster::{ GasPaymentFilter, IInterchainGasPaymaster as EthereumInterchainGasPaymasterInternal, IINTERCHAINGASPAYMASTER_ABI, }; -use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider}; +use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider, EthereumReorgPeriod}; impl Display for EthereumInterchainGasPaymasterInternal where @@ -33,7 +33,7 @@ where pub struct InterchainGasPaymasterIndexerBuilder { pub mailbox_address: H160, - pub reorg_period: u32, + pub reorg_period: EthereumReorgPeriod, } #[async_trait] @@ -63,7 +63,7 @@ where { contract: Arc>, provider: Arc, - reorg_period: u32, + reorg_period: EthereumReorgPeriod, } impl EthereumInterchainGasPaymasterIndexer @@ -71,7 +71,11 @@ where M: Middleware + 'static, { /// Create new EthereumInterchainGasPaymasterIndexer - pub fn new(provider: Arc, locator: &ContractLocator, reorg_period: u32) -> Self { + pub fn new( + provider: Arc, + locator: &ContractLocator, + reorg_period: EthereumReorgPeriod, + ) -> Self { Self { contract: Arc::new(EthereumInterchainGasPaymasterInternal::new( locator.address, @@ -122,13 +126,7 @@ where #[instrument(level = "debug", err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { - Ok(self - .provider - .get_block_number() - .await - .map_err(ChainCommunicationError::from_other)? - .as_u32() - .saturating_sub(self.reorg_period)) + get_finalized_block_number(&self.provider, &self.reorg_period).await } async fn fetch_logs_by_tx_hash( diff --git a/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs index 72d01e4d6..a9141e7b7 100644 --- a/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs @@ -2,7 +2,6 @@ #![allow(missing_docs)] use std::collections::HashMap; -use std::num::NonZeroU64; use std::ops::RangeInclusive; use std::sync::Arc; @@ -14,7 +13,7 @@ use ethers_contract::builders::ContractCall; use ethers_contract::{Multicall, MulticallResult}; use futures_util::future::join_all; use hyperlane_core::rpc_clients::call_and_retry_indefinitely; -use hyperlane_core::{BatchResult, QueueOperation, H512}; +use hyperlane_core::{BatchResult, QueueOperation, ReorgPeriod, H512}; use itertools::Itertools; use tracing::instrument; @@ -31,11 +30,14 @@ use crate::interfaces::i_mailbox::{ IMailbox as EthereumMailboxInternal, ProcessCall, IMAILBOX_ABI, }; use crate::interfaces::mailbox::DispatchFilter; -use crate::tx::{call_with_lag, fill_tx_gas_params, report_tx}; -use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider, TransactionOverrides}; +use crate::tx::{call_with_reorg_period, fill_tx_gas_params, report_tx}; +use crate::{ + BuildableWithProvider, ConnectionConf, EthereumProvider, EthereumReorgPeriod, + TransactionOverrides, +}; use super::multicall::{self, build_multicall}; -use super::utils::fetch_raw_logs_and_meta; +use super::utils::{fetch_raw_logs_and_meta, get_finalized_block_number}; impl std::fmt::Display for EthereumMailboxInternal where @@ -47,7 +49,7 @@ where } pub struct SequenceIndexerBuilder { - pub reorg_period: u32, + pub reorg_period: EthereumReorgPeriod, } #[async_trait] @@ -70,7 +72,7 @@ impl BuildableWithProvider for SequenceIndexerBuilder { } pub struct DeliveryIndexerBuilder { - pub reorg_period: u32, + pub reorg_period: EthereumReorgPeriod, } #[async_trait] @@ -100,7 +102,7 @@ where { contract: Arc>, provider: Arc, - reorg_period: u32, + reorg_period: EthereumReorgPeriod, } impl EthereumMailboxIndexer @@ -108,7 +110,11 @@ where M: Middleware + 'static, { /// Create new EthereumMailboxIndexer - pub fn new(provider: Arc, locator: &ContractLocator, reorg_period: u32) -> Self { + pub fn new( + provider: Arc, + locator: &ContractLocator, + reorg_period: EthereumReorgPeriod, + ) -> Self { let contract = Arc::new(EthereumMailboxInternal::new( locator.address, provider.clone(), @@ -122,13 +128,7 @@ where #[instrument(level = "debug", err, ret, skip(self))] async fn get_finalized_block_number(&self) -> ChainResult { - Ok(self - .provider - .get_block_number() - .await - .map_err(ChainCommunicationError::from_other)? - .as_u32() - .saturating_sub(self.reorg_period)) + get_finalized_block_number(&self.provider, &self.reorg_period).await } } @@ -460,8 +460,9 @@ where M: Middleware + 'static, { #[instrument(skip(self))] - async fn count(&self, maybe_lag: Option) -> ChainResult { - let call = call_with_lag(self.contract.nonce(), &self.provider, maybe_lag).await?; + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { + let call = + call_with_reorg_period(self.contract.nonce(), &self.provider, reorg_period).await?; let nonce = call.call().await?; Ok(nonce) } diff --git a/rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs index a2f8a4a74..f098d75ca 100644 --- a/rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs @@ -1,5 +1,4 @@ #![allow(missing_docs)] -use std::num::NonZeroU64; use std::ops::RangeInclusive; use std::sync::Arc; @@ -10,18 +9,18 @@ use hyperlane_core::rpc_clients::call_and_retry_indefinitely; use tracing::instrument; use hyperlane_core::{ - ChainCommunicationError, ChainResult, Checkpoint, ContractLocator, HyperlaneChain, - HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, LogMeta, - MerkleTreeHook, MerkleTreeInsertion, SequenceAwareIndexer, H256, H512, + ChainResult, Checkpoint, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain, + HyperlaneProvider, Indexed, Indexer, LogMeta, MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod, + SequenceAwareIndexer, H256, H512, }; use crate::interfaces::merkle_tree_hook::{ InsertedIntoTreeFilter, MerkleTreeHook as MerkleTreeHookContract, Tree, }; -use crate::tx::call_with_lag; -use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider}; +use crate::tx::call_with_reorg_period; +use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider, EthereumReorgPeriod}; -use super::utils::fetch_raw_logs_and_meta; +use super::utils::{fetch_raw_logs_and_meta, get_finalized_block_number}; // We don't need the reverse of this impl, so it's ok to disable the clippy lint #[allow(clippy::from_over_into)] @@ -58,7 +57,7 @@ impl BuildableWithProvider for MerkleTreeHookBuilder { } pub struct MerkleTreeHookIndexerBuilder { - pub reorg_period: u32, + pub reorg_period: EthereumReorgPeriod, } #[async_trait] @@ -88,7 +87,7 @@ where { contract: Arc>, provider: Arc, - reorg_period: u32, + reorg_period: EthereumReorgPeriod, } impl EthereumMerkleTreeHookIndexer @@ -96,7 +95,11 @@ where M: Middleware + 'static, { /// Create new EthereumMerkleTreeHookIndexer - pub fn new(provider: Arc, locator: &ContractLocator, reorg_period: u32) -> Self { + pub fn new( + provider: Arc, + locator: &ContractLocator, + reorg_period: EthereumReorgPeriod, + ) -> Self { Self { contract: Arc::new(MerkleTreeHookContract::new( locator.address, @@ -143,13 +146,7 @@ where #[instrument(level = "debug", err, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { - Ok(self - .provider - .get_block_number() - .await - .map_err(ChainCommunicationError::from_other)? - .as_u32() - .saturating_sub(self.reorg_period)) + get_finalized_block_number(&self.provider, &self.reorg_period).await } async fn fetch_logs_by_tx_hash( @@ -253,9 +250,13 @@ where M: Middleware + 'static, { #[instrument(skip(self))] - async fn latest_checkpoint(&self, maybe_lag: Option) -> ChainResult { - let call = - call_with_lag(self.contract.latest_checkpoint(), &self.provider, maybe_lag).await?; + async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult { + let call = call_with_reorg_period( + self.contract.latest_checkpoint(), + &self.provider, + reorg_period, + ) + .await?; let (root, index) = call.call().await?; Ok(Checkpoint { @@ -268,15 +269,17 @@ where #[instrument(skip(self))] #[allow(clippy::needless_range_loop)] - async fn tree(&self, maybe_lag: Option) -> ChainResult { - let call = call_with_lag(self.contract.tree(), &self.provider, maybe_lag).await?; + async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult { + let call = + call_with_reorg_period(self.contract.tree(), &self.provider, reorg_period).await?; Ok(call.call().await?.into()) } #[instrument(skip(self))] - async fn count(&self, maybe_lag: Option) -> ChainResult { - let call = call_with_lag(self.contract.count(), &self.provider, maybe_lag).await?; + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { + let call = + call_with_reorg_period(self.contract.count(), &self.provider, reorg_period).await?; let count = call.call().await?; Ok(count) } diff --git a/rust/main/chains/hyperlane-ethereum/src/contracts/mod.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/mod.rs index 1a39fae07..f8475f9e7 100644 --- a/rust/main/chains/hyperlane-ethereum/src/contracts/mod.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/mod.rs @@ -1,5 +1,7 @@ pub use {interchain_gas::*, mailbox::*, merkle_tree_hook::*, validator_announce::*}; +pub(crate) use utils::get_finalized_block_number; + mod interchain_gas; mod mailbox; mod merkle_tree_hook; diff --git a/rust/main/chains/hyperlane-ethereum/src/contracts/utils.rs b/rust/main/chains/hyperlane-ethereum/src/contracts/utils.rs index 290519918..5e9c78201 100644 --- a/rust/main/chains/hyperlane-ethereum/src/contracts/utils.rs +++ b/rust/main/chains/hyperlane-ethereum/src/contracts/utils.rs @@ -6,7 +6,10 @@ use ethers::{ types::{H160 as EthersH160, H256 as EthersH256}, }; use ethers_contract::{ContractError, EthEvent, LogMeta as EthersLogMeta}; -use hyperlane_core::{ChainResult, LogMeta, H512}; +use hyperlane_core::{ChainCommunicationError, ChainResult, LogMeta, H512}; +use tracing::instrument; + +use crate::EthereumReorgPeriod; pub async fn fetch_raw_logs_and_meta( tx_hash: H512, @@ -44,3 +47,33 @@ where .collect(); Ok(logs) } + +#[instrument(level = "trace", err, ret, skip(provider))] +pub async fn get_finalized_block_number( + provider: &M, + reorg_period: &EthereumReorgPeriod, +) -> ChainResult +where + M: Middleware + 'static, +{ + let number = match *reorg_period { + EthereumReorgPeriod::Blocks(blocks) => provider + .get_block_number() + .await + .map_err(ChainCommunicationError::from_other)? + .as_u32() + .saturating_sub(blocks), + + EthereumReorgPeriod::Tag(tag) => provider + .get_block(tag) + .await + .map_err(ChainCommunicationError::from_other)? + .and_then(|block| block.number) + .ok_or(ChainCommunicationError::CustomError( + "Unable to get finalized block number".into(), + ))? + .as_u32(), + }; + + Ok(number) +} diff --git a/rust/main/chains/hyperlane-ethereum/src/tx.rs b/rust/main/chains/hyperlane-ethereum/src/tx.rs index eb42f66d4..2e774622a 100644 --- a/rust/main/chains/hyperlane-ethereum/src/tx.rs +++ b/rust/main/chains/hyperlane-ethereum/src/tx.rs @@ -1,4 +1,3 @@ -use std::num::NonZeroU64; use std::sync::Arc; use std::time::Duration; @@ -16,10 +15,12 @@ use ethers_core::{ EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE, }, }; -use hyperlane_core::{utils::bytes_to_hex, ChainCommunicationError, ChainResult, H256, U256}; +use hyperlane_core::{ + utils::bytes_to_hex, ChainCommunicationError, ChainResult, ReorgPeriod, H256, U256, +}; use tracing::{debug, error, info, warn}; -use crate::{Middleware, TransactionOverrides}; +use crate::{get_finalized_block_number, EthereumReorgPeriod, Middleware, TransactionOverrides}; /// An amount of gas to add to the estimated gas pub const GAS_ESTIMATE_BUFFER: u32 = 75_000; @@ -216,23 +217,20 @@ where Ok((base_fee_per_gas, max_fee_per_gas, max_priority_fee_per_gas)) } -pub(crate) async fn call_with_lag( +pub(crate) async fn call_with_reorg_period( call: ethers::contract::builders::ContractCall, provider: &M, - maybe_lag: Option, + reorg_period: &ReorgPeriod, ) -> ChainResult> where M: Middleware + 'static, T: Detokenize, { - if let Some(lag) = maybe_lag { - let fixed_block_number: BlockNumber = provider - .get_block_number() - .await - .map_err(ChainCommunicationError::from_other)? - .saturating_sub(lag.get().into()) - .into(); - Ok(call.block(fixed_block_number)) + if !reorg_period.is_none() { + let reorg_period = EthereumReorgPeriod::try_from(reorg_period)?; + let block = get_finalized_block_number(provider, &reorg_period).await? as u64; + + Ok(call.block(block)) } else { Ok(call) } diff --git a/rust/main/chains/hyperlane-fuel/src/mailbox.rs b/rust/main/chains/hyperlane-fuel/src/mailbox.rs index 1c78e839e..fbe951abe 100644 --- a/rust/main/chains/hyperlane-fuel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-fuel/src/mailbox.rs @@ -10,13 +10,12 @@ use fuels::{ use hyperlane_core::{ utils::bytes_to_hex, ChainCommunicationError, ChainResult, ContractLocator, HyperlaneAbi, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, - Indexed, Indexer, LogMeta, Mailbox, RawHyperlaneMessage, SequenceAwareIndexer, TxCostEstimate, - TxOutcome, H256, H512, U256, + Indexed, Indexer, LogMeta, Mailbox, RawHyperlaneMessage, ReorgPeriod, SequenceAwareIndexer, + TxCostEstimate, TxOutcome, H256, H512, U256, }; use std::{ collections::HashMap, fmt::{Debug, Formatter}, - num::NonZeroU64, ops::RangeInclusive, }; use tracing::{instrument, warn}; @@ -74,9 +73,9 @@ impl Debug for FuelMailbox { impl Mailbox for FuelMailbox { #[instrument(level = "debug", err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn count(&self, lag: Option) -> ChainResult { + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { assert!( - lag.is_none(), + reorg_period.is_none(), "Fuel does not support querying point-in-time" ); self.contract diff --git a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs index 952599c42..5453360e0 100644 --- a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs @@ -12,8 +12,8 @@ use hyperlane_core::{ ChainCommunicationError::ContractError, ChainResult, Checkpoint, ContractLocator, Decode as _, Encode as _, FixedPointNumber, HyperlaneAbi, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Indexed, Indexer, KnownHyperlaneDomain, - LogMeta, Mailbox, MerkleTreeHook, SequenceAwareIndexer, TxCostEstimate, TxOutcome, H256, H512, - U256, + LogMeta, Mailbox, MerkleTreeHook, ReorgPeriod, SequenceAwareIndexer, TxCostEstimate, TxOutcome, + H256, H512, U256, }; use hyperlane_sealevel_interchain_security_module_interface::{ InterchainSecurityModuleInstruction, VerifyInstruction, @@ -416,8 +416,8 @@ impl std::fmt::Debug for SealevelMailbox { #[async_trait] impl Mailbox for SealevelMailbox { #[instrument(err, ret, skip(self))] - async fn count(&self, _maybe_lag: Option) -> ChainResult { - ::count(self, _maybe_lag).await + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { + ::count(self, reorg_period).await } #[instrument(err, ret, skip(self))] @@ -755,7 +755,7 @@ impl SequenceAwareIndexer for SealevelMailboxIndexer { async fn latest_sequence_count_and_tip(&self) -> ChainResult<(Option, u32)> { let tip = Indexer::::get_finalized_block_number(self).await?; // TODO: need to make sure the call and tip are at the same height? - let count = Mailbox::count(&self.mailbox, None).await?; + let count = Mailbox::count(&self.mailbox, &ReorgPeriod::None).await?; Ok((Some(count), tip)) } } diff --git a/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs b/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs index 947f7e70a..a0813bfba 100644 --- a/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs +++ b/rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs @@ -1,11 +1,11 @@ -use std::{num::NonZeroU64, ops::RangeInclusive}; +use std::ops::RangeInclusive; use async_trait::async_trait; use derive_new::new; use hyperlane_core::{ accumulator::incremental::IncrementalMerkle, ChainCommunicationError, ChainResult, Checkpoint, HyperlaneChain, HyperlaneMessage, Indexed, Indexer, LogMeta, MerkleTreeHook, - MerkleTreeInsertion, SequenceAwareIndexer, + MerkleTreeInsertion, ReorgPeriod, SequenceAwareIndexer, }; use hyperlane_sealevel_mailbox::accounts::OutboxAccount; use tracing::instrument; @@ -16,9 +16,9 @@ use crate::{SealevelMailbox, SealevelMailboxIndexer}; impl MerkleTreeHook for SealevelMailbox { #[instrument(err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn tree(&self, lag: Option) -> ChainResult { + async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult { assert!( - lag.is_none(), + reorg_period.is_none(), "Sealevel does not support querying point-in-time" ); @@ -35,13 +35,13 @@ impl MerkleTreeHook for SealevelMailbox { #[instrument(err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn latest_checkpoint(&self, lag: Option) -> ChainResult { + async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult { assert!( - lag.is_none(), + reorg_period.is_none(), "Sealevel does not support querying point-in-time" ); - let tree = self.tree(lag).await?; + let tree = self.tree(reorg_period).await?; let root = tree.root(); let count: u32 = tree @@ -64,8 +64,8 @@ impl MerkleTreeHook for SealevelMailbox { #[instrument(err, ret, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn count(&self, _maybe_lag: Option) -> ChainResult { - let tree = self.tree(_maybe_lag).await?; + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { + let tree = self.tree(reorg_period).await?; tree.count() .try_into() diff --git a/rust/main/hyperlane-base/src/settings/chains.rs b/rust/main/hyperlane-base/src/settings/chains.rs index 8dcb2b9c5..0e08b2d15 100644 --- a/rust/main/hyperlane-base/src/settings/chains.rs +++ b/rust/main/hyperlane-base/src/settings/chains.rs @@ -10,13 +10,13 @@ use hyperlane_core::{ config::OperationBatchConfig, AggregationIsm, CcipReadIsm, ContractLocator, HyperlaneAbi, HyperlaneDomain, HyperlaneDomainProtocol, HyperlaneMessage, HyperlaneProvider, IndexMode, InterchainGasPaymaster, InterchainGasPayment, InterchainSecurityModule, Mailbox, - MerkleTreeHook, MerkleTreeInsertion, MultisigIsm, RoutingIsm, SequenceAwareIndexer, - ValidatorAnnounce, H256, + MerkleTreeHook, MerkleTreeInsertion, MultisigIsm, ReorgPeriod, RoutingIsm, + SequenceAwareIndexer, ValidatorAnnounce, H256, }; use hyperlane_cosmos as h_cosmos; use hyperlane_ethereum::{ self as h_eth, BuildableWithProvider, EthereumInterchainGasPaymasterAbi, EthereumMailboxAbi, - EthereumValidatorAnnounceAbi, + EthereumReorgPeriod, EthereumValidatorAnnounceAbi, }; use hyperlane_fuel as h_fuel; use hyperlane_sealevel as h_sealevel; @@ -45,7 +45,7 @@ pub struct ChainConf { /// Signer configuration for this chain pub signer: Option, /// The reorg period of the chain, i.e. the number of blocks until finality - pub reorg_period: u32, + pub reorg_period: ReorgPeriod, /// Addresses of contracts on the chain pub addresses: CoreContractAddresses, /// The chain connection details @@ -272,13 +272,13 @@ impl ChainConf { match &self.connection { ChainConnectionConf::Ethereum(conf) => { + let reorg_period = + EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?; self.build_ethereum( conf, &locator, metrics, - h_eth::SequenceIndexerBuilder { - reorg_period: self.reorg_period, - }, + h_eth::SequenceIndexerBuilder { reorg_period }, ) .await } @@ -289,11 +289,12 @@ impl ChainConf { } ChainConnectionConf::Cosmos(conf) => { let signer = self.cosmos_signer().await.context(ctx)?; + let reorg_period = self.reorg_period.as_blocks().context(ctx)?; let indexer = Box::new(h_cosmos::CosmosMailboxDispatchIndexer::new( conf.clone(), locator, signer, - self.reorg_period, + reorg_period, )?); Ok(indexer as Box>) } @@ -311,13 +312,13 @@ impl ChainConf { match &self.connection { ChainConnectionConf::Ethereum(conf) => { + let reorg_period = + EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?; self.build_ethereum( conf, &locator, metrics, - h_eth::DeliveryIndexerBuilder { - reorg_period: self.reorg_period, - }, + h_eth::DeliveryIndexerBuilder { reorg_period }, ) .await } @@ -328,11 +329,12 @@ impl ChainConf { } ChainConnectionConf::Cosmos(conf) => { let signer = self.cosmos_signer().await.context(ctx)?; + let reorg_period = self.reorg_period.as_blocks().context(ctx)?; let indexer = Box::new(h_cosmos::CosmosMailboxDeliveryIndexer::new( conf.clone(), locator, signer, - self.reorg_period, + reorg_period, )?); Ok(indexer as Box>) } @@ -389,13 +391,15 @@ impl ChainConf { match &self.connection { ChainConnectionConf::Ethereum(conf) => { + let reorg_period = + EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?; self.build_ethereum( conf, &locator, metrics, h_eth::InterchainGasPaymasterIndexerBuilder { mailbox_address: self.addresses.mailbox.into(), - reorg_period: self.reorg_period, + reorg_period, }, ) .await @@ -408,10 +412,11 @@ impl ChainConf { Ok(indexer as Box>) } ChainConnectionConf::Cosmos(conf) => { + let reorg_period = self.reorg_period.as_blocks().context(ctx)?; let indexer = Box::new(h_cosmos::CosmosInterchainGasPaymasterIndexer::new( conf.clone(), locator, - self.reorg_period, + reorg_period, )?); Ok(indexer as Box>) } @@ -429,13 +434,13 @@ impl ChainConf { match &self.connection { ChainConnectionConf::Ethereum(conf) => { + let reorg_period = + EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?; self.build_ethereum( conf, &locator, metrics, - h_eth::MerkleTreeHookIndexerBuilder { - reorg_period: self.reorg_period, - }, + h_eth::MerkleTreeHookIndexerBuilder { reorg_period }, ) .await } @@ -450,12 +455,13 @@ impl ChainConf { } ChainConnectionConf::Cosmos(conf) => { let signer = self.cosmos_signer().await.context(ctx)?; + let reorg_period = self.reorg_period.as_blocks().context(ctx)?; let indexer = Box::new(h_cosmos::CosmosMerkleTreeHookIndexer::new( conf.clone(), locator, // TODO: remove signer requirement entirely signer, - self.reorg_period, + reorg_period, )?); Ok(indexer as Box>) } diff --git a/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs b/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs index 38274dafa..3434a7168 100644 --- a/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs +++ b/rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs @@ -180,7 +180,7 @@ mod test { use std::panic::AssertUnwindSafe; use futures_util::FutureExt; - use hyperlane_core::{ReorgEvent, H256}; + use hyperlane_core::{ReorgEvent, ReorgPeriod, H256}; #[tokio::test] async fn test_build_and_validate() { @@ -209,7 +209,7 @@ mod test { .unwrap(); let dummy_checkpoint_index = 56; let unix_timestamp = 1620000000; - let reorg_period = 5; + let reorg_period = ReorgPeriod::from_blocks(5); let dummy_reorg_event = ReorgEvent { local_merkle_root: dummy_local_merkle_root, canonical_merkle_root: dummy_canonical_merkle_root, @@ -237,7 +237,9 @@ mod test { canonical_merkle_root: 0xb437b888332ef12f7260c7f679aad3c96b91ab81c2dc7242f8b290f0b6bba92b, checkpoint_index: 56, unix_timestamp: 1620000000, - reorg_period: 5, + reorg_period: Blocks( + 5, + ), }. Please resolve the reorg to continue."# ); } else { diff --git a/rust/main/hyperlane-base/src/settings/parser/mod.rs b/rust/main/hyperlane-base/src/settings/parser/mod.rs index 65a8c845a..7c608427b 100644 --- a/rust/main/hyperlane-base/src/settings/parser/mod.rs +++ b/rust/main/hyperlane-base/src/settings/parser/mod.rs @@ -19,7 +19,7 @@ use url::Url; use h_cosmos::RawCosmosAmount; use hyperlane_core::{ cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol, - HyperlaneDomainTechnicalStack, IndexMode, + HyperlaneDomainTechnicalStack, IndexMode, ReorgPeriod, }; use crate::settings::{ @@ -136,8 +136,8 @@ fn parse_chain( .chain(&mut err) .get_opt_key("blocks") .get_key("reorgPeriod") - .parse_u32() - .unwrap_or(1); + .parse_value("Invalid reorgPeriod") + .unwrap_or(ReorgPeriod::from_blocks(1)); let rpcs = parse_base_and_override_urls(&chain, "rpcUrls", "customRpcUrls", "http", &mut err); diff --git a/rust/main/hyperlane-core/src/chain.rs b/rust/main/hyperlane-core/src/chain.rs index bd73ff613..a4cfaac77 100644 --- a/rust/main/hyperlane-core/src/chain.rs +++ b/rust/main/hyperlane-core/src/chain.rs @@ -3,16 +3,20 @@ use std::{ fmt::{Debug, Formatter}, hash::{Hash, Hasher}, + num::NonZeroU32, }; use derive_new::new; use num_derive::FromPrimitive; use num_traits::FromPrimitive; -use serde::Serialize; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + #[cfg(feature = "strum")] use strum::{EnumIter, EnumString, IntoStaticStr}; -use crate::{utils::many_to_one, HyperlaneProtocolError, IndexMode, H160, H256}; +use crate::{ + utils::many_to_one, ChainCommunicationError, HyperlaneProtocolError, IndexMode, H160, H256, +}; #[derive(Debug, Clone)] pub struct Address(pub bytes::Bytes); @@ -39,6 +43,80 @@ impl<'a> std::fmt::Display for ContractLocator<'a> { } } +#[derive(Default, Debug, Clone, PartialEq)] +pub enum ReorgPeriod { + #[default] + None, + Blocks(NonZeroU32), + Tag(String), +} + +impl ReorgPeriod { + pub fn from_blocks(blocks: u32) -> Self { + NonZeroU32::try_from(blocks) + .map(ReorgPeriod::Blocks) + .unwrap_or(ReorgPeriod::None) + } + + pub fn as_blocks(&self) -> Result { + match self { + ReorgPeriod::None => Ok(0), + ReorgPeriod::Blocks(blocks) => Ok(blocks.get()), + ReorgPeriod::Tag(_) => Err(ChainCommunicationError::InvalidReorgPeriod(self.clone())), + } + } + + pub fn is_none(&self) -> bool { + matches!(self, ReorgPeriod::None) + } +} + +impl Serialize for ReorgPeriod { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + ReorgPeriod::None => serializer.serialize_u32(0), + ReorgPeriod::Blocks(blocks) => serializer.serialize_u32(blocks.get()), + ReorgPeriod::Tag(tag) => serializer.serialize_str(tag), + } + } +} + +impl<'de> Deserialize<'de> for ReorgPeriod { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use serde::de; + + struct ReorgPeriodVisitor; + + impl<'de> de::Visitor<'de> for ReorgPeriodVisitor { + type Value = ReorgPeriod; + + fn expecting(&self, f: &mut Formatter) -> std::fmt::Result { + f.write_str("reorgPeriod as a number or string") + } + + fn visit_u64(self, v: u64) -> Result { + let v = v.try_into().map_err(de::Error::custom)?; + Ok(ReorgPeriod::from_blocks(v)) + } + + fn visit_str(self, v: &str) -> Result { + match v.parse::() { + Ok(v) => self.visit_u32(v), + Err(_) => Ok(ReorgPeriod::Tag(v.to_string())), + } + } + } + + deserializer.deserialize_any(ReorgPeriodVisitor) + } +} + /// All domains supported by Hyperlane. #[derive(FromPrimitive, PartialEq, Eq, Debug, Clone, Copy, Hash, Serialize)] #[cfg_attr( @@ -505,9 +583,9 @@ impl HyperlaneDomain { #[cfg(test)] #[cfg(feature = "strum")] mod tests { - use std::str::FromStr; + use std::{num::NonZeroU32, str::FromStr}; - use crate::KnownHyperlaneDomain; + use crate::{KnownHyperlaneDomain, ReorgPeriod}; #[test] fn domain_strings() { @@ -560,4 +638,32 @@ mod tests { ); assert!("foo".parse::().is_err()); } + + #[test] + fn parse_reorg_period() { + assert_eq!( + serde_json::from_value::(0.into()).unwrap(), + ReorgPeriod::None + ); + + assert_eq!( + serde_json::from_value::("0".into()).unwrap(), + ReorgPeriod::None + ); + + assert_eq!( + serde_json::from_value::(12.into()).unwrap(), + ReorgPeriod::Blocks(NonZeroU32::new(12).unwrap()) + ); + + assert_eq!( + serde_json::from_value::("12".into()).unwrap(), + ReorgPeriod::Blocks(NonZeroU32::new(12).unwrap()) + ); + + assert_eq!( + serde_json::from_value::("finalized".into()).unwrap(), + ReorgPeriod::Tag("finalized".into()) + ); + } } diff --git a/rust/main/hyperlane-core/src/error.rs b/rust/main/hyperlane-core/src/error.rs index 56bbf4a82..fe1385c0e 100644 --- a/rust/main/hyperlane-core/src/error.rs +++ b/rust/main/hyperlane-core/src/error.rs @@ -10,8 +10,10 @@ use crate::config::StrOrIntParseError; use crate::rpc_clients::RpcClientError; use std::string::FromUtf8Error; -use crate::HyperlaneProviderError; -use crate::{Error as PrimitiveTypeError, HyperlaneSignerError, H256, U256}; +use crate::{ + Error as PrimitiveTypeError, HyperlaneProviderError, HyperlaneSignerError, ReorgPeriod, H256, + U256, +}; /// The result of interacting with a chain. pub type ChainResult = Result; @@ -157,6 +159,9 @@ pub enum ChainCommunicationError { /// Hyperlane signer error #[error("{0}")] HyperlaneSignerError(#[from] HyperlaneSignerError), + /// Invalid reorg period + #[error("Invalid reorg period: {0:?}")] + InvalidReorgPeriod(ReorgPeriod), } impl ChainCommunicationError { diff --git a/rust/main/hyperlane-core/src/traits/mailbox.rs b/rust/main/hyperlane-core/src/traits/mailbox.rs index d5e9081b6..83646e659 100644 --- a/rust/main/hyperlane-core/src/traits/mailbox.rs +++ b/rust/main/hyperlane-core/src/traits/mailbox.rs @@ -1,12 +1,11 @@ use std::fmt::Debug; -use std::num::NonZeroU64; use async_trait::async_trait; use derive_new::new; use crate::{ traits::TxOutcome, utils::domain_hash, BatchItem, ChainCommunicationError, ChainResult, - HyperlaneContract, HyperlaneMessage, QueueOperation, TxCostEstimate, H256, U256, + HyperlaneContract, HyperlaneMessage, QueueOperation, ReorgPeriod, TxCostEstimate, H256, U256, }; /// Interface for the Mailbox chain contract. Allows abstraction over different @@ -20,9 +19,9 @@ pub trait Mailbox: HyperlaneContract + Send + Sync + Debug { /// Gets the current leaf count of the merkle tree /// - /// - `lag` is how far behind the current block to query, if not specified + /// - `reorg_period` is how far behind the current block to query, if not specified /// it will query at the latest block. - async fn count(&self, lag: Option) -> ChainResult; + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult; /// Fetch the status of a message async fn delivered(&self, id: H256) -> ChainResult; diff --git a/rust/main/hyperlane-core/src/traits/merkle_tree_hook.rs b/rust/main/hyperlane-core/src/traits/merkle_tree_hook.rs index 35f3fa4ef..183ca7383 100644 --- a/rust/main/hyperlane-core/src/traits/merkle_tree_hook.rs +++ b/rust/main/hyperlane-core/src/traits/merkle_tree_hook.rs @@ -1,11 +1,11 @@ use std::fmt::Debug; -use std::num::NonZeroU64; use async_trait::async_trait; use auto_impl::auto_impl; use crate::{ accumulator::incremental::IncrementalMerkle, ChainResult, Checkpoint, HyperlaneContract, + ReorgPeriod, }; /// Interface for the MerkleTreeHook chain contract. Allows abstraction over different @@ -15,19 +15,19 @@ use crate::{ pub trait MerkleTreeHook: HyperlaneContract + Send + Sync + Debug { /// Return the incremental merkle tree in storage /// - /// - `lag` is how far behind the current block to query, if not specified + /// - `reorg_period` is how far behind the current block to query, if not specified /// it will query at the latest block. - async fn tree(&self, lag: Option) -> ChainResult; + async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult; /// Gets the current leaf count of the merkle tree /// - /// - `lag` is how far behind the current block to query, if not specified + /// - `reorg_period` is how far behind the current block to query, if not specified /// it will query at the latest block. - async fn count(&self, lag: Option) -> ChainResult; + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult; /// Get the latest checkpoint. /// - /// - `lag` is how far behind the current block to query, if not specified + /// - `reorg_period` is how far behind the current block to query, if not specified /// it will query at the latest block. - async fn latest_checkpoint(&self, lag: Option) -> ChainResult; + async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult; } diff --git a/rust/main/hyperlane-core/src/types/reorg.rs b/rust/main/hyperlane-core/src/types/reorg.rs index 00a8dedc1..eb41844c0 100644 --- a/rust/main/hyperlane-core/src/types/reorg.rs +++ b/rust/main/hyperlane-core/src/types/reorg.rs @@ -1,7 +1,7 @@ use derive_new::new; use serde::{Deserialize, Serialize}; -use crate::H256; +use crate::{ReorgPeriod, H256}; /// Details about a detected chain reorg, from an agent's perspective #[derive(Debug, Clone, Serialize, Deserialize, new)] @@ -15,6 +15,6 @@ pub struct ReorgEvent { pub checkpoint_index: u32, /// the timestamp when the reorg was detected, in seconds since the Unix epoch pub unix_timestamp: u64, - /// the reorg period configured for the agent, in blocks - pub reorg_period: u64, + /// the reorg period configured for the agent + pub reorg_period: ReorgPeriod, } diff --git a/rust/main/hyperlane-test/src/mocks/mailbox.rs b/rust/main/hyperlane-test/src/mocks/mailbox.rs index dc09e1026..7333e2c8a 100644 --- a/rust/main/hyperlane-test/src/mocks/mailbox.rs +++ b/rust/main/hyperlane-test/src/mocks/mailbox.rs @@ -1,7 +1,5 @@ #![allow(non_snake_case)] -use std::num::NonZeroU64; - use async_trait::async_trait; use mockall::*; @@ -28,11 +26,11 @@ mock! { nonce: usize, ) -> ChainResult> {} - pub fn _tree(&self, maybe_lag: Option) -> ChainResult {} + pub fn _tree(&self, reorg_period: &ReorgPeriod) -> ChainResult {} - pub fn _count(&self, maybe_lag: Option) -> ChainResult {} + pub fn _count(&self, reorg_period: &ReorgPeriod) -> ChainResult {} - pub fn _latest_checkpoint(&self, maybe_lag: Option) -> ChainResult {} + pub fn _latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult {} pub fn _default_ism(&self) -> ChainResult {} pub fn _recipient_ism(&self, recipient: H256) -> ChainResult {} @@ -68,8 +66,8 @@ impl std::fmt::Debug for MockMailboxContract { #[async_trait] impl Mailbox for MockMailboxContract { - async fn count(&self, maybe_lag: Option) -> ChainResult { - self._count(maybe_lag) + async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult { + self._count(reorg_period) } async fn default_ism(&self) -> ChainResult { diff --git a/typescript/cli/src/config/chain.ts b/typescript/cli/src/config/chain.ts index 199e026c8..d3279a202 100644 --- a/typescript/cli/src/config/chain.ts +++ b/typescript/cli/src/config/chain.ts @@ -168,6 +168,11 @@ async function addBlockOrGasConfig(metadata: ChainMetadata): Promise { } async function addBlockConfig(metadata: ChainMetadata): Promise { + const parseReorgPeriod = (value: string) => { + const parsed = parseInt(value, 10); + return isNaN(parsed) ? value : parsed; + }; + const wantBlockConfig = await confirm({ message: 'Do you want to add block config for this chain', }); @@ -179,8 +184,10 @@ async function addBlockConfig(metadata: ChainMetadata): Promise { }); const blockReorgPeriod = await input({ message: - 'Enter no. of blocks before a transaction has a near-zero chance of reverting (0-500):', - validate: (value) => parseInt(value) >= 0 && parseInt(value) <= 500, + 'Enter no. of blocks before a transaction has a near-zero chance of reverting (0-500) or block tag:', + validate: (value) => + isNaN(parseInt(value)) || + (parseInt(value) >= 0 && parseInt(value) <= 500), }); const blockTimeEstimate = await input({ message: 'Enter the rough estimate of time per block in seconds (0-20):', @@ -188,7 +195,7 @@ async function addBlockConfig(metadata: ChainMetadata): Promise { }); metadata.blocks = { confirmations: parseInt(blockConfirmation, 10), - reorgPeriod: parseInt(blockReorgPeriod, 10), + reorgPeriod: parseReorgPeriod(blockReorgPeriod), estimateBlockTime: parseInt(blockTimeEstimate, 10), }; } diff --git a/typescript/infra/config/registry.ts b/typescript/infra/config/registry.ts index 51ac87729..4b72c9f5b 100644 --- a/typescript/infra/config/registry.ts +++ b/typescript/infra/config/registry.ts @@ -78,7 +78,7 @@ export function getDomainId(chainName: ChainName): number { return resolveDomainId(chain); } -export function getReorgPeriod(chainName: ChainName): number { +export function getReorgPeriod(chainName: ChainName): string | number { const chain = getChain(chainName); return resolveReorgPeriod(chain); } diff --git a/typescript/infra/src/config/agent/validator.ts b/typescript/infra/src/config/agent/validator.ts index 05293abfa..e18220017 100644 --- a/typescript/infra/src/config/agent/validator.ts +++ b/typescript/infra/src/config/agent/validator.ts @@ -26,8 +26,8 @@ export type ValidatorBaseChainConfigMap = ChainMap; export interface ValidatorBaseChainConfig { // How frequently to check for new checkpoints interval: number; - // The reorg_period in blocks; overrides chain metadata - reorgPeriod: number; + // The reorg_period in blocks or block tag; overrides chain metadata + reorgPeriod: string | number; // Individual validator agents validators: Array; } diff --git a/typescript/sdk/src/metadata/chainMetadata.test.ts b/typescript/sdk/src/metadata/chainMetadata.test.ts index 773eb9c03..65a980f83 100644 --- a/typescript/sdk/src/metadata/chainMetadata.test.ts +++ b/typescript/sdk/src/metadata/chainMetadata.test.ts @@ -62,6 +62,16 @@ describe('ChainMetadataSchema', () => { grpcUrls: [], }), ).to.eq(true); + + expect( + isValidChainMetadata({ + ...minimalSchema, + blocks: { + confirmations: 1, + reorgPeriod: 'finalized', + }, + }), + ).to.eq(true); }); it('Rejects invalid schemas', () => { diff --git a/typescript/sdk/src/metadata/chainMetadataTypes.ts b/typescript/sdk/src/metadata/chainMetadataTypes.ts index caf290ced..cf6c9bb54 100644 --- a/typescript/sdk/src/metadata/chainMetadataTypes.ts +++ b/typescript/sdk/src/metadata/chainMetadataTypes.ts @@ -125,9 +125,12 @@ export const ChainMetadataSchemaObject = z.object({ confirmations: ZUint.describe( 'Number of blocks to wait before considering a transaction confirmed.', ), - reorgPeriod: ZUint.optional().describe( - 'Number of blocks before a transaction has a near-zero chance of reverting.', - ), + reorgPeriod: z + .union([ZUint, z.string()]) + .optional() + .describe( + 'Number of blocks before a transaction has a near-zero chance of reverting or block tag.', + ), estimateBlockTime: z .number() .positive() @@ -371,7 +374,7 @@ export function getChainIdNumber(chainMetadata: ChainMetadata): number { else throw new Error('ChainId is not a number, chain may be of Cosmos type'); } -export function getReorgPeriod(chainMetadata: ChainMetadata): number { +export function getReorgPeriod(chainMetadata: ChainMetadata): string | number { if (chainMetadata.blocks?.reorgPeriod !== undefined) return chainMetadata.blocks.reorgPeriod; else throw new Error('Chain has no reorg period'); From 2cc51c1640db7757a08ecd16241a49efd17aff3c Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:07:19 +0100 Subject: [PATCH 174/224] chore: split cli e2e into separate job (#4733) ### Description chore: split cli e2e into separate job before: ![image](https://github.com/user-attachments/assets/bb19243f-fc38-478e-b94c-f39020756964) after: ![image](https://github.com/user-attachments/assets/6ebcb783-1d07-4350-8823-5cc5df7c5c65) ### Drive-by changes na ### Related issues `yarn-test` step sometimes taking even 15 mins nowadays, half of which is e2e tests ### Backward compatibility yes ### Testing ci --- .github/workflows/test.yml | 26 ++++++++++++++++++- typescript/cli/.mocharc-e2e.json | 8 ++++++ typescript/cli/.mocharc.json | 2 +- typescript/cli/package.json | 3 ++- .../scripts/{all-test.sh => run-e2e-test.sh} | 12 ++++----- 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 typescript/cli/.mocharc-e2e.json rename typescript/cli/scripts/{all-test.sh => run-e2e-test.sh} (71%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b37075002..bfbb3c8f6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -109,6 +109,30 @@ jobs: - name: Unit Tests run: yarn test:ci + cli-e2e: + runs-on: ubuntu-latest + needs: [yarn-install] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + submodules: recursive + fetch-depth: 0 + + - name: foundry-install + uses: foundry-rs/foundry-toolchain@v1 + + - name: yarn-build + uses: ./.github/actions/yarn-build-with-cache + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Checkout registry + uses: ./.github/actions/checkout-registry + + - name: CLI e2e tests + run: yarn --cwd typescript/cli test:e2e + agent-configs: runs-on: ubuntu-latest needs: [yarn-install] @@ -218,7 +242,7 @@ jobs: run: | if [[ -n "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)" ]]; then echo "rust_changes=true" >> $GITHUB_OUTPUT - echo "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)" + echo "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)" else echo "rust_changes=false" >> $GITHUB_OUTPUT fi diff --git a/typescript/cli/.mocharc-e2e.json b/typescript/cli/.mocharc-e2e.json new file mode 100644 index 000000000..ecabac62f --- /dev/null +++ b/typescript/cli/.mocharc-e2e.json @@ -0,0 +1,8 @@ +{ + "extensions": ["ts"], + "spec": ["src/**/*.e2e-test.ts"], + "node-option": [ + "experimental-specifier-resolution=node", + "loader=ts-node/esm" + ] +} diff --git a/typescript/cli/.mocharc.json b/typescript/cli/.mocharc.json index 17ba33e2f..2d7433a2f 100644 --- a/typescript/cli/.mocharc.json +++ b/typescript/cli/.mocharc.json @@ -1,6 +1,6 @@ { "extensions": ["ts"], - "spec": ["src/**/*.test.*", "src/**/*.e2e-test.ts"], + "spec": ["src/**/*.test.*"], "node-option": [ "experimental-specifier-resolution=node", "loader=ts-node/esm" diff --git a/typescript/cli/package.json b/typescript/cli/package.json index ee91e5fc8..a014c8bbc 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -47,7 +47,8 @@ "clean": "rm -rf ./dist", "lint": "eslint . --ext .ts", "prettier": "prettier --write ./src ./examples", - "test:ci": "./scripts/all-test.sh", + "test:ci": "yarn mocha --config .mocharc.json", + "test:e2e": "./scripts/run-e2e-test.sh", "version:update": "echo \"export const VERSION = '$npm_package_version';\" > src/version.ts" }, "files": [ diff --git a/typescript/cli/scripts/all-test.sh b/typescript/cli/scripts/run-e2e-test.sh similarity index 71% rename from typescript/cli/scripts/all-test.sh rename to typescript/cli/scripts/run-e2e-test.sh index f33060987..e398253b2 100755 --- a/typescript/cli/scripts/all-test.sh +++ b/typescript/cli/scripts/run-e2e-test.sh @@ -1,24 +1,24 @@ #!/usr/bin/env bash function cleanup() { - set +e + set +e pkill -f anvil rm -rf /tmp/anvil2 rm -rf /tmp/anvil3 rm -f ./test-configs/anvil/chains/anvil2/addresses.yaml rm -f ./test-configs/anvil/chains/anvil3/addresses.yaml - set -e + set -e } cleanup -echo "Starting anvil2 and anvil3 chain" +echo "Starting anvil2 and anvil3 chain for E2E tests" anvil --chain-id 31338 -p 8555 --state /tmp/anvil2/state --gas-price 1 > /dev/null & anvil --chain-id 31347 -p 8600 --state /tmp/anvil3/state --gas-price 1 > /dev/null & -echo "Running all tests" -yarn mocha --config .mocharc.json +echo "Running E2E tests" +yarn mocha --config .mocharc-e2e.json cleanup -echo "Done all tests" \ No newline at end of file +echo "Completed E2E tests" From 937392b61d3d00e915eaf92566f1df86fa372c05 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:49:55 +0100 Subject: [PATCH 175/224] chore(evm): optimize block number fetching (#4736) ### Description Fix for leftover [comment](https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4629#discussion_r1811084234) from https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4629 ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../chains/hyperlane-ethereum/src/config.rs | 22 ++++++++++++++++++- rust/main/chains/hyperlane-ethereum/src/tx.rs | 10 ++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/rust/main/chains/hyperlane-ethereum/src/config.rs b/rust/main/chains/hyperlane-ethereum/src/config.rs index 0e2a2a13a..e1375e790 100644 --- a/rust/main/chains/hyperlane-ethereum/src/config.rs +++ b/rust/main/chains/hyperlane-ethereum/src/config.rs @@ -1,5 +1,8 @@ +use ethers::providers::Middleware; use ethers_core::types::{BlockId, BlockNumber}; -use hyperlane_core::{config::OperationBatchConfig, ChainCommunicationError, ReorgPeriod, U256}; +use hyperlane_core::{ + config::OperationBatchConfig, ChainCommunicationError, ChainResult, ReorgPeriod, U256, +}; use url::Url; /// Ethereum RPC connection configuration @@ -84,3 +87,20 @@ impl TryFrom<&ReorgPeriod> for EthereumReorgPeriod { } } } + +impl EthereumReorgPeriod { + /// Converts the reorg period into a block id + pub async fn into_block_id( + &self, + provider: &M, + ) -> ChainResult { + let block_id = match self { + EthereumReorgPeriod::Blocks(_) => { + (crate::get_finalized_block_number(provider, self).await? as u64).into() + } + // no need to fetch the block number for the `tag` + EthereumReorgPeriod::Tag(tag) => *tag, + }; + Ok(block_id) + } +} diff --git a/rust/main/chains/hyperlane-ethereum/src/tx.rs b/rust/main/chains/hyperlane-ethereum/src/tx.rs index 2e774622a..05cc4da44 100644 --- a/rust/main/chains/hyperlane-ethereum/src/tx.rs +++ b/rust/main/chains/hyperlane-ethereum/src/tx.rs @@ -20,7 +20,7 @@ use hyperlane_core::{ }; use tracing::{debug, error, info, warn}; -use crate::{get_finalized_block_number, EthereumReorgPeriod, Middleware, TransactionOverrides}; +use crate::{EthereumReorgPeriod, Middleware, TransactionOverrides}; /// An amount of gas to add to the estimated gas pub const GAS_ESTIMATE_BUFFER: u32 = 75_000; @@ -227,10 +227,10 @@ where T: Detokenize, { if !reorg_period.is_none() { - let reorg_period = EthereumReorgPeriod::try_from(reorg_period)?; - let block = get_finalized_block_number(provider, &reorg_period).await? as u64; - - Ok(call.block(block)) + let block_id = EthereumReorgPeriod::try_from(reorg_period)? + .into_block_id(provider) + .await?; + Ok(call.block(block_id)) } else { Ok(call) } From 5fc442b97fdcde19ea4513ef01eab9b3d5463034 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:52:46 +0100 Subject: [PATCH 176/224] chore: add sleep log in `fetch_logs_with_cursor` (#4734) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/main/config/mainnet_config.json | 6 ++++-- .../hyperlane-base/src/contract_sync/mod.rs | 17 ++++++++++++----- .../hyperlane-base/src/settings/parser/mod.rs | 4 +++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index 2667590fe..dc0551f9d 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -784,7 +784,8 @@ "gasCurrencyCoinGeckoId": "ethereum", "index": { "from": 1, - "mode": "sequence" + "mode": "sequence", + "chunk": 100 }, "interchainGasPaymaster": "ABb3i11z7wKoGCfeRQNQbVYWjAm7jG7HzZnDLV4RKRbK", "mailbox": "EitxJuv2iBjsg2d7jVy2LDC1e2zBrx4GB5Y9h2Ko3A9Y", @@ -2804,7 +2805,8 @@ "gasCurrencyCoinGeckoId": "solana", "index": { "from": 1, - "mode": "sequence" + "mode": "sequence", + "chunk": 100 }, "interchainGasPaymaster": "JAvHW21tYXE9dtdG83DReqU2b4LUexFuCbtJT5tF8X6M", "mailbox": "E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi", diff --git a/rust/main/hyperlane-base/src/contract_sync/mod.rs b/rust/main/hyperlane-base/src/contract_sync/mod.rs index 5105a1ade..8e6f8278f 100644 --- a/rust/main/hyperlane-base/src/contract_sync/mod.rs +++ b/rust/main/hyperlane-base/src/contract_sync/mod.rs @@ -170,7 +170,7 @@ where Ok(logs) => logs, Err(err) => { warn!(?err, ?range, "Error fetching logs in range"); - break SLEEP_DURATION; + break Some(SLEEP_DURATION); } }; @@ -196,13 +196,20 @@ where // Update cursor if let Err(err) = cursor.update(logs, range).await { warn!(?err, "Error updating cursor"); - break SLEEP_DURATION; + break Some(SLEEP_DURATION); }; - break Default::default(); + break None; }, - CursorAction::Sleep(duration) => duration, + CursorAction::Sleep(duration) => Some(duration), }; - sleep(sleep_duration).await + if let Some(sleep_duration) = sleep_duration { + debug!( + cursor = ?cursor, + ?sleep_duration, + "Cursor can't make progress, sleeping", + ); + sleep(sleep_duration).await + } } async fn dedupe_and_store_logs( diff --git a/rust/main/hyperlane-base/src/settings/parser/mod.rs b/rust/main/hyperlane-base/src/settings/parser/mod.rs index 7c608427b..d176ad857 100644 --- a/rust/main/hyperlane-base/src/settings/parser/mod.rs +++ b/rust/main/hyperlane-base/src/settings/parser/mod.rs @@ -34,6 +34,8 @@ pub use self::json_value_parser::ValueParser; mod connection_parser; mod json_value_parser; +const DEFAULT_CHUNK_SIZE: u32 = 1999; + /// The base agent config #[derive(Debug, Deserialize)] #[serde(transparent)] @@ -152,7 +154,7 @@ fn parse_chain( .get_opt_key("index") .get_opt_key("chunk") .parse_u32() - .unwrap_or(1999); + .unwrap_or(DEFAULT_CHUNK_SIZE); let mode = chain .chain(&mut err) .get_opt_key("index") From d41aa6928553788df395f2880043e7ff28cede77 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:20:17 +0100 Subject: [PATCH 177/224] feat: add block tag enum for validating reorgPeriod (#4739) ### Description - feat: add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod - cli will check that reorgPeriod is either a number or one of the appropriate tags, but the underlying schema is still left loose to be forwards-compatible - exporting the enum will also let us use this in unit tests on the registry side ### Drive-by changes na ### Related issues na ### Backward compatibility ye ### Testing ci --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/quiet-cooks-join.md | 6 ++++++ typescript/cli/src/config/chain.ts | 21 +++++++++++++------ typescript/sdk/src/index.ts | 1 + .../sdk/src/metadata/chainMetadata.test.ts | 8 +++++-- .../sdk/src/metadata/chainMetadataTypes.ts | 8 +++++++ 5 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 .changeset/quiet-cooks-join.md diff --git a/.changeset/quiet-cooks-join.md b/.changeset/quiet-cooks-join.md new file mode 100644 index 000000000..a5f39f2ab --- /dev/null +++ b/.changeset/quiet-cooks-join.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod diff --git a/typescript/cli/src/config/chain.ts b/typescript/cli/src/config/chain.ts index d3279a202..e710b6cf0 100644 --- a/typescript/cli/src/config/chain.ts +++ b/typescript/cli/src/config/chain.ts @@ -5,6 +5,7 @@ import { stringify as yamlStringify } from 'yaml'; import { ChainMetadata, ChainMetadataSchema, + EthJsonRpcBlockParameterTag, ExplorerFamily, ZChainName, } from '@hyperlane-xyz/sdk'; @@ -168,9 +169,11 @@ async function addBlockOrGasConfig(metadata: ChainMetadata): Promise { } async function addBlockConfig(metadata: ChainMetadata): Promise { - const parseReorgPeriod = (value: string) => { + const parseReorgPeriod = ( + value: string, + ): number | EthJsonRpcBlockParameterTag => { const parsed = parseInt(value, 10); - return isNaN(parsed) ? value : parsed; + return isNaN(parsed) ? (value as EthJsonRpcBlockParameterTag) : parsed; }; const wantBlockConfig = await confirm({ @@ -184,10 +187,16 @@ async function addBlockConfig(metadata: ChainMetadata): Promise { }); const blockReorgPeriod = await input({ message: - 'Enter no. of blocks before a transaction has a near-zero chance of reverting (0-500) or block tag:', - validate: (value) => - isNaN(parseInt(value)) || - (parseInt(value) >= 0 && parseInt(value) <= 500), + 'Enter no. of blocks before a transaction has a near-zero chance of reverting (0-500) or block tag (earliest, latest, safe, finalized, pending):', + validate: (value) => { + const parsedInt = parseInt(value, 10); + return ( + Object.values(EthJsonRpcBlockParameterTag).includes( + value as EthJsonRpcBlockParameterTag, + ) || + (!isNaN(parsedInt) && parsedInt >= 0 && parsedInt <= 500) + ); + }, }); const blockTimeEstimate = await input({ message: 'Enter the rough estimate of time per block in seconds (0-20):', diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index 415a11d26..e9bd31bb4 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -196,6 +196,7 @@ export { export { BlockExplorer, BlockExplorerSchema, + EthJsonRpcBlockParameterTag, ChainMetadata, ChainMetadataSchema, ChainMetadataSchemaObject, diff --git a/typescript/sdk/src/metadata/chainMetadata.test.ts b/typescript/sdk/src/metadata/chainMetadata.test.ts index 65a980f83..f38a59e46 100644 --- a/typescript/sdk/src/metadata/chainMetadata.test.ts +++ b/typescript/sdk/src/metadata/chainMetadata.test.ts @@ -2,7 +2,11 @@ import { expect } from 'chai'; import { ProtocolType } from '@hyperlane-xyz/utils'; -import { ChainMetadata, isValidChainMetadata } from './chainMetadataTypes.js'; +import { + ChainMetadata, + EthJsonRpcBlockParameterTag, + isValidChainMetadata, +} from './chainMetadataTypes.js'; const minimalSchema: ChainMetadata = { chainId: 5, @@ -68,7 +72,7 @@ describe('ChainMetadataSchema', () => { ...minimalSchema, blocks: { confirmations: 1, - reorgPeriod: 'finalized', + reorgPeriod: EthJsonRpcBlockParameterTag.Finalized, }, }), ).to.eq(true); diff --git a/typescript/sdk/src/metadata/chainMetadataTypes.ts b/typescript/sdk/src/metadata/chainMetadataTypes.ts index cf6c9bb54..bf41cd4ac 100644 --- a/typescript/sdk/src/metadata/chainMetadataTypes.ts +++ b/typescript/sdk/src/metadata/chainMetadataTypes.ts @@ -10,6 +10,14 @@ import { ChainMap } from '../types.js'; import { ZChainName, ZNzUint, ZUint } from './customZodTypes.js'; +export enum EthJsonRpcBlockParameterTag { + Earliest = 'earliest', + Latest = 'latest', + Safe = 'safe', + Finalized = 'finalized', + Pending = 'pending', +} + export enum ExplorerFamily { Etherscan = 'etherscan', Blockscout = 'blockscout', From 7f3e0669d284ad7d6826443573abd4a23f6c423f Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:51:05 +0100 Subject: [PATCH 178/224] feat: add stride to relayed chains (#4716) ### Description - feat: add stride to relayer - feat: add stride to scraper ### Drive-by changes - fix filtering non-evm addresses in appFromAddressesMapHelper - fallback to manual `yarn install` in `yarn-build-with-cache` action - fix bug in app governor to make inevm env-test pass ### Related issues na ### Backward compatibility yes ### Testing manual --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/tough-bats-yell.md | 5 + .../actions/yarn-build-with-cache/action.yml | 16 +- .registryrc | 2 +- .../m20230309_000001_create_table_domain.rs | 8 + rust/main/config/mainnet_config.json | 206 ++++++++++++------ .../config/environments/mainnet3/agent.ts | 9 +- .../config/environments/mainnet3/funding.ts | 2 + .../environments/mainnet3/gasPrices.json | 4 + .../mainnet3/supportedChainNames.ts | 1 + .../environments/mainnet3/tokenPrices.json | 1 + .../infra/src/govern/HyperlaneAppGovernor.ts | 24 +- typescript/sdk/src/contracts/contracts.ts | 32 +-- 12 files changed, 204 insertions(+), 106 deletions(-) create mode 100644 .changeset/tough-bats-yell.md diff --git a/.changeset/tough-bats-yell.md b/.changeset/tough-bats-yell.md new file mode 100644 index 000000000..71343609b --- /dev/null +++ b/.changeset/tough-bats-yell.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Fix filtering non-evm addresses in appFromAddressesMapHelper diff --git a/.github/actions/yarn-build-with-cache/action.yml b/.github/actions/yarn-build-with-cache/action.yml index 7ffad99a0..2aec33acc 100644 --- a/.github/actions/yarn-build-with-cache/action.yml +++ b/.github/actions/yarn-build-with-cache/action.yml @@ -11,12 +11,26 @@ runs: steps: - name: Cache uses: buildjet/cache@v4 + id: cache with: path: | **/node_modules .yarn key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }} - fail-on-cache-miss: true + + # Typically, the cache will be hit, but if there's a network error when + # restoring the cache, let's run the install step ourselves. + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + shell: bash + run: | + yarn install + CHANGES=$(git status -s --ignore-submodules) + if [[ ! -z $CHANGES ]]; then + echo "Changes found: $CHANGES" + git diff + exit 1 + fi - name: Build shell: bash diff --git a/.registryrc b/.registryrc index 44edec0c4..862c96776 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -8583d0841615313c8c880e765eba760378e061cd +dee58183e51f4eb43e84dbac0e595a4b389dbe80 diff --git a/rust/main/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs b/rust/main/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs index 80dcfc622..3a89e313d 100644 --- a/rust/main/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs +++ b/rust/main/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs @@ -438,6 +438,14 @@ const DOMAINS: &[RawDomain] = &[ is_test_net: false, is_deprecated: false, }, + RawDomain { + name: "stride", + token: "STRD", + domain: 745, + chain_id: 745, + is_test_net: false, + is_deprecated: false, + }, RawDomain { name: "cosmostest99990", token: "OSMO", diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index dc0551f9d..a562cd84e 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -34,7 +34,7 @@ "interchainAccountIsm": "0xd766e7C7517f2d0D92754b2fe4aE7AdEf7bDEC3e", "interchainAccountRouter": "0x25C87e735021F72d8728438C2130b02E3141f2cb", "interchainGasPaymaster": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA", - "interchainSecurityModule": "0x565C280Cdb56095Cf6BF23b5fF140180208CBa9e", + "interchainSecurityModule": "0x4e1d2cdB48A2C2912b11801Eb1F1d5007474cA43", "isTestnet": false, "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x811808Dd29ba8B0FC6C0ec0b5537035E59745162", @@ -100,7 +100,7 @@ "interchainAccountIsm": "0x2A7574358Ec53522CE2452887661AB4c86F7d400", "interchainAccountRouter": "0x91874Dbed74925dFe6059B90385EEb90DdE0B2E6", "interchainGasPaymaster": "0x3b6044acd6767f017e99318AA6Ef93b7B06A5a22", - "interchainSecurityModule": "0x3d0BE14dFbB1Eb736303260c1724B6ea270c8Dc4", + "interchainSecurityModule": "0x50d0b0E27B8B93119618f053A623886116dd3b6d", "mailbox": "0x979Ca5202784112f4738403dBec5D0F3B9daabB9", "merkleTreeHook": "0x748040afB89B8FdBb992799808215419d36A0930", "name": "arbitrum", @@ -172,7 +172,7 @@ "interchainAccountIsm": "0x27a3233c05C1Df7c163123301D14bE9349E3Cb48", "interchainAccountRouter": "0xa82a0227e6d6db53AF4B264A852bfF91C6504a51", "interchainGasPaymaster": "0x95519ba800BBd0d34eeAE026fEc620AD978176C0", - "interchainSecurityModule": "0x6723A49c12FE37ccBD08512dd586C8471743676f", + "interchainSecurityModule": "0xbc803Da34A88E5f6B50dfc0CC9D924d9865c91C5", "mailbox": "0xFf06aFcaABaDDd1fb08371f9ccA15D73D51FeBD6", "merkleTreeHook": "0x84eea61D679F42D92145fA052C89900CBAccE95A", "name": "avalanche", @@ -245,7 +245,7 @@ "interchainAccountIsm": "0x223F7D3f27E6272266AE4B5B91Fd5C7A2d798cD8", "interchainAccountRouter": "0x4767D22117bBeeb295413000B620B93FD8522d53", "interchainGasPaymaster": "0xc3F23848Ed2e04C0c6d41bd7804fa8f89F940B94", - "interchainSecurityModule": "0xaeEf8f7D049C03181E0B5f2746CA2Db4d25C0B82", + "interchainSecurityModule": "0xB7fcb4665ace2B0d36fd92D26b4a8B516c0bFe5F", "mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", "merkleTreeHook": "0x19dc38aeae620380430C200a6E990D5Af5480117", "name": "base", @@ -316,7 +316,7 @@ "interchainAccountIsm": "0xe93f2f409ad8B5000431D234472973fe848dcBEC", "interchainAccountRouter": "0x2f4Eb04189e11Af642237Da62d163Ab714614498", "interchainGasPaymaster": "0xB3fCcD379ad66CED0c91028520C64226611A48c9", - "interchainSecurityModule": "0xbCe3469E8C270e04ea9ccd20Efdeed2b90c9d57C", + "interchainSecurityModule": "0xECa4a584E91867a72cd036DB7Db22Ad894a197B7", "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", "merkleTreeHook": "0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465", "name": "blast", @@ -384,7 +384,7 @@ "interchainAccountIsm": "0x451dF8AB0936D85526D816f0b4dCaDD934A034A4", "interchainAccountRouter": "0x5C02157068a52cEcfc98EDb6115DE6134EcB4764", "interchainGasPaymaster": "0x62B7592C1B6D1E43f4630B8e37f4377097840C05", - "interchainSecurityModule": "0x26eA240CB4cABd7B75A9F17E7f4e224170270Ee3", + "interchainSecurityModule": "0x93E3e6CA295803417212421785606B1F7dDeaD8f", "mailbox": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147", "merkleTreeHook": "0x781bE492F1232E66990d83a9D3AC3Ec26f56DAfB", "name": "bob", @@ -450,7 +450,7 @@ "interchainAccountIsm": "0x9e22945bE593946618383B108CC5bce09eBA4C26", "interchainAccountRouter": "0x32A07c1B7a7fe8D4A0e44B0181873aB9d64C16c1", "interchainGasPaymaster": "0x78E25e7f84416e69b9339B0A6336EB6EFfF6b451", - "interchainSecurityModule": "0x0A7cE15E3cc638abC3B5FfA7Fc8F3295Ae3595D1", + "interchainSecurityModule": "0xA0506B5b12770494740A4a7cc86C9A36Dc1Fc6Dc", "mailbox": "0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4", "merkleTreeHook": "0xFDb9Cd5f9daAA2E4474019405A328a88E7484f26", "name": "bsc", @@ -531,7 +531,7 @@ "interchainAccountIsm": "0xB732c83aeE29596E3163Da2260710eAB67Bc0B29", "interchainAccountRouter": "0x27a6cAe33378bB6A6663b382070427A01fc9cB37", "interchainGasPaymaster": "0x571f1435613381208477ac5d6974310d88AC7cB7", - "interchainSecurityModule": "0x33BC62504248F4cb43813532067ccAEd46a5e61C", + "interchainSecurityModule": "0xa6f4835940dbA46E295076D0CD0411349C33789f", "mailbox": "0x50da3B3907A08a24fe4999F4Dcf337E8dC7954bb", "merkleTreeHook": "0x04dB778f05854f26E67e0a66b740BBbE9070D366", "name": "celo", @@ -596,7 +596,7 @@ "interchainAccountIsm": "0x4Eb82Ee35b0a1c1d776E3a3B547f9A9bA6FCC9f2", "interchainAccountRouter": "0xEF9A332Ec1fD233Bf9344A58be56ff9E104B4f60", "interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503", - "interchainSecurityModule": "0xc1FF2bf7a4C315bE2a06941D236457EB02F93993", + "interchainSecurityModule": "0x05f6BAa16F1aCf7b19c4A09E019D856c10ab8355", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD", "name": "cheesechain", @@ -659,7 +659,7 @@ "from": 4842212 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xEfFaEddFf4FFd6F8a6D714bf149b114fD34E5Fd4", + "interchainSecurityModule": "0x9A746C4BC2bE7E657A3469f0a0DAA1dE517b8514", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "cyber", @@ -726,7 +726,7 @@ "from": 23783929 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xB5e6AA45E117f9fD2a3F8e78432fCAfdB833d316", + "interchainSecurityModule": "0x168E9C1481F50E66Cc5F5E24b04eBf7071629c4E", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "degenchain", @@ -839,7 +839,7 @@ "interchainAccountIsm": "0xCeafc098e5c3c7768b9229Be2FEC275862A81Abd", "interchainAccountRouter": "0xed9a722c543883FB7e07E78F3879762DE09eA7D5", "interchainGasPaymaster": "0xB30EAB08aa87138D57168D0e236850A530f49921", - "interchainSecurityModule": "0xC0737f1EA1d0aF287c2804090370b1715c593385", + "interchainSecurityModule": "0x094120BaC576aD7D88ec6893C9B220a0e64923E9", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xC831271c1fB212012811a91Dd43e5926C1020563", "name": "endurance", @@ -910,7 +910,7 @@ "interchainAccountIsm": "0x292C614ED53DaaDBf971521bc2C652d1ca51cB47", "interchainAccountRouter": "0x5E532F7B610618eE73C2B462978e94CB1F7995Ce", "interchainGasPaymaster": "0x9e6B1022bE9BBF5aFd152483DAD9b88911bC8611", - "interchainSecurityModule": "0xFc440a9c946Bf4840623E4adf49646089361584a", + "interchainSecurityModule": "0x23d160e4474Ce011829c71Bf1bCaA40F0b5612D5", "mailbox": "0xc005dc82818d67AF737725bD4bf75435d065D239", "merkleTreeHook": "0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA", "name": "ethereum", @@ -979,7 +979,7 @@ "interchainAccountIsm": "0x7C012DCA02C42cfA3Fd7Da3B0ED7234B52AE68eF", "interchainAccountRouter": "0xbed53B5C5BCE9433f25A2A702e6df13E22d84Ae9", "interchainGasPaymaster": "0x2Fca7f6eC3d4A0408900f2BB30004d4616eE985E", - "interchainSecurityModule": "0x2bed66bbfE45f1d73928179e72B73e5eCF7B9900", + "interchainSecurityModule": "0x8B497dff421844Bb0882E0C495d0851D4461675C", "mailbox": "0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3", "merkleTreeHook": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147", "name": "fraxtal", @@ -1047,7 +1047,7 @@ "interchainAccountIsm": "0x9629c28990F11c31735765A6FD59E1E1bC197DbD", "interchainAccountRouter": "0x2351FBe24C1212F253b7a300ff0cBCFd97952a19", "interchainGasPaymaster": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", - "interchainSecurityModule": "0x1E12bdb6a33442102FEF2ab766b93c863653B4bE", + "interchainSecurityModule": "0x69b33D67B9C51D45E23d22E727FF186DD6298ECA", "mailbox": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696", "merkleTreeHook": "0xfBc08389224d23b79cb21cDc16c5d42F0ad0F57f", "name": "fusemainnet", @@ -1121,7 +1121,7 @@ "interchainAccountIsm": "0x07E2062A1bC66a2C1d05cb5C3870a4AF86e0056E", "interchainAccountRouter": "0xBE70Ab882D1F7E37e04a70CDd9Ec23b37a234064", "interchainGasPaymaster": "0xDd260B99d302f0A3fF885728c086f729c06f227f", - "interchainSecurityModule": "0x996Be332325DA49Ea590A9772a515d62dD90C74c", + "interchainSecurityModule": "0x00533a5F14B3a0632C86f99E4e20a10b73C4AE0D", "mailbox": "0xaD09d78f4c6b9dA2Ae82b1D34107802d380Bb74f", "merkleTreeHook": "0x2684C6F89E901987E1FdB7649dC5Be0c57C61645", "name": "gnosis", @@ -1184,7 +1184,7 @@ "domainId": 2525, "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", - "fallbackRoutingHook": "0xA376b27212D608324808923Add679A2c9FAFe9Da", + "fallbackRoutingHook": "0xf8dba46ff9d8ef650052c89ca2df793fabc375f9", "gasCurrencyCoinGeckoId": "injective-protocol", "index": { "from": 37 @@ -1192,7 +1192,7 @@ "interchainAccountIsm": "0x708E002637792FDC031E6B62f23DD60014AC976a", "interchainAccountRouter": "0xfB8cea1c7F45608Da30655b50bbF355D123A4358", "interchainGasPaymaster": "0x19dc38aeae620380430C200a6E990D5Af5480117", - "interchainSecurityModule": "0x1Bff27a1c1319b0704348895b67426a4Eb1b629e", + "interchainSecurityModule": "0xB8F85B879775adF156Dd4AFa43e97DeB880d99D4", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0972954923a1e2b2aAb04Fa0c4a0797e5989Cd65", "name": "inevm", @@ -1229,7 +1229,14 @@ }, "injective": { "bech32Prefix": "inj", - "blockExplorers": [], + "blockExplorers": [ + { + "apiUrl": "https://www.mintscan.io/injective", + "family": "other", + "name": "Mintscan", + "url": "https://www.mintscan.io/injective" + } + ], "blocks": { "confirmations": 1, "estimateBlockTime": 1, @@ -1313,7 +1320,7 @@ "from": 14616307 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xcaE599dD2142CD8F09a68bAC89b4d809A038d2E9", + "interchainSecurityModule": "0xE2968dAb74541184Ad95651b1e5Cf34Ab1bBEc97", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "kroma", @@ -1386,7 +1393,7 @@ "interchainAccountIsm": "0xdcA646C56E7768DD11654956adE24bfFf9Ba4893", "interchainAccountRouter": "0xD59dA396F162Ed93a41252Cebb8d5DD4F093238C", "interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28", - "interchainSecurityModule": "0x916e612358dA3F7E8e19f51ba2Cf7af3285a6793", + "interchainSecurityModule": "0x0EEF1e64646EE01DeED4850074Cd4B97C0A630a9", "mailbox": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9", "merkleTreeHook": "0xC077A0Cc408173349b1c9870C667B40FE3C01dd7", "name": "linea", @@ -1457,7 +1464,7 @@ "from": 4195553 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xa660FA2047105E0341b356393218586ED2191d14", + "interchainSecurityModule": "0x63Bb509b9CA644609B15Ea55E56f0Acbbb9dB02E", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "lisk", @@ -1521,7 +1528,7 @@ "from": 3088760 }, "interchainGasPaymaster": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", - "interchainSecurityModule": "0x391BD8dD2709F77d39dab4fB3bf4BCAfd5EC3248", + "interchainSecurityModule": "0x609ad94304896607A6D81DB00d882245045B79da", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x062200d92dF6bB7bA89Ce4D6800110450f94784e", "name": "lukso", @@ -1595,7 +1602,7 @@ "interchainAccountIsm": "0x8Ea50255C282F89d1A14ad3F159437EE5EF0507f", "interchainAccountRouter": "0x693A4cE39d99e46B04cb562329e3F0141cA17331", "interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4", - "interchainSecurityModule": "0xBcB96842301c659B575c40C3f93F7311D09c93d9", + "interchainSecurityModule": "0xC012e8E3cBeB6295E1E4837FBA5DB8E077EBc549", "isTestnet": false, "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112", @@ -1665,7 +1672,7 @@ "interchainAccountIsm": "0xe039DA3A0071BEd087A12660D7b03cf669c7776E", "interchainAccountRouter": "0x45285463352c53a481e882cD5E2AF2E25BBdAd0D", "interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28", - "interchainSecurityModule": "0xe542Ed13B5782aF0AFAe7f232bB867FB0208Ab7B", + "interchainSecurityModule": "0x8722328A5Ed815965F9B5eBAA21d04f0F9BFDd35", "mailbox": "0x398633D19f4371e1DB5a8EFE90468eB70B1176AA", "merkleTreeHook": "0x5332D1AC0A626D265298c14ff681c0A8D28dB86d", "name": "mantle", @@ -1727,7 +1734,7 @@ "from": 13523607 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x5725a9Bf3bdaF104Ce1A0098308DD974F6395365", + "interchainSecurityModule": "0xE8176Fc70f129255aA83d3db242C2246Ad77Af7D", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "merlin", @@ -1794,7 +1801,7 @@ "from": 17966274 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xfd810678075502F76A6ef79cedffe58cff6Cc410", + "interchainSecurityModule": "0xA9309228762699D5c81A4b0BAfd06Da21589746b", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "metis", @@ -1859,7 +1866,7 @@ "from": 3752032 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xfd810678075502F76A6ef79cedffe58cff6Cc410", + "interchainSecurityModule": "0xA9309228762699D5c81A4b0BAfd06Da21589746b", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "mint", @@ -1926,7 +1933,7 @@ "interchainAccountIsm": "0xa377b8269e0A47cdd2fD5AAeAe860b45623c6d82", "interchainAccountRouter": "0x6e1B9f776bd415d7cC3C7458A5f0d801016918f8", "interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d", - "interchainSecurityModule": "0x1ab6985E0e15d293e71d01510fa6B57311C69718", + "interchainSecurityModule": "0x0777dFffcEd18EE416e35401E0e5e0413b7D43be", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6", "name": "mode", @@ -1994,7 +2001,7 @@ "interchainAccountIsm": "0x79b3730CE3685f65802aF1771319992bA960EB9D", "interchainAccountRouter": "0xc4482f66191754a8629D35289043C4EB0285F10E", "interchainGasPaymaster": "0x14760E32C0746094cF14D97124865BC7F0F7368F", - "interchainSecurityModule": "0x105215D46F45a88B3793B798Fb87AF231Ad9f611", + "interchainSecurityModule": "0xad1Ad827035eDe500aFd0ff122c53f6eA607Eb5C", "mailbox": "0x094d03E751f49908080EFf000Dd6FD177fd44CC3", "merkleTreeHook": "0x87403b85f6f316e7ba91ba1fa6C3Fb7dD4095547", "name": "moonbeam", @@ -2136,7 +2143,7 @@ "interchainAccountIsm": "0x2c46BF14641d00549ECa4779BF5CBf91602C1DEd", "interchainAccountRouter": "0x03D6cC17d45E9EA27ED757A8214d1F07F7D901aD", "interchainGasPaymaster": "0xD8A76C4D91fCbB7Cc8eA795DFDF870E48368995C", - "interchainSecurityModule": "0x1E491c93Ab56A298bBC34B4Fca8A4cE68E8d540a", + "interchainSecurityModule": "0x3878aB31B2426A92E8a1E0AE758d848879F7F5E8", "mailbox": "0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D", "merkleTreeHook": "0x68eE9bec9B4dbB61f69D9D293Ae26a5AACb2e28f", "name": "optimism", @@ -2271,7 +2278,7 @@ "interchainAccountIsm": "0xBAC4529cdfE7CCe9E858BF706e41F8Ed096C1BAd", "interchainAccountRouter": "0xF163949AD9F88977ebF649D0461398Ca752E64B9", "interchainGasPaymaster": "0x0071740Bf129b05C4684abfbBeD248D80971cce2", - "interchainSecurityModule": "0x0D408EF040ca0E7a75f03c41Aa46cAc904770D45", + "interchainSecurityModule": "0x9fFC02BfB5C7260C985b005C0cF40d7EC601aac2", "mailbox": "0x5d934f4e2f797775e53561bB72aca21ba36B96BB", "merkleTreeHook": "0x73FbD25c3e817DC4B4Cd9d00eff6D83dcde2DfF6", "name": "polygon", @@ -2348,7 +2355,7 @@ "interchainAccountIsm": "0xc1198e241DAe48BF5AEDE5DCE49Fe4A6064cF7a7", "interchainAccountRouter": "0x20a0A32a110362920597F72974E1E0d7e25cA20a", "interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4", - "interchainSecurityModule": "0x5C622f40365F57D06b5e7132B1483fcbc9566560", + "interchainSecurityModule": "0xc6c475184F197FA65f233dFc22FA6bD4cE48B4fE", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112", "name": "polygonzkevm", @@ -2416,7 +2423,7 @@ "from": 32018468 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x336306ADB3c510A318107c01D109D2072c7abB6B", + "interchainSecurityModule": "0x70e8beCE806914959c1B5D8F75d2217058D31437", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "proofofplay", @@ -2480,7 +2487,7 @@ "from": 363159 }, "interchainGasPaymaster": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696", - "interchainSecurityModule": "0x06567d07b49ad922A821A641F1C962569a255dbB", + "interchainSecurityModule": "0x43346a54445BBdf8241062904E8A13AA62842a02", "mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", "merkleTreeHook": "0x55E4F0bc6b7Bb493D50839A8592e7ad8d5e93cf7", "name": "real", @@ -2547,7 +2554,7 @@ "interchainAccountIsm": "0x5DA60220C5dDe35b7aE91c042ff5979047FA0785", "interchainAccountRouter": "0x7a4d31a686A36285d68e14EDD53631417eB19603", "interchainGasPaymaster": "0x2Fa570E83009eaEef3a1cbd496a9a30F05266634", - "interchainSecurityModule": "0x5a3bB91853CfDaDb1bC95D2E061B50d433fbe3E8", + "interchainSecurityModule": "0xd8b6B632526834D8192860e6B6CE47165Fd02a42", "mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", "merkleTreeHook": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA", "name": "redstone", @@ -2609,7 +2616,7 @@ "from": 937117 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xA76F4620ac1e97d273B2C9Ca71805c8afD792098", + "interchainSecurityModule": "0x6A2748201F66647ad6D164CB3340A893881A4bb2", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "sanko", @@ -2677,7 +2684,7 @@ "interchainAccountIsm": "0x32af5Df81fEd5E26119F6640FBB13f3d63a94CDe", "interchainAccountRouter": "0x0B48a744698ba8dFa514742dFEB6728f52fD66f7", "interchainGasPaymaster": "0xBF12ef4B9f307463D3FB59c3604F294dDCe287E2", - "interchainSecurityModule": "0x37e17723b665A9F95F4aecEEc40D9eF39624764e", + "interchainSecurityModule": "0xAd1a987BfE0D6fbD92089628daC7C7e4bA9a6AAF", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x6119E37Bd66406A1Db74920aC79C15fB8411Ba76", "name": "scroll", @@ -2745,7 +2752,7 @@ "interchainAccountIsm": "0xf35dc7B9eE4Ebf0cd3546Bd6EE3b403dE2b9F5D6", "interchainAccountRouter": "0xBcaedE97a98573A88242B3b0CB0A255F3f90d4d5", "interchainGasPaymaster": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72", - "interchainSecurityModule": "0x26184898fA27D3471B50BD956AB5b3E9Aa14763C", + "interchainSecurityModule": "0x494028EA206642e4c60Ec3d12e96B4549E5e1800", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xca1b69fA4c4a7c7fD839bC50867c589592bcfe49", "name": "sei", @@ -2860,7 +2867,7 @@ "interchainAccountIsm": "0xAE557e108b3336130370aC74836f1356B4b30Cf2", "interchainAccountRouter": "0x1F8CF09F060A2AE962c0Bb1F92e209a1E7b0E10B", "interchainGasPaymaster": "0x273Bc6b01D9E88c064b6E5e409BdF998246AEF42", - "interchainSecurityModule": "0x478D0e5d221C8d7CA1A6353315fac6FA88Ff1B97", + "interchainSecurityModule": "0xC93F2796A17Ee4580c039aeB7b0c923b10ce79C2", "mailbox": "0x28EFBCadA00A7ed6772b3666F3898d276e88CAe3", "merkleTreeHook": "0x6A55822cf11f9fcBc4c75BC2638AfE8Eb942cAdd", "name": "taiko", @@ -2922,7 +2929,7 @@ "from": 1678063 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0x336306ADB3c510A318107c01D109D2072c7abB6B", + "interchainSecurityModule": "0x70e8beCE806914959c1B5D8F75d2217058D31437", "isTestnet": false, "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", @@ -2990,7 +2997,7 @@ "interchainAccountIsm": "0x551BbEc45FD665a8C95ca8731CbC32b7653Bc59B", "interchainAccountRouter": "0xc11f8Cf2343d3788405582F65B8af6A4F7a6FfC8", "interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4", - "interchainSecurityModule": "0x5542503cBde841c336Afef014FE80b0F1c9d716d", + "interchainSecurityModule": "0x3465AccC39AE5e6C344184013a57cDCe546834d6", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112", "name": "viction", @@ -3058,7 +3065,7 @@ "interchainAccountIsm": "0xCB9f90EE5d83Ea52ABd922BD70898f0155D54798", "interchainAccountRouter": "0x473884010F0C1742DA8Ad01E7E295624B931076b", "interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503", - "interchainSecurityModule": "0xc1FF2bf7a4C315bE2a06941D236457EB02F93993", + "interchainSecurityModule": "0x05f6BAa16F1aCf7b19c4A09E019D856c10ab8355", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD", "name": "worldchain", @@ -3120,7 +3127,7 @@ "from": 24395308 }, "interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF", - "interchainSecurityModule": "0xC630ef37e03534721557026FeC397Ec05f85584C", + "interchainSecurityModule": "0x4886ed96bcdba2ad85Bf518C3171C39e256ac840", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "name": "xai", @@ -3188,7 +3195,7 @@ "interchainAccountIsm": "0x29B37088724B745C0ABcE591449Cf042772160C2", "interchainAccountRouter": "0x03cF708E42C89623bd83B281A56935cB562b9258", "interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503", - "interchainSecurityModule": "0x0811C6250965E7Ba1A872A12249B1b2300d85CFD", + "interchainSecurityModule": "0x59B0ec92522F164b72c9BE473382197c564B92dc", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD", "name": "xlayer", @@ -3256,7 +3263,7 @@ "interchainAccountIsm": "0x2b6d3F7d28B5EC8C3C028fBCAdcf774D9709Dd29", "interchainAccountRouter": "0x3AdCBc94ab8C48EC52D06dc65Bb787fD1981E3d5", "interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d", - "interchainSecurityModule": "0x858a077945bCC4afA40DaE5a75faB9237e899b30", + "interchainSecurityModule": "0xd32353Ae5719ac4f8f24AeD81A2A6898d2632D26", "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6", "name": "zetachain", @@ -3322,7 +3329,7 @@ "from": 1511458 }, "interchainGasPaymaster": "0x03cF708E42C89623bd83B281A56935cB562b9258", - "interchainSecurityModule": "0xb04DE6Cbc6E258E8f2D2B00EBdcD2Ea901791EAA", + "interchainSecurityModule": "0xFFec270FE3D0e3B9348B3664BE73A5d4906BA620", "mailbox": "0xc2FbB9411186AB3b1a6AFCCA702D1a80B48b197c", "merkleTreeHook": "0x4C97D35c668EE5194a13c8DE8Afc18cce40C9F28", "name": "zircuit", @@ -3395,7 +3402,7 @@ "interchainAccountIsm": "0xb2674E213019972f937CCFc5e23BF963D915809e", "interchainAccountRouter": "0x11b76D93a9D39Eb51F54eBf5566308640cDe882b", "interchainGasPaymaster": "0x18B0688990720103dB63559a3563f7E8d0f63EDb", - "interchainSecurityModule": "0xDede6e50E548460FB6a939320F707214CFfC701C", + "interchainSecurityModule": "0xED5fD1715A0885a3C7B908BAd5c8C64Ba5166265", "mailbox": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a", "merkleTreeHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", "name": "zoramainnet", @@ -3466,7 +3473,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", + "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3533,7 +3540,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", + "interchainSecurityModule": "0xa18979d2e5b8A64f62E0f9e9523d28E934F1104c", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3603,7 +3610,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", + "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3679,7 +3686,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", + "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3743,7 +3750,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", + "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3816,7 +3823,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", + "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3884,7 +3891,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B", + "interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -3947,7 +3954,7 @@ "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", "fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB", "interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", - "interchainSecurityModule": "0x12C8cfA5B97Df96AaB2795a4186675dA49938968", + "interchainSecurityModule": "0xf08b7F859966ed27286Fe7d924A42b40e2DB80Bd", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575", "pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27", @@ -4017,7 +4024,7 @@ "interchainAccountIsm": "0xcd9D3744512F07AE844c40E27912092d7c503565", "interchainAccountRouter": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8", "interchainGasPaymaster": "0xb58257cc81E47EC72fD38aE16297048de23163b4", - "interchainSecurityModule": "0xA16954f5040ba7fE2286569aD107a22a46FffDC6", + "interchainSecurityModule": "0xcC5C35a6214982d9018B95e9684D5b4dA626237e", "mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", "merkleTreeHook": "0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1", "pausableHook": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd", @@ -4077,7 +4084,7 @@ "interchainAccountIsm": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319", "interchainAccountRouter": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE", "interchainGasPaymaster": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86", - "interchainSecurityModule": "0x128432015A0E08d490e0FD6b4dE4EAbe30f617a3", + "interchainSecurityModule": "0x50B5Edd94A1C7ad18Fa2CA667A30Dc051a695aEe", "mailbox": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", "merkleTreeHook": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59", "pausableHook": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2", @@ -4149,7 +4156,7 @@ "interchainAccountIsm": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", "interchainAccountRouter": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", + "interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4212,7 +4219,7 @@ "interchainAccountIsm": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47", "interchainAccountRouter": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", + "interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4282,7 +4289,7 @@ "interchainAccountIsm": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", "interchainAccountRouter": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", + "interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4353,7 +4360,7 @@ "interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719", "interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64", "interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", - "interchainSecurityModule": "0x8750ac24C3bE28b406fBCD664AbabF676d3aCB29", + "interchainSecurityModule": "0x9dccF81bB9f419425b0a6584E8800556B92209Cc", "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", "merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", "pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", @@ -4421,7 +4428,7 @@ "interchainAccountIsm": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8", "interchainAccountRouter": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE", "interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2", - "interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6", + "interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6", "pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c", @@ -4487,7 +4494,7 @@ "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", "interchainGasPaymaster": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", - "interchainSecurityModule": "0x01031eCa87184c84938016E1444150472Da35b3a", + "interchainSecurityModule": "0x81EC949b07e033b0346E60C2098464d115F0a997", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", "pausableHook": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD", @@ -4558,7 +4565,7 @@ "interchainAccountIsm": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666", "interchainAccountRouter": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de", "interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", - "interchainSecurityModule": "0x8750ac24C3bE28b406fBCD664AbabF676d3aCB29", + "interchainSecurityModule": "0x9dccF81bB9f419425b0a6584E8800556B92209Cc", "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", "merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912", "pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19", @@ -4619,7 +4626,7 @@ "interchainAccountIsm": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", "interchainAccountRouter": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", "interchainGasPaymaster": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76", - "interchainSecurityModule": "0xE89fF24e1979F6AbD6b71b733cc62d1289d193c4", + "interchainSecurityModule": "0x9d1481A1fc2515aeE0Bf4eEeDDB75893DfAF0752", "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", "merkleTreeHook": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918", "pausableHook": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E", @@ -4683,7 +4690,7 @@ "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", "interchainGasPaymaster": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4", - "interchainSecurityModule": "0xFF16628ff85F145Ce6d1712014D46DcFB52da75A", + "interchainSecurityModule": "0x8f93c32C19986B891beA2bF317686Aa2336b3854", "mailbox": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9", "merkleTreeHook": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56", "pausableHook": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594", @@ -4748,7 +4755,7 @@ "interchainAccountIsm": "0xb5668713E9BA8bC96f97D691663E70b54CE90b0A", "interchainAccountRouter": "0xc5068BB6803ADbe5600DE5189fe27A4dAcE31170", "interchainGasPaymaster": "0xA1Df6B70044029a2D1eDDC50EfDE2813e478140a", - "interchainSecurityModule": "0x729E790E70902429873c23BaA73eE39aCEEfc461", + "interchainSecurityModule": "0x01180E7B92A4fEA1e250C92E32A02Df1cA058Fe0", "mailbox": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", "merkleTreeHook": "0x25d668D37f20E6f396cB5DF1DFf5A3f2F568e707", "pausableHook": "0xC9ab9Dc82F05eA118F266611f4c474529d43b599", @@ -4773,6 +4780,69 @@ "transactionOverrides": { "gasPrice": 100000000 } + }, + "stride": { + "bech32Prefix": "stride", + "blockExplorers": [ + { + "apiUrl": "https://www.mintscan.io/stride", + "family": "other", + "name": "Mintscan", + "url": "https://www.mintscan.io/stride" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 5, + "reorgPeriod": 1 + }, + "chainId": "stride-1", + "deployer": { + "name": "Stride Labs", + "url": "https://www.stride.zone" + }, + "displayName": "Stride", + "domainId": 745, + "gasCurrencyCoinGeckoId": "stride", + "grpcUrls": [ + { + "http": "https://stride-grpc.publicnode.com:443" + } + ], + "isTestnet": false, + "name": "stride", + "nativeToken": { + "decimals": 6, + "denom": "ustrd", + "name": "Stride", + "symbol": "STRD" + }, + "protocol": "cosmos", + "restUrls": [ + { + "http": "https://stride-api.polkachu.com" + } + ], + "rpcUrls": [ + { + "http": "https://stride-rpc.polkachu.com" + } + ], + "slip44": 118, + "interchainGasPaymaster": "0x0000000000000000000000000000000000000000000000000000000000000000", + "mailbox": "0x89945750e089d84581f194e1947a58480b335f18386ad4f761f05feebf5e2454", + "merkleTreeHook": "0x7ab4a8c3ba5371e34cd8d5dc584e0d924504fc21c3cbf41c3f64d436176bf007", + "validatorAnnounce": "0xf57d954bf3ddb5f1032a0e020a99e931215cf83ceb4de987c781488065aaae0d", + "gasPrice": { + "denom": "ustrd", + "amount": "0.005" + }, + "canonicalAsset": "ustrd", + "contractAddressBytes": 32, + "index": { + "from": 9152000, + "chunk": 5 + } } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 6b6f2bae5..fa21db977 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -115,6 +115,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< sei: true, shibarium: true, solanamainnet: true, + stride: false, superposition: true, taiko: true, tangle: true, @@ -189,6 +190,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< sei: true, shibarium: true, solanamainnet: true, + stride: true, superposition: true, taiko: true, tangle: true, @@ -264,6 +266,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< shibarium: true, // Cannot scrape Sealevel chains solanamainnet: false, + stride: true, superposition: true, taiko: true, tangle: true, @@ -418,7 +421,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'b1ff48b-20241016-183301', + tag: '42d6b50-20241021-155906', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -437,7 +440,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '9c0c4bb-20241018-113820', + tag: '42d6b50-20241021-155906', }, resources: scraperResources, }, @@ -452,7 +455,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'b1ff48b-20241016-183301', + tag: '42d6b50-20241021-155906', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index dafee524d..e69298dc3 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -82,6 +82,8 @@ export const keyFunderConfig: KeyFunderConfig< scroll: '0.5', sei: '50', shibarium: '50', + // ignore non-evm chains + stride: '0', superposition: '0.05', taiko: '0.2', tangle: '2', diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index d68a6d290..7f61122c8 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -243,6 +243,10 @@ "amount": "0.5", "decimals": 1 }, + "stride": { + "amount": "0.005", + "decimals": 1 + }, "superposition": { "amount": "0.01", "decimals": 9 diff --git a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts index c5eabc80c..3e5957241 100644 --- a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts +++ b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts @@ -62,6 +62,7 @@ export const mainnet3SupportedChainNames = [ 'sei', 'shibarium', 'solanamainnet', + 'stride', 'superposition', 'taiko', 'tangle', diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index df245702e..86c2ed731 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -60,6 +60,7 @@ "sei": "0.447635", "shibarium": "0.410927", "solanamainnet": "155.35", + "stride": "0.840153", "superposition": "2629.74", "taiko": "2629.74", "tangle": "1", diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index d35a1499f..893a25c71 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -166,17 +166,23 @@ export abstract class HyperlaneAppGovernor< // If calls are being submitted via a safe, we need to check for any safe owner changes first if (submissionType === SubmissionType.SAFE) { - const { safeSdk } = await getSafeAndService( - chain, - this.checker.multiProvider, - (multiSend as SafeMultiSend).safeAddress, - ); - const updateOwnerCalls = await updateSafeOwner(safeSdk); - callsForSubmissionType.push(...updateOwnerCalls, ...filteredCalls); - } else { - callsForSubmissionType.push(...filteredCalls); + try { + const { safeSdk } = await getSafeAndService( + chain, + this.checker.multiProvider, + (multiSend as SafeMultiSend).safeAddress, + ); + const updateOwnerCalls = await updateSafeOwner(safeSdk); + callsForSubmissionType.push(...updateOwnerCalls); + } catch (error) { + // Catch but don't throw because we want to try submitting any remaining calls + console.error(`Error updating safe owner: ${error}`); + } } + // Add the filtered calls to the calls for submission type + callsForSubmissionType.push(...filteredCalls); + if (callsForSubmissionType.length > 0) { this.printSeparator(); const confirmed = await summarizeCalls( diff --git a/typescript/sdk/src/contracts/contracts.ts b/typescript/sdk/src/contracts/contracts.ts index 90b754e8c..5f1913a55 100644 --- a/typescript/sdk/src/contracts/contracts.ts +++ b/typescript/sdk/src/contracts/contracts.ts @@ -1,4 +1,4 @@ -import { Contract, ethers } from 'ethers'; +import { Contract } from 'ethers'; import { Ownable } from '@hyperlane-xyz/core'; import { @@ -235,31 +235,15 @@ export function appFromAddressesMapHelper( contractsMap: HyperlaneContractsMap; multiProvider: MultiProvider; } { - // Hack to accommodate non-Ethereum artifacts, while still retaining their - // presence in the addressesMap so that they are included in the list of chains - // on the MultiProvider (needed for getting metadata). A non-Ethereum-style address - // from another execution environment will cause Ethers to throw if we try to attach - // it, so we just replace it with the zero address. - const addressesMapWithEthereumizedAddresses = objMap( + // Filter out non-Ethereum chains from the addressesMap + const ethereumAddressesMap = objFilter( addressesMap, - (chain, addresses) => { - const metadata = multiProvider.getChainMetadata(chain); - if (metadata.protocol === ProtocolType.Ethereum) { - return addresses; - } - return objMap( - addresses, - (_key, _address) => ethers.constants.AddressZero, - ); - }, + (chain, _): _ is HyperlaneAddresses => + multiProvider.getProtocol(chain) === ProtocolType.Ethereum, ); - // Attaches contracts for each chain for which we have a complete set of - // addresses - const contractsMap = attachContractsMap( - addressesMapWithEthereumizedAddresses, - factories, - ); + // Attaches contracts for each Ethereum chain for which we have a complete set of addresses + const contractsMap = attachContractsMap(ethereumAddressesMap, factories); // Filters out providers for chains for which we don't have a complete set // of addresses @@ -270,6 +254,6 @@ export function appFromAddressesMapHelper( return { contractsMap: filteredContractsMap, - multiProvider: multiProvider, + multiProvider, }; } From f9f0ece7c47ed80aebc8b035db8a61b85fd3bc0d Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Wed, 23 Oct 2024 19:08:36 +0100 Subject: [PATCH 179/224] feat: add zkSync enum variant to HyperlaneDomainTechnicalStack (#4740) ### Description To match the new TS schema ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/main/hyperlane-core/src/chain.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/main/hyperlane-core/src/chain.rs b/rust/main/hyperlane-core/src/chain.rs index a4cfaac77..134881bf7 100644 --- a/rust/main/hyperlane-core/src/chain.rs +++ b/rust/main/hyperlane-core/src/chain.rs @@ -299,6 +299,7 @@ pub enum HyperlaneDomainTechnicalStack { OpStack, PolygonCDK, PolkadotSubstrate, + ZkSync, #[default] Other, } @@ -382,6 +383,7 @@ impl KnownHyperlaneDomain { HyperlaneDomainTechnicalStack::PolkadotSubstrate: [ Moonbeam, Tangle ], + HyperlaneDomainTechnicalStack::ZkSync: [], HyperlaneDomainTechnicalStack::Other: [ Avalanche, BinanceSmartChain, Celo, EclipseMainnet, Endurance, Ethereum, FuseMainnet, Gnosis, Injective, Linea, Lukso, Neutron, Osmosis, Polygon, From b585de0c53f02a9ec73aeb401bf2f8ae9170f6c9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:17:43 +0000 Subject: [PATCH 180/224] Version Packages (#4663) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/core@5.5.0 ### Minor Changes - 72c23c0d6: Added PRECISION and rateUpdateNonce to ensure compatibility of HypERC4626 ### Patch Changes - c9085afd9: Patched OPL2ToL1Ism to check for correct messageId for external call in verify - ec6b874b1: Added nonce to HypERC4626 - Updated dependencies [f1712deb7] - Updated dependencies [29341950e] - @hyperlane-xyz/utils@5.6.0 ## @hyperlane-xyz/cli@5.6.0 ### Minor Changes - 41035aac8: Add strategyUrl detect and validation in the beginning of `warp apply` Remove yaml transactions print from `warp apply` - 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation - 32d0a67c2: Adds the warp check command to compare warp routes config files with on chain warp route deployments - 3662297fc: Add prompt in `warp init` command to choose if a trusted relayer should be used instead of making the choice by default for the user and enable the `--yes` flag to default to a trusted ISM - b1ff48bd1: Add rebasing yield route support into CLI/SDK - d41aa6928: Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod - c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. - a4d5d692f: Update `warp apply` such that it updates in place AND extends in a single call - 01e7070eb: updates the multi chain selection prompt by adding search functionality and an optional confirmation prompt for the current selection ### Patch Changes - e89f9e35d: Update registry to v4.7.0 - Updated dependencies [f1712deb7] - Updated dependencies [46044a2e9] - Updated dependencies [02a5b92ba] - Updated dependencies [29341950e] - Updated dependencies [8001bbbd6] - Updated dependencies [32d0a67c2] - Updated dependencies [b1ff48bd1] - Updated dependencies [d41aa6928] - Updated dependencies [c3e9268f1] - Updated dependencies [7d7bcc1a3] - Updated dependencies [7f3e0669d] - Updated dependencies [2317eca3c] - @hyperlane-xyz/utils@5.6.0 - @hyperlane-xyz/sdk@5.6.0 ## @hyperlane-xyz/sdk@5.6.0 ### Minor Changes - 46044a2e9: Deploy to odysseytestnet - 02a5b92ba: Enroll new validators. Add tx overrides when deploying ICA accounts. Core checker now surfaces owner violations for defaultHook and requiredHook. App checker temporarily ignores bytecode mismatch violations. - 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation - 8001bbbd6: Add override to some transactions to fix warp apply - 32d0a67c2: Adds the warp check command to compare warp routes config files with on chain warp route deployments - b1ff48bd1: Add rebasing yield route support into CLI/SDK - d41aa6928: Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod - c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. - 7d7bcc1a3: Add deployments for mainnets: flow, metall2, polynomial ### Patch Changes - 7f3e0669d: Fix filtering non-evm addresses in appFromAddressesMapHelper - 2317eca3c: Set transaction overrides and add 10% gas limit buffer when sending message through HyperlaneCore. - Updated dependencies [f1712deb7] - Updated dependencies [29341950e] - Updated dependencies [c9085afd9] - Updated dependencies [ec6b874b1] - Updated dependencies [72c23c0d6] - @hyperlane-xyz/utils@5.6.0 - @hyperlane-xyz/core@5.5.0 ## @hyperlane-xyz/utils@5.6.0 ### Minor Changes - 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation ### Patch Changes - f1712deb7: Fix objMerge implementation ## @hyperlane-xyz/helloworld@5.6.0 ### Patch Changes - e89f9e35d: Update registry to v4.7.0 - Updated dependencies [46044a2e9] - Updated dependencies [02a5b92ba] - Updated dependencies [29341950e] - Updated dependencies [8001bbbd6] - Updated dependencies [32d0a67c2] - Updated dependencies [c9085afd9] - Updated dependencies [b1ff48bd1] - Updated dependencies [d41aa6928] - Updated dependencies [ec6b874b1] - Updated dependencies [c3e9268f1] - Updated dependencies [72c23c0d6] - Updated dependencies [7d7bcc1a3] - Updated dependencies [7f3e0669d] - Updated dependencies [2317eca3c] - @hyperlane-xyz/sdk@5.6.0 - @hyperlane-xyz/core@5.5.0 ## @hyperlane-xyz/widgets@5.6.0 ### Patch Changes - e89f9e35d: Update registry to v4.7.0 - Updated dependencies [f1712deb7] - Updated dependencies [46044a2e9] - Updated dependencies [02a5b92ba] - Updated dependencies [29341950e] - Updated dependencies [8001bbbd6] - Updated dependencies [32d0a67c2] - Updated dependencies [b1ff48bd1] - Updated dependencies [d41aa6928] - Updated dependencies [c3e9268f1] - Updated dependencies [7d7bcc1a3] - Updated dependencies [7f3e0669d] - Updated dependencies [2317eca3c] - @hyperlane-xyz/utils@5.6.0 - @hyperlane-xyz/sdk@5.6.0 ## @hyperlane-xyz/infra@5.6.0 ### Minor Changes - b3495b205: Updates the warpIds for Renzo's latest deployment to Sei and Taiko to be used by the Checker - c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. ### Patch Changes - Updated dependencies [f1712deb7] - Updated dependencies [46044a2e9] - Updated dependencies [02a5b92ba] - Updated dependencies [29341950e] - Updated dependencies [8001bbbd6] - Updated dependencies [32d0a67c2] - Updated dependencies [b1ff48bd1] - Updated dependencies [e89f9e35d] - Updated dependencies [d41aa6928] - Updated dependencies [c3e9268f1] - Updated dependencies [7d7bcc1a3] - Updated dependencies [7f3e0669d] - Updated dependencies [2317eca3c] - @hyperlane-xyz/utils@5.6.0 - @hyperlane-xyz/sdk@5.6.0 - @hyperlane-xyz/helloworld@5.6.0 ## @hyperlane-xyz/ccip-server@5.6.0 ## @hyperlane-xyz/github-proxy@5.6.0 --------- Co-authored-by: github-actions[bot] --- .changeset/dirty-clocks-repeat.md | 5 ---- .changeset/dirty-months-buy.md | 5 ---- .changeset/dry-foxes-battle.md | 6 ----- .changeset/few-goats-add.md | 5 ---- .changeset/flat-swans-help.md | 7 ------ .changeset/fluffy-ducks-buy.md | 5 ---- .changeset/grumpy-ears-relate.md | 6 ----- .changeset/itchy-singers-hang.md | 5 ---- .changeset/long-swans-drive.md | 5 ---- .changeset/plenty-chicken-clean.md | 6 ----- .changeset/poor-coins-accept.md | 7 ------ .changeset/quiet-cooks-join.md | 6 ----- .changeset/red-actors-shop.md | 5 ---- .changeset/silver-dancers-rhyme.md | 5 ---- .changeset/strange-beers-buy.md | 7 ------ .changeset/sweet-humans-argue.md | 5 ---- .changeset/tender-spiders-deny.md | 5 ---- .changeset/tidy-hornets-beam.md | 5 ---- .changeset/tough-bats-yell.md | 5 ---- .changeset/tricky-mangos-sin.md | 5 ---- .changeset/wise-camels-repair.md | 5 ---- solidity/CHANGELOG.md | 14 +++++++++++ solidity/contracts/PackageVersioned.sol | 2 +- solidity/package.json | 4 +-- typescript/ccip-server/CHANGELOG.md | 2 ++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 33 +++++++++++++++++++++++++ typescript/cli/package.json | 6 ++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 2 ++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 22 +++++++++++++++++ typescript/helloworld/package.json | 6 ++--- typescript/infra/CHANGELOG.md | 26 +++++++++++++++++++ typescript/infra/package.json | 8 +++--- typescript/sdk/CHANGELOG.md | 26 +++++++++++++++++++ typescript/sdk/package.json | 6 ++--- typescript/utils/CHANGELOG.md | 10 ++++++++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 20 +++++++++++++++ typescript/widgets/package.json | 6 ++--- yarn.lock | 32 ++++++++++++------------ 42 files changed, 194 insertions(+), 154 deletions(-) delete mode 100644 .changeset/dirty-clocks-repeat.md delete mode 100644 .changeset/dirty-months-buy.md delete mode 100644 .changeset/dry-foxes-battle.md delete mode 100644 .changeset/few-goats-add.md delete mode 100644 .changeset/flat-swans-help.md delete mode 100644 .changeset/fluffy-ducks-buy.md delete mode 100644 .changeset/grumpy-ears-relate.md delete mode 100644 .changeset/itchy-singers-hang.md delete mode 100644 .changeset/long-swans-drive.md delete mode 100644 .changeset/plenty-chicken-clean.md delete mode 100644 .changeset/poor-coins-accept.md delete mode 100644 .changeset/quiet-cooks-join.md delete mode 100644 .changeset/red-actors-shop.md delete mode 100644 .changeset/silver-dancers-rhyme.md delete mode 100644 .changeset/strange-beers-buy.md delete mode 100644 .changeset/sweet-humans-argue.md delete mode 100644 .changeset/tender-spiders-deny.md delete mode 100644 .changeset/tidy-hornets-beam.md delete mode 100644 .changeset/tough-bats-yell.md delete mode 100644 .changeset/tricky-mangos-sin.md delete mode 100644 .changeset/wise-camels-repair.md diff --git a/.changeset/dirty-clocks-repeat.md b/.changeset/dirty-clocks-repeat.md deleted file mode 100644 index d9159825a..000000000 --- a/.changeset/dirty-clocks-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/utils': patch ---- - -Fix objMerge implementation diff --git a/.changeset/dirty-months-buy.md b/.changeset/dirty-months-buy.md deleted file mode 100644 index 2b3f91e99..000000000 --- a/.changeset/dirty-months-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Deploy to odysseytestnet diff --git a/.changeset/dry-foxes-battle.md b/.changeset/dry-foxes-battle.md deleted file mode 100644 index eadb8427e..000000000 --- a/.changeset/dry-foxes-battle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor ---- - -Add strategyUrl detect and validation in the beginning of `warp apply` -Remove yaml transactions print from `warp apply` diff --git a/.changeset/few-goats-add.md b/.changeset/few-goats-add.md deleted file mode 100644 index ffcab1f49..000000000 --- a/.changeset/few-goats-add.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Enroll new validators. Add tx overrides when deploying ICA accounts. Core checker now surfaces owner violations for defaultHook and requiredHook. App checker temporarily ignores bytecode mismatch violations. diff --git a/.changeset/flat-swans-help.md b/.changeset/flat-swans-help.md deleted file mode 100644 index e5f0e2111..000000000 --- a/.changeset/flat-swans-help.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperlane-xyz/utils': minor -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation diff --git a/.changeset/fluffy-ducks-buy.md b/.changeset/fluffy-ducks-buy.md deleted file mode 100644 index 1b5db5097..000000000 --- a/.changeset/fluffy-ducks-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Add override to some transactions to fix warp apply diff --git a/.changeset/grumpy-ears-relate.md b/.changeset/grumpy-ears-relate.md deleted file mode 100644 index 8dbc0a515..000000000 --- a/.changeset/grumpy-ears-relate.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Adds the warp check command to compare warp routes config files with on chain warp route deployments diff --git a/.changeset/itchy-singers-hang.md b/.changeset/itchy-singers-hang.md deleted file mode 100644 index 97096ff1a..000000000 --- a/.changeset/itchy-singers-hang.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': patch ---- - -Patched OPL2ToL1Ism to check for correct messageId for external call in verify diff --git a/.changeset/long-swans-drive.md b/.changeset/long-swans-drive.md deleted file mode 100644 index 3f21e56c4..000000000 --- a/.changeset/long-swans-drive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor ---- - -Add prompt in `warp init` command to choose if a trusted relayer should be used instead of making the choice by default for the user and enable the `--yes` flag to default to a trusted ISM diff --git a/.changeset/plenty-chicken-clean.md b/.changeset/plenty-chicken-clean.md deleted file mode 100644 index e35a59eff..000000000 --- a/.changeset/plenty-chicken-clean.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Add rebasing yield route support into CLI/SDK diff --git a/.changeset/poor-coins-accept.md b/.changeset/poor-coins-accept.md deleted file mode 100644 index 2c3c6a892..000000000 --- a/.changeset/poor-coins-accept.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperlane-xyz/helloworld': patch -'@hyperlane-xyz/widgets': patch -'@hyperlane-xyz/cli': patch ---- - -Update registry to v4.7.0 diff --git a/.changeset/quiet-cooks-join.md b/.changeset/quiet-cooks-join.md deleted file mode 100644 index a5f39f2ab..000000000 --- a/.changeset/quiet-cooks-join.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod diff --git a/.changeset/red-actors-shop.md b/.changeset/red-actors-shop.md deleted file mode 100644 index 0ee301e90..000000000 --- a/.changeset/red-actors-shop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': patch ---- - -Added nonce to HypERC4626 diff --git a/.changeset/silver-dancers-rhyme.md b/.changeset/silver-dancers-rhyme.md deleted file mode 100644 index 14ce7dd00..000000000 --- a/.changeset/silver-dancers-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/infra': minor ---- - -Updates the warpIds for Renzo's latest deployment to Sei and Taiko to be used by the Checker diff --git a/.changeset/strange-beers-buy.md b/.changeset/strange-beers-buy.md deleted file mode 100644 index 3ad5bc57e..000000000 --- a/.changeset/strange-beers-buy.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperlane-xyz/infra': minor -'@hyperlane-xyz/cli': minor -'@hyperlane-xyz/sdk': minor ---- - -Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. diff --git a/.changeset/sweet-humans-argue.md b/.changeset/sweet-humans-argue.md deleted file mode 100644 index 3a6ff4647..000000000 --- a/.changeset/sweet-humans-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': minor ---- - -Added PRECISION and rateUpdateNonce to ensure compatibility of HypERC4626 diff --git a/.changeset/tender-spiders-deny.md b/.changeset/tender-spiders-deny.md deleted file mode 100644 index 99a6cede4..000000000 --- a/.changeset/tender-spiders-deny.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor ---- - -Update `warp apply` such that it updates in place AND extends in a single call diff --git a/.changeset/tidy-hornets-beam.md b/.changeset/tidy-hornets-beam.md deleted file mode 100644 index b4cff7c2f..000000000 --- a/.changeset/tidy-hornets-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': minor ---- - -Add deployments for mainnets: flow, metall2, polynomial diff --git a/.changeset/tough-bats-yell.md b/.changeset/tough-bats-yell.md deleted file mode 100644 index 71343609b..000000000 --- a/.changeset/tough-bats-yell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Fix filtering non-evm addresses in appFromAddressesMapHelper diff --git a/.changeset/tricky-mangos-sin.md b/.changeset/tricky-mangos-sin.md deleted file mode 100644 index 31ea11b57..000000000 --- a/.changeset/tricky-mangos-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': minor ---- - -updates the multi chain selection prompt by adding search functionality and an optional confirmation prompt for the current selection diff --git a/.changeset/wise-camels-repair.md b/.changeset/wise-camels-repair.md deleted file mode 100644 index 7cde52ed6..000000000 --- a/.changeset/wise-camels-repair.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Set transaction overrides and add 10% gas limit buffer when sending message through HyperlaneCore. diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index 01d7e99ae..dbffd611f 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,19 @@ # @hyperlane-xyz/core +## 5.5.0 + +### Minor Changes + +- 72c23c0d6: Added PRECISION and rateUpdateNonce to ensure compatibility of HypERC4626 + +### Patch Changes + +- c9085afd9: Patched OPL2ToL1Ism to check for correct messageId for external call in verify +- ec6b874b1: Added nonce to HypERC4626 +- Updated dependencies [f1712deb7] +- Updated dependencies [29341950e] + - @hyperlane-xyz/utils@5.6.0 + ## 5.4.1 ### Patch Changes diff --git a/solidity/contracts/PackageVersioned.sol b/solidity/contracts/PackageVersioned.sol index f0d43b725..eb57706c1 100644 --- a/solidity/contracts/PackageVersioned.sol +++ b/solidity/contracts/PackageVersioned.sol @@ -7,5 +7,5 @@ pragma solidity >=0.6.11; **/ abstract contract PackageVersioned { // GENERATED CODE - DO NOT EDIT - string public constant PACKAGE_VERSION = "5.4.1"; + string public constant PACKAGE_VERSION = "5.5.0"; } diff --git a/solidity/package.json b/solidity/package.json index 7fb78e878..78c42ca78 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.4.1", + "version": "5.5.0", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.5.0", + "@hyperlane-xyz/utils": "5.6.0", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index 2f082f6b2..6ec43d13c 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/ccip-server +## 5.6.0 + ## 5.5.0 ## 5.4.0 diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index c58df422c..457654431 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.5.0", + "version": "5.6.0", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index 517b7ebe1..1cd6506a1 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,38 @@ # @hyperlane-xyz/cli +## 5.6.0 + +### Minor Changes + +- 41035aac8: Add strategyUrl detect and validation in the beginning of `warp apply` + Remove yaml transactions print from `warp apply` +- 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation +- 32d0a67c2: Adds the warp check command to compare warp routes config files with on chain warp route deployments +- 3662297fc: Add prompt in `warp init` command to choose if a trusted relayer should be used instead of making the choice by default for the user and enable the `--yes` flag to default to a trusted ISM +- b1ff48bd1: Add rebasing yield route support into CLI/SDK +- d41aa6928: Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod +- c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. +- a4d5d692f: Update `warp apply` such that it updates in place AND extends in a single call +- 01e7070eb: updates the multi chain selection prompt by adding search functionality and an optional confirmation prompt for the current selection + +### Patch Changes + +- e89f9e35d: Update registry to v4.7.0 +- Updated dependencies [f1712deb7] +- Updated dependencies [46044a2e9] +- Updated dependencies [02a5b92ba] +- Updated dependencies [29341950e] +- Updated dependencies [8001bbbd6] +- Updated dependencies [32d0a67c2] +- Updated dependencies [b1ff48bd1] +- Updated dependencies [d41aa6928] +- Updated dependencies [c3e9268f1] +- Updated dependencies [7d7bcc1a3] +- Updated dependencies [7f3e0669d] +- Updated dependencies [2317eca3c] + - @hyperlane-xyz/utils@5.6.0 + - @hyperlane-xyz/sdk@5.6.0 + ## 5.5.0 ### Patch Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index a014c8bbc..ab516e294 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.5.0", + "version": "5.6.0", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.5.0", - "@hyperlane-xyz/utils": "5.5.0", + "@hyperlane-xyz/sdk": "5.6.0", + "@hyperlane-xyz/utils": "5.6.0", "@inquirer/prompts": "^3.0.0", "ansi-escapes": "^7.0.0", "asn1.js": "^5.4.1", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index ce5c04eb3..d4a8ed991 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.5.0'; +export const VERSION = '5.6.0'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md index a22fdc8ab..a71264e35 100644 --- a/typescript/github-proxy/CHANGELOG.md +++ b/typescript/github-proxy/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/github-proxy +## 5.6.0 + ## 5.5.0 ## 5.4.0 diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index cefc3c0dc..d8173c30d 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.5.0", + "version": "5.6.0", "private": true, "scripts": { "deploy": "wrangler deploy", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index aac142144..1d2f1535b 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,27 @@ # @hyperlane-xyz/helloworld +## 5.6.0 + +### Patch Changes + +- e89f9e35d: Update registry to v4.7.0 +- Updated dependencies [46044a2e9] +- Updated dependencies [02a5b92ba] +- Updated dependencies [29341950e] +- Updated dependencies [8001bbbd6] +- Updated dependencies [32d0a67c2] +- Updated dependencies [c9085afd9] +- Updated dependencies [b1ff48bd1] +- Updated dependencies [d41aa6928] +- Updated dependencies [ec6b874b1] +- Updated dependencies [c3e9268f1] +- Updated dependencies [72c23c0d6] +- Updated dependencies [7d7bcc1a3] +- Updated dependencies [7f3e0669d] +- Updated dependencies [2317eca3c] + - @hyperlane-xyz/sdk@5.6.0 + - @hyperlane-xyz/core@5.5.0 + ## 5.5.0 ### Patch Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index ca2d79f60..927647d06 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.5.0", + "version": "5.6.0", "dependencies": { - "@hyperlane-xyz/core": "5.4.1", + "@hyperlane-xyz/core": "5.5.0", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.5.0", + "@hyperlane-xyz/sdk": "5.6.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index bd6476484..3b623135c 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,31 @@ # @hyperlane-xyz/infra +## 5.6.0 + +### Minor Changes + +- b3495b205: Updates the warpIds for Renzo's latest deployment to Sei and Taiko to be used by the Checker +- c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. + +### Patch Changes + +- Updated dependencies [f1712deb7] +- Updated dependencies [46044a2e9] +- Updated dependencies [02a5b92ba] +- Updated dependencies [29341950e] +- Updated dependencies [8001bbbd6] +- Updated dependencies [32d0a67c2] +- Updated dependencies [b1ff48bd1] +- Updated dependencies [e89f9e35d] +- Updated dependencies [d41aa6928] +- Updated dependencies [c3e9268f1] +- Updated dependencies [7d7bcc1a3] +- Updated dependencies [7f3e0669d] +- Updated dependencies [2317eca3c] + - @hyperlane-xyz/utils@5.6.0 + - @hyperlane-xyz/sdk@5.6.0 + - @hyperlane-xyz/helloworld@5.6.0 + ## 5.5.0 ### Patch Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index d49058100..9d1d090c5 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.5.0", + "version": "5.6.0", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.5.0", + "@hyperlane-xyz/helloworld": "5.6.0", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.5.0", - "@hyperlane-xyz/utils": "5.5.0", + "@hyperlane-xyz/sdk": "5.6.0", + "@hyperlane-xyz/utils": "5.6.0", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index 058f6b817..0cec012ff 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,31 @@ # @hyperlane-xyz/sdk +## 5.6.0 + +### Minor Changes + +- 46044a2e9: Deploy to odysseytestnet +- 02a5b92ba: Enroll new validators. Add tx overrides when deploying ICA accounts. Core checker now surfaces owner violations for defaultHook and requiredHook. App checker temporarily ignores bytecode mismatch violations. +- 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation +- 8001bbbd6: Add override to some transactions to fix warp apply +- 32d0a67c2: Adds the warp check command to compare warp routes config files with on chain warp route deployments +- b1ff48bd1: Add rebasing yield route support into CLI/SDK +- d41aa6928: Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod +- c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block. +- 7d7bcc1a3: Add deployments for mainnets: flow, metall2, polynomial + +### Patch Changes + +- 7f3e0669d: Fix filtering non-evm addresses in appFromAddressesMapHelper +- 2317eca3c: Set transaction overrides and add 10% gas limit buffer when sending message through HyperlaneCore. +- Updated dependencies [f1712deb7] +- Updated dependencies [29341950e] +- Updated dependencies [c9085afd9] +- Updated dependencies [ec6b874b1] +- Updated dependencies [72c23c0d6] + - @hyperlane-xyz/utils@5.6.0 + - @hyperlane-xyz/core@5.5.0 + ## 5.5.0 ### Minor Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 6290277c8..1a5e86aa8 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.5.0", + "version": "5.6.0", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.4.1", - "@hyperlane-xyz/utils": "5.5.0", + "@hyperlane-xyz/core": "5.5.0", + "@hyperlane-xyz/utils": "5.6.0", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index a9252e563..e22dca07a 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @hyperlane-xyz/utils +## 5.6.0 + +### Minor Changes + +- 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation + +### Patch Changes + +- f1712deb7: Fix objMerge implementation + ## 5.5.0 ### Minor Changes diff --git a/typescript/utils/package.json b/typescript/utils/package.json index 83c8ed9c3..9baa234bf 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.5.0", + "version": "5.6.0", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index 8e5869427..e4698dd65 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,25 @@ # @hyperlane-xyz/widgets +## 5.6.0 + +### Patch Changes + +- e89f9e35d: Update registry to v4.7.0 +- Updated dependencies [f1712deb7] +- Updated dependencies [46044a2e9] +- Updated dependencies [02a5b92ba] +- Updated dependencies [29341950e] +- Updated dependencies [8001bbbd6] +- Updated dependencies [32d0a67c2] +- Updated dependencies [b1ff48bd1] +- Updated dependencies [d41aa6928] +- Updated dependencies [c3e9268f1] +- Updated dependencies [7d7bcc1a3] +- Updated dependencies [7f3e0669d] +- Updated dependencies [2317eca3c] + - @hyperlane-xyz/utils@5.6.0 + - @hyperlane-xyz/sdk@5.6.0 + ## 5.5.0 ### Minor Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 2e0177246..031a87479 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,15 +1,15 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.5.0", + "version": "5.6.0", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@headlessui/react": "^2.1.8", - "@hyperlane-xyz/sdk": "5.5.0", - "@hyperlane-xyz/utils": "5.5.0", + "@hyperlane-xyz/sdk": "5.6.0", + "@hyperlane-xyz/utils": "5.6.0", "clsx": "^2.1.1", "react-tooltip": "^5.28.0" }, diff --git a/yarn.lock b/yarn.lock index ebfca2e5c..556803a51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7824,8 +7824,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.5.0" - "@hyperlane-xyz/utils": "npm:5.5.0" + "@hyperlane-xyz/sdk": "npm:5.6.0" + "@hyperlane-xyz/utils": "npm:5.6.0" "@inquirer/prompts": "npm:^3.0.0" "@types/chai-as-promised": "npm:^8" "@types/mocha": "npm:^10.0.1" @@ -7858,13 +7858,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.4.1, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.5.0, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.5.0" + "@hyperlane-xyz/utils": "npm:5.6.0" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7915,13 +7915,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.5.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.6.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.4.1" + "@hyperlane-xyz/core": "npm:5.5.0" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.5.0" + "@hyperlane-xyz/sdk": "npm:5.6.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7968,10 +7968,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.5.0" + "@hyperlane-xyz/helloworld": "npm:5.6.0" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.5.0" - "@hyperlane-xyz/utils": "npm:5.5.0" + "@hyperlane-xyz/sdk": "npm:5.6.0" + "@hyperlane-xyz/utils": "npm:5.6.0" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -8037,7 +8037,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.5.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.6.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -8045,8 +8045,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.4.1" - "@hyperlane-xyz/utils": "npm:5.5.0" + "@hyperlane-xyz/core": "npm:5.5.0" + "@hyperlane-xyz/utils": "npm:5.6.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -8087,7 +8087,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.5.0, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.6.0, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -8113,8 +8113,8 @@ __metadata: dependencies: "@headlessui/react": "npm:^2.1.8" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.5.0" - "@hyperlane-xyz/utils": "npm:5.5.0" + "@hyperlane-xyz/sdk": "npm:5.6.0" + "@hyperlane-xyz/utils": "npm:5.6.0" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From 8cc0d9a4ae5dac32864eafff09b292ba31853b67 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Thu, 24 Oct 2024 00:31:56 +0530 Subject: [PATCH 181/224] feat(contracts): add wrapped HypERC4626 for ease of defi use (#4563) ### Description ### Drive-by changes None ### Related issues - closes https://github.com/chainlight-io/2024-08-hyperlane/issues/7 ### Backward compatibility Yes ### Testing Unit --- .changeset/itchy-bananas-know.md | 5 + .changeset/shiny-baboons-hunt.md | 5 + .../token/extensions/WHypERC4626.sol | 113 +++++++++++++++++ solidity/test/token/WHypERC4626.t.sol | 116 ++++++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 .changeset/itchy-bananas-know.md create mode 100644 .changeset/shiny-baboons-hunt.md create mode 100644 solidity/contracts/token/extensions/WHypERC4626.sol create mode 100644 solidity/test/token/WHypERC4626.t.sol diff --git a/.changeset/itchy-bananas-know.md b/.changeset/itchy-bananas-know.md new file mode 100644 index 000000000..188981756 --- /dev/null +++ b/.changeset/itchy-bananas-know.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': patch +--- + +Add wrapped HypERC4626 for easy defi use diff --git a/.changeset/shiny-baboons-hunt.md b/.changeset/shiny-baboons-hunt.md new file mode 100644 index 000000000..ef302d93f --- /dev/null +++ b/.changeset/shiny-baboons-hunt.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': minor +--- + +Added WHypERC4626 as a wrapper for rebasing HypERC4626 diff --git a/solidity/contracts/token/extensions/WHypERC4626.sol b/solidity/contracts/token/extensions/WHypERC4626.sol new file mode 100644 index 000000000..08cb59732 --- /dev/null +++ b/solidity/contracts/token/extensions/WHypERC4626.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.0; + +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {HypERC4626} from "./HypERC4626.sol"; +import {PackageVersioned} from "../../PackageVersioned.sol"; + +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +/** + * @title WHypERC4626 + * @author Abacus Works + * @notice A wrapper for HypERC4626 that allows for wrapping and unwrapping of underlying rebasing tokens + */ +contract WHypERC4626 is ERC20, PackageVersioned { + HypERC4626 public immutable underlying; + + constructor( + HypERC4626 _underlying, + string memory name, + string memory symbol + ) ERC20(name, symbol) { + underlying = _underlying; + } + + /* + * @notice Wraps an amount of underlying tokens into wrapped tokens + * @param _underlyingAmount The amount of underlying tokens to wrap + * @return The amount of wrapped tokens + */ + function wrap(uint256 _underlyingAmount) external returns (uint256) { + require( + _underlyingAmount > 0, + "WHypERC4626: wrap amount must be greater than 0" + ); + uint256 wrappedAmount = underlying.assetsToShares(_underlyingAmount); + _mint(msg.sender, wrappedAmount); + underlying.transferFrom(msg.sender, address(this), _underlyingAmount); + return wrappedAmount; + } + + /* + * @notice Unwraps an amount of wrapped tokens into underlying tokens + * @param _wrappedAmount The amount of wrapped tokens to unwrap + * @return The amount of underlying tokens + */ + function unwrap(uint256 _wrappedAmount) external returns (uint256) { + require( + _wrappedAmount > 0, + "WHypERC4626: unwrap amount must be greater than 0" + ); + uint256 underlyingAmount = underlying.sharesToAssets(_wrappedAmount); + _burn(msg.sender, _wrappedAmount); + underlying.transfer(msg.sender, underlyingAmount); + return underlyingAmount; + } + + /* + * @notice Gets the amount of wrapped tokens for a given amount of underlying tokens + * @param _underlyingAmount The amount of underlying tokens + * @return The amount of wrapped tokens + */ + function getWrappedAmount( + uint256 _underlyingAmount + ) external view returns (uint256) { + return underlying.assetsToShares(_underlyingAmount); + } + + /* + * @notice Gets the amount of underlying tokens for a given amount of wrapped tokens + * @param _wrappedAmount The amount of wrapped tokens + * @return The amount of underlying tokens + */ + function getUnderlyingAmount( + uint256 _wrappedAmount + ) external view returns (uint256) { + return underlying.sharesToAssets(_wrappedAmount); + } + + /* + * @notice Gets the amount of wrapped tokens for 1 unit of underlying tokens + * @return The amount of wrapped tokens + */ + function wrappedPerUnderlying() external view returns (uint256) { + return underlying.assetsToShares(1 * 10 ** underlying.decimals()); + } + + /* + * @notice Gets the amount of underlying tokens for 1 unit of wrapped tokens + * @return The amount of underlying tokens + */ + function underlyingPerWrapped() external view returns (uint256) { + return underlying.sharesToAssets(1 * 10 ** decimals()); + } + + /* + * @notice Gets the decimals of the wrapped token + * @return The decimals of the wrapped token + */ + function decimals() public view override returns (uint8) { + return underlying.decimals(); + } +} diff --git a/solidity/test/token/WHypERC4626.t.sol b/solidity/test/token/WHypERC4626.t.sol new file mode 100644 index 000000000..5684eeee2 --- /dev/null +++ b/solidity/test/token/WHypERC4626.t.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.13; + +import {Test} from "forge-std/Test.sol"; +import {MockMailbox} from "../../contracts/mock/MockMailbox.sol"; +import {WHypERC4626} from "../../contracts/token/extensions/WHypERC4626.sol"; +import {HypERC4626} from "../../contracts/token/extensions/HypERC4626.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract MockHypERC4626 is HypERC4626 { + constructor(address _mailbox) HypERC4626(18, _mailbox, 2) {} + + function mint(address to, uint256 amount) external { + _mint(to, amount); + } +} + +contract WHypERC4626Test is Test { + WHypERC4626 public wHypERC4626; + MockHypERC4626 public underlyingToken; + address public alice = address(0x1); + address public bob = address(0x2); + + function setUp() public { + MockMailbox mailbox = new MockMailbox(1); + underlyingToken = new MockHypERC4626(address(mailbox)); + wHypERC4626 = new WHypERC4626( + underlyingToken, + "Wrapped Rebasing Token", + "WRT" + ); + + underlyingToken.mint(alice, 1000 * 10 ** 18); + underlyingToken.mint(bob, 1000 * 10 ** 18); + } + + function test_wrap() public { + uint256 amount = 100 * 10 ** 18; + + vm.startPrank(alice); + underlyingToken.approve(address(wHypERC4626), amount); + uint256 wrappedAmount = wHypERC4626.wrap(amount); + + assertEq(wHypERC4626.balanceOf(alice), wrappedAmount); + assertEq(underlyingToken.balanceOf(alice), 900 * 10 ** 18); + vm.stopPrank(); + } + + function test_wrap_revertsWhen_zeroAmount() public { + vm.startPrank(alice); + underlyingToken.approve(address(wHypERC4626), 0); + vm.expectRevert("WHypERC4626: wrap amount must be greater than 0"); + wHypERC4626.wrap(0); + vm.stopPrank(); + } + + function test_unwrap() public { + uint256 amount = 100 * 10 ** 18; + + vm.startPrank(alice); + underlyingToken.approve(address(wHypERC4626), amount); + uint256 wrappedAmount = wHypERC4626.wrap(amount); + + uint256 unwrappedAmount = wHypERC4626.unwrap(wrappedAmount); + + assertEq(wHypERC4626.balanceOf(alice), 0); + assertEq(underlyingToken.balanceOf(alice), 1000 * 10 ** 18); + assertEq(unwrappedAmount, amount); + vm.stopPrank(); + } + + function test_unwrap_revertsWhen_zeroAmount() public { + vm.startPrank(alice); + vm.expectRevert("WHypERC4626: unwrap amount must be greater than 0"); + wHypERC4626.unwrap(0); + vm.stopPrank(); + } + + function test_getWrappedAmount() public view { + uint256 amount = 100 * 10 ** 18; + uint256 wrappedAmount = wHypERC4626.getWrappedAmount(amount); + + assertEq(wrappedAmount, underlyingToken.assetsToShares(amount)); + } + + function test_getUnderlyingAmount() public view { + uint256 amount = 100 * 10 ** 18; + uint256 underlyingAmount = wHypERC4626.getUnderlyingAmount(amount); + + assertEq(underlyingAmount, underlyingToken.sharesToAssets(amount)); + } + + function test_wrappedPerUnderlying() public view { + uint256 wrappedPerUnderlying = wHypERC4626.wrappedPerUnderlying(); + + assertEq( + wrappedPerUnderlying, + underlyingToken.assetsToShares(1 * 10 ** underlyingToken.decimals()) + ); + } + + function test_underlyingPerWrapped() public view { + uint256 underlyingPerWrapped = wHypERC4626.underlyingPerWrapped(); + + assertEq( + underlyingPerWrapped, + underlyingToken.sharesToAssets(1 * 10 ** underlyingToken.decimals()) + ); + } + + function test_decimals() public view { + uint8 decimals = wHypERC4626.decimals(); + + assertEq(decimals, underlyingToken.decimals()); + } +} From c55257cf5f897e0656e62d567ab6474321bc1906 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Thu, 24 Oct 2024 00:56:53 +0530 Subject: [PATCH 182/224] fix(contracts): minor token related changes (#4580) ### Description Minor token related changes like adding custom hook to 4626 collateral, checking for ERC20 as valid contract in HypERC20Collateral, etc. ### Drive-by changes check for overflow in bytes32ToAddress ### Related issues - partly fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/14 ### Backward compatibility Yes ### Testing Unit tests --- .changeset/perfect-dryers-destroy.md | 5 ++ solidity/contracts/client/GasRouter.sol | 16 +++++ solidity/contracts/libs/TypeCasts.sol | 4 ++ .../contracts/token/HypERC20Collateral.sol | 16 +++++ .../token/extensions/HypERC4626Collateral.sol | 16 ++--- solidity/test/GasRouter.t.sol | 2 + solidity/test/isms/RateLimitedIsm.t.sol | 2 +- solidity/test/token/HypERC20.t.sol | 5 ++ solidity/test/token/HypERC4626Test.t.sol | 68 +++++++++++++++---- 9 files changed, 110 insertions(+), 24 deletions(-) create mode 100644 .changeset/perfect-dryers-destroy.md diff --git a/.changeset/perfect-dryers-destroy.md b/.changeset/perfect-dryers-destroy.md new file mode 100644 index 000000000..f9a906ef1 --- /dev/null +++ b/.changeset/perfect-dryers-destroy.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': minor +--- + +Minor token related changes like adding custom hook to 4626 collateral, checking for ERC20 as valid contract in HypERC20Collateral, etc. diff --git a/solidity/contracts/client/GasRouter.sol b/solidity/contracts/client/GasRouter.sol index c5f9efd1c..f14d0b642 100644 --- a/solidity/contracts/client/GasRouter.sol +++ b/solidity/contracts/client/GasRouter.sol @@ -1,10 +1,25 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +// ============ Internal Imports ============ import {Router} from "./Router.sol"; import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol"; abstract contract GasRouter is Router { + event GasSet(uint32 domain, uint256 gas); + // ============ Mutable Storage ============ mapping(uint32 => uint256) public destinationGas; @@ -56,6 +71,7 @@ abstract contract GasRouter is Router { function _setDestinationGas(uint32 domain, uint256 gas) internal { destinationGas[domain] = gas; + emit GasSet(domain, gas); } function _GasRouter_dispatch( diff --git a/solidity/contracts/libs/TypeCasts.sol b/solidity/contracts/libs/TypeCasts.sol index 4440f63da..d156e9850 100644 --- a/solidity/contracts/libs/TypeCasts.sol +++ b/solidity/contracts/libs/TypeCasts.sol @@ -9,6 +9,10 @@ library TypeCasts { // alignment preserving cast function bytes32ToAddress(bytes32 _buf) internal pure returns (address) { + require( + uint256(_buf) <= uint256(type(uint160).max), + "TypeCasts: bytes32ToAddress overflow" + ); return address(uint160(uint256(_buf))); } } diff --git a/solidity/contracts/token/HypERC20Collateral.sol b/solidity/contracts/token/HypERC20Collateral.sol index 858a3140b..69b137e75 100644 --- a/solidity/contracts/token/HypERC20Collateral.sol +++ b/solidity/contracts/token/HypERC20Collateral.sol @@ -1,10 +1,25 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0; +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +// ============ Internal Imports ============ import {TokenRouter} from "./libs/TokenRouter.sol"; import {TokenMessage} from "./libs/TokenMessage.sol"; import {MailboxClient} from "../client/MailboxClient.sol"; +// ============ External Imports ============ +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -22,6 +37,7 @@ contract HypERC20Collateral is TokenRouter { * @param erc20 Address of the token to keep as collateral */ constructor(address erc20, address _mailbox) TokenRouter(_mailbox) { + require(Address.isContract(erc20), "HypERC20Collateral: invalid token"); wrappedToken = IERC20(erc20); } diff --git a/solidity/contracts/token/extensions/HypERC4626Collateral.sol b/solidity/contracts/token/extensions/HypERC4626Collateral.sol index 87528b109..1f164563e 100644 --- a/solidity/contracts/token/extensions/HypERC4626Collateral.sol +++ b/solidity/contracts/token/extensions/HypERC4626Collateral.sol @@ -66,11 +66,7 @@ contract HypERC4626Collateral is HypERC20Collateral { // Can't override _transferFromSender only because we need to pass shares in the token message _transferFromSender(_amount); uint256 _shares = _depositIntoVault(_amount); - uint256 _exchangeRate = PRECISION.mulDiv( - vault.totalAssets(), - vault.totalSupply(), - Math.Rounding.Down - ); + uint256 _exchangeRate = vault.convertToAssets(PRECISION); rateUpdateNonce++; bytes memory _tokenMetadata = abi.encode( @@ -121,15 +117,19 @@ contract HypERC4626Collateral is HypERC20Collateral { * @dev Update the exchange rate on the synthetic token by accounting for additional yield accrued to the underlying vault * @param _destinationDomain domain of the vault */ - function rebase(uint32 _destinationDomain) public payable { + function rebase( + uint32 _destinationDomain, + bytes calldata _hookMetadata, + address _hook + ) public payable { // force a rebase with an empty transfer to 0x1 _transferRemote( _destinationDomain, NULL_RECIPIENT, 0, msg.value, - bytes(""), - address(0) + _hookMetadata, + _hook ); } } diff --git a/solidity/test/GasRouter.t.sol b/solidity/test/GasRouter.t.sol index aaf73b2a3..becd43cf3 100644 --- a/solidity/test/GasRouter.t.sol +++ b/solidity/test/GasRouter.t.sol @@ -68,6 +68,8 @@ contract GasRouterTest is Test { } function testSetDestinationGas(uint256 gas) public { + vm.expectEmit(true, true, true, true); + emit GasRouter.GasSet(originDomain, gas); setDestinationGas(remoteRouter, originDomain, gas); assertEq(remoteRouter.destinationGas(originDomain), gas); diff --git a/solidity/test/isms/RateLimitedIsm.t.sol b/solidity/test/isms/RateLimitedIsm.t.sol index 7c4b76356..481bbaa49 100644 --- a/solidity/test/isms/RateLimitedIsm.t.sol +++ b/solidity/test/isms/RateLimitedIsm.t.sol @@ -75,7 +75,7 @@ contract RateLimitedIsmTest is Test { TokenMessage.format(bytes32(""), _amount, bytes("")) ); - vm.expectRevert("InvalidRecipient"); + vm.expectRevert("TypeCasts: bytes32ToAddress overflow"); rateLimitedIsm.verify(bytes(""), _message); } diff --git a/solidity/test/token/HypERC20.t.sol b/solidity/test/token/HypERC20.t.sol index 9c068b239..c3b7da74c 100644 --- a/solidity/test/token/HypERC20.t.sol +++ b/solidity/test/token/HypERC20.t.sol @@ -406,6 +406,11 @@ contract HypERC20CollateralTest is HypTokenTest { _enrollRemoteTokenRouter(); } + function test_constructor_revert_ifInvalidToken() public { + vm.expectRevert("HypERC20Collateral: invalid token"); + new HypERC20Collateral(address(0), address(localMailbox)); + } + function testInitialize_revert_ifAlreadyInitialized() public {} function testRemoteTransfer() public { diff --git a/solidity/test/token/HypERC4626Test.t.sol b/solidity/test/token/HypERC4626Test.t.sol index 338d39b75..ef9243148 100644 --- a/solidity/test/token/HypERC4626Test.t.sol +++ b/solidity/test/token/HypERC4626Test.t.sol @@ -24,7 +24,9 @@ import {MockMailbox} from "../../contracts/mock/MockMailbox.sol"; import {HypERC20} from "../../contracts/token/HypERC20.sol"; import {HypERC4626Collateral} from "../../contracts/token/extensions/HypERC4626Collateral.sol"; import {HypERC4626} from "../../contracts/token/extensions/HypERC4626.sol"; +import {StandardHookMetadata} from "../../contracts/hooks/libs/StandardHookMetadata.sol"; import "../../contracts/test/ERC4626/ERC4626Test.sol"; +import {ProtocolFee} from "../../contracts/hooks/ProtocolFee.sol"; contract HypERC4626CollateralTest is HypTokenTest { using TypeCasts for address; @@ -124,14 +126,38 @@ contract HypERC4626CollateralTest is HypTokenTest { _accrueYield(); - localRebasingToken.rebase(DESTINATION); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); remoteMailbox.processNextInboundMessage(); - assertEq( + assertApproxEqRelDecimal( remoteToken.balanceOf(BOB), - transferAmount + _discountedYield() + transferAmount + _discountedYield(), + 1e14, + 0 ); } + function testRemoteTransfer_rebaseWithCustomHook() public { + _performRemoteTransferWithoutExpectation(0, transferAmount); + assertEq(remoteToken.balanceOf(BOB), transferAmount); + + _accrueYield(); + + uint256 FEE = 1e18; + ProtocolFee customHook = new ProtocolFee( + FEE, + FEE, + address(this), + address(this) + ); + + localRebasingToken.rebase{value: FEE}( + DESTINATION, + StandardHookMetadata.overrideMsgValue(FEE), + address(customHook) + ); + assertEq(address(customHook).balance, FEE); + } + function testRebaseWithTransfer() public { _performRemoteTransferWithoutExpectation(0, transferAmount); assertEq(remoteToken.balanceOf(BOB), transferAmount); @@ -275,7 +301,7 @@ contract HypERC4626CollateralTest is HypTokenTest { _accrueYield(); - localRebasingToken.rebase(DESTINATION); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); remoteMailbox.processNextInboundMessage(); // Use balance here since it might be off by <1bp @@ -314,7 +340,7 @@ contract HypERC4626CollateralTest is HypTokenTest { _accrueYield(); _accrueYield(); // earning 2x yield to be split - localRebasingToken.rebase(DESTINATION); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); vm.prank(CAROL); remoteToken.transferRemote( @@ -352,7 +378,7 @@ contract HypERC4626CollateralTest is HypTokenTest { // decrease collateral in vault by 10% uint256 drawdown = 5e18; primaryToken.burnFrom(address(vault), drawdown); - localRebasingToken.rebase(DESTINATION); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); remoteMailbox.processNextInboundMessage(); // Use balance here since it might be off by <1bp @@ -378,7 +404,7 @@ contract HypERC4626CollateralTest is HypTokenTest { _accrueYield(); - localRebasingToken.rebase(DESTINATION); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); remoteMailbox.processNextInboundMessage(); vm.prank(BOB); @@ -389,13 +415,23 @@ contract HypERC4626CollateralTest is HypTokenTest { ); peerMailbox.processNextInboundMessage(); - assertEq(remoteRebasingToken.exchangeRate(), 1045e7); // 5 * 0.9 = 4.5% yield + assertApproxEqRelDecimal( + remoteRebasingToken.exchangeRate(), + 1045e7, + 1e14, + 0 + ); // 5 * 0.9 = 4.5% yield assertEq(peerRebasingToken.exchangeRate(), 1e10); // assertingthat transfers by the synthetic variant don't impact the exchang rate - localRebasingToken.rebase(PEER_DESTINATION); + localRebasingToken.rebase(PEER_DESTINATION, bytes(""), address(0)); peerMailbox.processNextInboundMessage(); - assertEq(peerRebasingToken.exchangeRate(), 1045e7); // asserting that the exchange rate is set finally by the collateral variant + assertApproxEqRelDecimal( + peerRebasingToken.exchangeRate(), + 1045e7, + 1e14, + 0 + ); // asserting that the exchange rate is set finally by the collateral variant } function test_cyclicTransfers() public { @@ -405,7 +441,7 @@ contract HypERC4626CollateralTest is HypTokenTest { _accrueYield(); - localRebasingToken.rebase(DESTINATION); // yield is added + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); // yield is added remoteMailbox.processNextInboundMessage(); // BOB: remote -> peer(BOB) (yield is leftover) @@ -417,7 +453,7 @@ contract HypERC4626CollateralTest is HypTokenTest { ); peerMailbox.processNextInboundMessage(); - localRebasingToken.rebase(PEER_DESTINATION); + localRebasingToken.rebase(PEER_DESTINATION, bytes(""), address(0)); peerMailbox.processNextInboundMessage(); // BOB: peer -> local(CAROL) @@ -457,11 +493,13 @@ contract HypERC4626CollateralTest is HypTokenTest { _accrueYield(); - localRebasingToken.rebase(DESTINATION); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); remoteMailbox.processNextInboundMessage(); - assertEq( + assertApproxEqRelDecimal( remoteToken.balanceOf(BOB), - transferAmount + _discountedYield() + transferAmount + _discountedYield(), + 1e14, + 0 ); vm.prank(address(localMailbox)); From 29bf1d8c73ee82f1b6a3840a33a8236383192976 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:31:11 +0100 Subject: [PATCH 183/224] chore: set finalized reorgPeriod (#4741) ### Description - chore: set finalized reorgPeriod - update reorg period ### Drive-by changes na ### Related issues na ### Backward compatibility agents are already updated ### Testing manual Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .registryrc | 2 +- rust/main/config/mainnet_config.json | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.registryrc b/.registryrc index 862c96776..ab4e5304b 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -dee58183e51f4eb43e84dbac0e595a4b389dbe80 +5b4334afa6ff242c9eed872a5f666fcc7f880e27 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index a562cd84e..9d32c7578 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -429,7 +429,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 15 + "reorgPeriod": "finalized" }, "chainId": 56, "deployer": { @@ -1981,7 +1981,7 @@ "blocks": { "confirmations": 2, "estimateBlockTime": 12, - "reorgPeriod": 10 + "reorgPeriod": "finalized" }, "chainId": 1284, "deployer": { @@ -2258,7 +2258,7 @@ "blocks": { "confirmations": 3, "estimateBlockTime": 2, - "reorgPeriod": 256 + "reorgPeriod": "finalized" }, "chainId": 137, "deployer": { @@ -2912,7 +2912,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 6, - "reorgPeriod": 10 + "reorgPeriod": "finalized" }, "chainId": 5845, "deployer": { @@ -3446,7 +3446,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 13, - "reorgPeriod": 32 + "reorgPeriod": "finalized" }, "chainId": 592, "deployer": { @@ -3924,7 +3924,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 5 + "reorgPeriod": "finalized" }, "chainId": 109, "deployer": { @@ -4187,7 +4187,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 9 + "reorgPeriod": "finalized" }, "chainId": 88888, "deployer": { From a64af8be9a76120d0cfc727bb70660fa07e70cce Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:57:23 +0100 Subject: [PATCH 184/224] fix: revert chiliz reorg period back to 9 (#4744) ### Description fix: revert chiliz reorg period back to 9 ### Drive-by changes na ### Related issues na ### Backward compatibility ye ### Testing relayer sad times - [context](https://discord.com/channels/935678348330434570/1298963431743029359/1298965217757102100) --- .registryrc | 2 +- rust/main/config/mainnet_config.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.registryrc b/.registryrc index ab4e5304b..a694b325b 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -5b4334afa6ff242c9eed872a5f666fcc7f880e27 +65b3c54ede7bf2b56280b913b8ed57bb08f52a36 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index 9d32c7578..7f147b6e0 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -4187,7 +4187,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": "finalized" + "reorgPeriod": 9 }, "chainId": 88888, "deployer": { From ffbe1dd82e2452dbc111b6fb469a34fb870da8f1 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Thu, 24 Oct 2024 15:21:55 +0100 Subject: [PATCH 185/224] feat: Make HyperlaneProvider to request block by height, not by hash (#4727) ### Description Make HyperlaneProvider to request block by height, not by hash. Since it is hard to find a block by hash for Solana, we switch to use block height. We have to do it for all type of chains since we need to change signature of chain-agnostic method ### Drive-by changes * Small method rename ### Related issues - Contributes into https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4272 ### Backward compatibility Yes ### Testing Manual run of Scraper for Ethereum and Neutron chains. --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../agents/scraper/src/chain_scraper/mod.rs | 32 +++++---- .../src/providers/cosmos/provider.rs | 33 ++++------ .../src/rpc_clients/provider.rs | 65 +++++++++++++------ .../chains/hyperlane-fuel/src/provider.rs | 35 ++++++---- .../chains/hyperlane-sealevel/src/error.rs | 3 + .../chains/hyperlane-sealevel/src/mailbox.rs | 2 +- .../chains/hyperlane-sealevel/src/provider.rs | 27 ++++++-- .../hyperlane-sealevel/src/rpc/client.rs | 25 +++++-- rust/main/hyperlane-core/src/error.rs | 3 - .../hyperlane-core/src/traits/provider.rs | 22 ++++--- .../main/hyperlane-core/src/types/block_id.rs | 17 +++++ rust/main/hyperlane-core/src/types/mod.rs | 2 + 12 files changed, 181 insertions(+), 85 deletions(-) create mode 100644 rust/main/hyperlane-core/src/types/block_id.rs diff --git a/rust/main/agents/scraper/src/chain_scraper/mod.rs b/rust/main/agents/scraper/src/chain_scraper/mod.rs index 71ddd84ef..c23df70a1 100644 --- a/rust/main/agents/scraper/src/chain_scraper/mod.rs +++ b/rust/main/agents/scraper/src/chain_scraper/mod.rs @@ -9,7 +9,7 @@ use async_trait::async_trait; use eyre::Result; use hyperlane_base::settings::IndexSettings; use hyperlane_core::{ - unwrap_or_none_result, BlockInfo, Delivery, HyperlaneDomain, HyperlaneLogStore, + unwrap_or_none_result, BlockId, BlockInfo, Delivery, HyperlaneDomain, HyperlaneLogStore, HyperlaneMessage, HyperlaneProvider, HyperlaneSequenceAwareIndexerStoreReader, HyperlaneWatermarkedLogStore, Indexed, InterchainGasPayment, LogMeta, H256, }; @@ -78,13 +78,13 @@ impl HyperlaneSqlDb { &self, log_meta: impl Iterator, ) -> Result> { - let block_hash_by_txn_hash: HashMap = log_meta + let block_id_by_txn_hash: HashMap = log_meta .map(|meta| { ( meta.transaction_id .try_into() .expect("256-bit transaction ids are the maximum supported at this time"), - meta.block_hash, + BlockId::new(meta.block_hash, meta.block_number), ) }) .collect(); @@ -92,16 +92,16 @@ impl HyperlaneSqlDb { // all blocks we care about // hash of block maps to the block id and timestamp let blocks: HashMap<_, _> = self - .ensure_blocks(block_hash_by_txn_hash.values().copied()) + .ensure_blocks(block_id_by_txn_hash.values().copied()) .await? .map(|block| (block.hash, block)) .collect(); trace!(?blocks, "Ensured blocks"); // We ensure transactions only from blocks which are inserted into database - let txn_hash_with_block_ids = block_hash_by_txn_hash + let txn_hash_with_block_ids = block_id_by_txn_hash .into_iter() - .filter_map(move |(txn, block)| blocks.get(&block).map(|b| (txn, b.id))) + .filter_map(move |(txn, block)| blocks.get(&block.hash).map(|b| (txn, b.id))) .map(|(txn_hash, block_id)| TxnWithBlockId { txn_hash, block_id }); let txns_with_ids = self.ensure_txns(txn_hash_with_block_ids).await?; @@ -195,11 +195,17 @@ impl HyperlaneSqlDb { /// this method. async fn ensure_blocks( &self, - block_hashes: impl Iterator, + block_ids: impl Iterator, ) -> Result> { + // Mapping from block hash to block ids (hash and height) + let block_hash_to_block_id_map: HashMap = + block_ids.map(|b| (b.hash, b)).collect(); + // Mapping of block hash to `BasicBlock` which contains database block id and block hash. - let mut blocks: HashMap> = - block_hashes.map(|b| (b, None)).collect(); + let mut blocks: HashMap> = block_hash_to_block_id_map + .keys() + .map(|hash| (*hash, None)) + .collect(); let db_blocks: Vec = if !blocks.is_empty() { // check database to see which blocks we already know and fetch their IDs @@ -230,10 +236,14 @@ impl HyperlaneSqlDb { for chunk in as_chunks(blocks_to_fetch, CHUNK_SIZE) { debug_assert!(!chunk.is_empty()); for (hash, block_info) in chunk { - let info = match self.provider.get_block_by_hash(hash).await { + // We should have block_id in this map for every hashes + let block_id = block_hash_to_block_id_map[hash]; + let block_height = block_id.height; + + let info = match self.provider.get_block_by_height(block_height).await { Ok(info) => info, Err(e) => { - warn!(?hash, ?e, "error fetching and parsing block"); + warn!(block_hash = ?hash, ?block_height, ?e, "error fetching and parsing block"); continue; } }; diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index 491f19776..ef0c15345 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -18,8 +18,8 @@ use tracing::{error, warn}; use crypto::decompress_public_key; use hyperlane_core::{ AccountAddressType, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, - ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, TxnInfo, TxnReceiptInfo, - H256, U256, + ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, HyperlaneProviderError, + TxnInfo, TxnReceiptInfo, H256, U256, }; use crate::grpc::{WasmGrpcProvider, WasmProvider}; @@ -367,33 +367,26 @@ impl HyperlaneChain for CosmosProvider { #[async_trait] impl HyperlaneProvider for CosmosProvider { - async fn get_block_by_hash(&self, hash: &H256) -> ChainResult { - let tendermint_hash = Hash::from_bytes(Algorithm::Sha256, hash.as_bytes()) - .expect("block hash should be of correct size"); - - let response = self.rpc_client.get_block_by_hash(tendermint_hash).await?; + async fn get_block_by_height(&self, height: u64) -> ChainResult { + let response = self.rpc_client.get_block(height as u32).await?; - let received_hash = H256::from_slice(response.block_id.hash.as_bytes()); + let block = response.block; + let block_height = block.header.height.value(); - if &received_hash != hash { - return Err(ChainCommunicationError::from_other_str( - &format!("received incorrect block, expected hash: {hash:?}, received hash: {received_hash:?}") - )); + if block_height != height { + Err(HyperlaneProviderError::IncorrectBlockByHeight( + height, + block_height, + ))? } - let block = response.block.ok_or_else(|| { - ChainCommunicationError::from_other_str(&format!( - "empty block info for block: {:?}", - hash - )) - })?; - + let hash = H256::from_slice(response.block_id.hash.as_bytes()); let time: OffsetDateTime = block.header.time.into(); let block_info = BlockInfo { hash: hash.to_owned(), timestamp: time.unix_timestamp() as u64, - number: block.header.height.value(), + number: block_height, }; Ok(block_info) diff --git a/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs index 8434a4de3..c8ef3d78c 100644 --- a/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs +++ b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs @@ -49,26 +49,49 @@ where { #[instrument(err, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn get_block_by_hash(&self, hash: &H256) -> ChainResult { - let block = get_with_retry_on_none(hash, |h| { - let eth_h256: ethers_core_types::H256 = h.into(); - self.provider.get_block(eth_h256) - }) + async fn get_block_by_height(&self, height: u64) -> ChainResult { + let block = get_with_retry_on_none( + &height, + |h| self.provider.get_block(*h), + |h| HyperlaneProviderError::CouldNotFindBlockByHeight(*h), + ) .await?; - Ok(BlockInfo { - hash: *hash, + + let block_height = block + .number + .ok_or(HyperlaneProviderError::CouldNotFindBlockByHeight(height))? + .as_u64(); + + if block_height != height { + Err(HyperlaneProviderError::IncorrectBlockByHeight( + height, + block_height, + ))?; + } + + let block_hash = block + .hash + .ok_or(HyperlaneProviderError::BlockWithoutHash(height))?; + + let block_info = BlockInfo { + hash: block_hash.into(), timestamp: block.timestamp.as_u64(), - number: block - .number - .ok_or(HyperlaneProviderError::BlockIsNotPartOfChainYet(*hash))? - .as_u64(), - }) + number: block_height, + }; + + Ok(block_info) } #[instrument(err, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult { - let txn = get_with_retry_on_none(hash, |h| self.provider.get_transaction(*h)).await?; + let txn = get_with_retry_on_none( + hash, + |h| self.provider.get_transaction(*h), + |h| HyperlaneProviderError::CouldNotFindTransactionByHash(*h), + ) + .await?; + let receipt = self .provider .get_transaction_receipt(*hash) @@ -193,22 +216,24 @@ impl BuildableWithProvider for HyperlaneProviderBuilder { /// Call a get function that returns a Result> and retry if the inner /// option is None. This can happen because the provider has not discovered the /// object we are looking for yet. -async fn get_with_retry_on_none(hash: &H256, get: F) -> ChainResult +async fn get_with_retry_on_none( + id: &I, + get: F, + not_found_error: N, +) -> ChainResult where - F: Fn(&H256) -> O, + F: Fn(&I) -> O, O: Future, E>>, E: std::error::Error + Send + Sync + 'static, + N: Fn(&I) -> HyperlaneProviderError, { for _ in 0..3 { - if let Some(t) = get(hash) - .await - .map_err(ChainCommunicationError::from_other)? - { + if let Some(t) = get(id).await.map_err(ChainCommunicationError::from_other)? { return Ok(t); } else { sleep(Duration::from_secs(5)).await; continue; }; } - Err(HyperlaneProviderError::CouldNotFindObjectByHash(*hash).into()) + Err(not_found_error(id).into()) } diff --git a/rust/main/chains/hyperlane-fuel/src/provider.rs b/rust/main/chains/hyperlane-fuel/src/provider.rs index e3836f141..a72f8a6c5 100644 --- a/rust/main/chains/hyperlane-fuel/src/provider.rs +++ b/rust/main/chains/hyperlane-fuel/src/provider.rs @@ -1,7 +1,6 @@ use std::{collections::HashMap, ops::Deref}; use async_trait::async_trait; - use fuels::{ client::{FuelClient, PageDirection, PaginationRequest}, prelude::Provider, @@ -13,13 +12,14 @@ use fuels::{ transaction::{Transaction, TransactionType}, transaction_response::TransactionResponse, tx_status::TxStatus, - Address, Bytes32, ContractId, + Address, BlockHeight, Bytes32, ContractId, }, }; use futures::future::join_all; use hyperlane_core::{ BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, - HyperlaneMessage, HyperlaneProvider, Indexed, LogMeta, TxnInfo, H256, H512, U256, + HyperlaneMessage, HyperlaneProvider, HyperlaneProviderError, Indexed, LogMeta, TxnInfo, H256, + H512, U256, }; use crate::{make_client, make_provider, prelude::FuelIntoH256, ConnectionConf}; @@ -285,19 +285,30 @@ impl HyperlaneChain for FuelProvider { impl HyperlaneProvider for FuelProvider { /// Used by scraper #[allow(clippy::clone_on_copy)] // TODO: `rustc` 1.80.1 clippy issue - async fn get_block_by_hash(&self, hash: &H256) -> ChainResult { - let block_res = self.provider.block(&hash.0.into()).await.map_err(|e| { - ChainCommunicationError::CustomError(format!("Failed to get block: {}", e)) - })?; + async fn get_block_by_height(&self, height: u64) -> ChainResult { + let block_res = self + .provider + .block_by_height(BlockHeight::new(height as u32)) + .await + .map_err(|e| HyperlaneProviderError::CouldNotFindBlockByHeight(height))?; - match block_res { - Some(block) => Ok(BlockInfo { + let block_info = match block_res { + Some(block) => BlockInfo { hash: H256::from_slice(block.id.as_slice()), - number: block.header.height.into(), timestamp: block.header.time.map_or(0, |t| t.timestamp() as u64), - }), - None => Err(ChainCommunicationError::BlockNotFound(hash.clone())), + number: block.header.height.into(), + }, + None => Err(HyperlaneProviderError::CouldNotFindBlockByHeight(height))?, + }; + + if block_info.number != height { + Err(HyperlaneProviderError::IncorrectBlockByHeight( + height, + block_info.number, + ))?; } + + Ok(block_info) } /// Used by scraper diff --git a/rust/main/chains/hyperlane-sealevel/src/error.rs b/rust/main/chains/hyperlane-sealevel/src/error.rs index 55b81b416..ff0142c39 100644 --- a/rust/main/chains/hyperlane-sealevel/src/error.rs +++ b/rust/main/chains/hyperlane-sealevel/src/error.rs @@ -14,6 +14,9 @@ pub enum HyperlaneSealevelError { /// ClientError error #[error("{0}")] ClientError(#[from] ClientError), + /// Decoding error + #[error("{0}")] + Decoding(#[from] solana_sdk::bs58::decode::Error), } impl From for ChainCommunicationError { diff --git a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs index 5453360e0..5e348d999 100644 --- a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs @@ -430,7 +430,7 @@ impl Mailbox for SealevelMailbox { let account = self .rpc() - .get_possible_account_with_finalized_commitment(&processed_message_account_key) + .get_account_option_with_finalized_commitment(&processed_message_account_key) .await?; Ok(account.is_some()) diff --git a/rust/main/chains/hyperlane-sealevel/src/provider.rs b/rust/main/chains/hyperlane-sealevel/src/provider.rs index b292d9594..aaf32ac59 100644 --- a/rust/main/chains/hyperlane-sealevel/src/provider.rs +++ b/rust/main/chains/hyperlane-sealevel/src/provider.rs @@ -1,11 +1,11 @@ use std::{str::FromStr, sync::Arc}; use async_trait::async_trait; - use hyperlane_core::{ - BlockInfo, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, TxnInfo, - H256, U256, + BlockInfo, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, + HyperlaneProviderError, TxnInfo, H256, U256, }; +use solana_sdk::bs58; use solana_sdk::pubkey::Pubkey; use crate::{error::HyperlaneSealevelError, ConnectionConf, SealevelRpcClient}; @@ -47,8 +47,25 @@ impl HyperlaneChain for SealevelProvider { #[async_trait] impl HyperlaneProvider for SealevelProvider { - async fn get_block_by_hash(&self, _hash: &H256) -> ChainResult { - todo!() // FIXME + async fn get_block_by_height(&self, slot: u64) -> ChainResult { + let confirmed_block = self.rpc_client.get_block(slot).await?; + + let hash_binary = bs58::decode(confirmed_block.blockhash) + .into_vec() + .map_err(HyperlaneSealevelError::Decoding)?; + let block_hash = H256::from_slice(&hash_binary); + + let block_time = confirmed_block + .block_time + .ok_or(HyperlaneProviderError::CouldNotFindBlockByHeight(slot))?; + + let block_info = BlockInfo { + hash: block_hash, + timestamp: block_time as u64, + number: slot, + }; + + Ok(block_info) } async fn get_txn_by_hash(&self, _hash: &H256) -> ChainResult { diff --git a/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs b/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs index 77f21ee1f..44ba2c8d5 100644 --- a/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs +++ b/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs @@ -3,8 +3,8 @@ use borsh::{BorshDeserialize, BorshSerialize}; use hyperlane_core::{ChainCommunicationError, ChainResult, U256}; use serializable_account_meta::{SerializableAccountMeta, SimulationReturnData}; use solana_client::{ - nonblocking::rpc_client::RpcClient, rpc_config::RpcProgramAccountsConfig, - rpc_response::Response, + nonblocking::rpc_client::RpcClient, rpc_config::RpcBlockConfig, + rpc_config::RpcProgramAccountsConfig, rpc_response::Response, }; use solana_sdk::{ account::Account, @@ -16,7 +16,9 @@ use solana_sdk::{ signature::{Keypair, Signature, Signer}, transaction::Transaction, }; -use solana_transaction_status::{TransactionStatus, UiReturnDataEncoding, UiTransactionReturnData}; +use solana_transaction_status::{ + TransactionStatus, UiConfirmedBlock, UiReturnDataEncoding, UiTransactionReturnData, +}; use crate::error::HyperlaneSealevelError; @@ -79,12 +81,12 @@ impl SealevelRpcClient { &self, pubkey: &Pubkey, ) -> ChainResult { - self.get_possible_account_with_finalized_commitment(pubkey) + self.get_account_option_with_finalized_commitment(pubkey) .await? .ok_or_else(|| ChainCommunicationError::from_other_str("Could not find account data")) } - pub async fn get_possible_account_with_finalized_commitment( + pub async fn get_account_option_with_finalized_commitment( &self, pubkey: &Pubkey, ) -> ChainResult> { @@ -97,6 +99,19 @@ impl SealevelRpcClient { Ok(account) } + pub async fn get_block(&self, height: u64) -> ChainResult { + let config = RpcBlockConfig { + commitment: Some(CommitmentConfig::finalized()), + max_supported_transaction_version: Some(0), + ..Default::default() + }; + self.0 + .get_block_with_config(height, config) + .await + .map_err(HyperlaneSealevelError::ClientError) + .map_err(Into::into) + } + pub async fn get_block_height(&self) -> ChainResult { let height = self .0 diff --git a/rust/main/hyperlane-core/src/error.rs b/rust/main/hyperlane-core/src/error.rs index fe1385c0e..63c0f3655 100644 --- a/rust/main/hyperlane-core/src/error.rs +++ b/rust/main/hyperlane-core/src/error.rs @@ -93,9 +93,6 @@ pub enum ChainCommunicationError { /// Failed to parse strings or integers #[error("Data parsing error {0:?}")] StrOrIntParseError(#[from] StrOrIntParseError), - /// BlockNotFoundError - #[error("Block not found: {0:?}")] - BlockNotFound(H256), /// utf8 error #[error("{0}")] Utf8(#[from] FromUtf8Error), diff --git a/rust/main/hyperlane-core/src/traits/provider.rs b/rust/main/hyperlane-core/src/traits/provider.rs index 654e80218..47070bc2a 100644 --- a/rust/main/hyperlane-core/src/traits/provider.rs +++ b/rust/main/hyperlane-core/src/traits/provider.rs @@ -16,8 +16,8 @@ use crate::{BlockInfo, ChainInfo, ChainResult, HyperlaneChain, TxnInfo, H256, U2 #[async_trait] #[auto_impl(&, Box, Arc)] pub trait HyperlaneProvider: HyperlaneChain + Send + Sync + Debug { - /// Get block info for a given block hash - async fn get_block_by_hash(&self, hash: &H256) -> ChainResult; + /// Get block info for a given block height + async fn get_block_by_height(&self, height: u64) -> ChainResult; /// Get txn info for a given txn hash async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult; @@ -35,13 +35,19 @@ pub trait HyperlaneProvider: HyperlaneChain + Send + Sync + Debug { /// Errors when querying for provider information. #[derive(Error, Debug)] pub enum HyperlaneProviderError { - /// The requested block hash is not yet known by the provider - #[error("Block is not part of chain yet {0:?}")] - BlockIsNotPartOfChainYet(H256), /// The provider did not return the gas which was used #[error("Provider did not return gas used")] NoGasUsed, - /// Could not find a transaction, block, or other object - #[error("Could not find object from provider with hash {0:?}")] - CouldNotFindObjectByHash(H256), + /// Could not find a transaction by hash + #[error("Could not find transaction from provider with hash {0:?}")] + CouldNotFindTransactionByHash(H256), + /// Could not find a block by height + #[error("Could not find block from provider with height {0:?}")] + CouldNotFindBlockByHeight(u64), + /// The requested block does not have its hash + #[error("Block with height {0:?} does not contain its hash")] + BlockWithoutHash(u64), + /// Incorrect block is received + #[error("Requested block with height {0:?}, received block with height {1:?}")] + IncorrectBlockByHeight(u64, u64), } diff --git a/rust/main/hyperlane-core/src/types/block_id.rs b/rust/main/hyperlane-core/src/types/block_id.rs new file mode 100644 index 000000000..57f69045e --- /dev/null +++ b/rust/main/hyperlane-core/src/types/block_id.rs @@ -0,0 +1,17 @@ +use crate::H256; + +/// Struct `BlockId` contains two types of identifiers for the same block: hash and height. +#[derive(Debug, Default, Copy, Clone)] +pub struct BlockId { + /// Block hash + pub hash: H256, + /// Block height + pub height: u64, +} + +impl BlockId { + /// Creates instance of `BlockId` struct + pub fn new(hash: H256, height: u64) -> Self { + Self { hash, height } + } +} diff --git a/rust/main/hyperlane-core/src/types/mod.rs b/rust/main/hyperlane-core/src/types/mod.rs index 07989e83e..a8973a72b 100644 --- a/rust/main/hyperlane-core/src/types/mod.rs +++ b/rust/main/hyperlane-core/src/types/mod.rs @@ -9,6 +9,7 @@ pub use self::primitive_types::*; pub use ::primitive_types as ethers_core_types; pub use account_address_type::AccountAddressType; pub use announcement::*; +pub use block_id::BlockId; pub use chain_data::*; pub use checkpoint::*; pub use indexing::*; @@ -23,6 +24,7 @@ use crate::{Decode, Encode, HyperlaneProtocolError}; /// This module contains enum for account address type mod account_address_type; mod announcement; +mod block_id; mod chain_data; mod checkpoint; mod indexing; From 3474a8450716d649aed6cd5d54f0ee0d68ff9ee5 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:07:27 +0100 Subject: [PATCH 186/224] fix: update cli dependencies (#4746) ### Description fix: update cli dependencies ### Drive-by changes na ### Related issues https://discord.com/channels/935678348330434570/961710804011458621/1299011251858440324 ### Backward compatibility y ### Testing `npm pack` `npm install -g hyperlane-cli-local.tgz` --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .changeset/early-chicken-develop.md | 5 ++++ typescript/cli/package.json | 2 ++ yarn.lock | 46 +++++++++++++++-------------- 3 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 .changeset/early-chicken-develop.md diff --git a/.changeset/early-chicken-develop.md b/.changeset/early-chicken-develop.md new file mode 100644 index 000000000..c43d9342e --- /dev/null +++ b/.changeset/early-chicken-develop.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': patch +--- + +Explicitly define inquirer/core and inquirier/figures dependencies diff --git a/typescript/cli/package.json b/typescript/cli/package.json index ab516e294..e55f6e4a7 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -8,6 +8,8 @@ "@hyperlane-xyz/registry": "4.7.0", "@hyperlane-xyz/sdk": "5.6.0", "@hyperlane-xyz/utils": "5.6.0", + "@inquirer/core": "9.0.10", + "@inquirer/figures": "1.0.5", "@inquirer/prompts": "^3.0.0", "ansi-escapes": "^7.0.0", "asn1.js": "^5.4.1", diff --git a/yarn.lock b/yarn.lock index 556803a51..40836ce5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7826,6 +7826,8 @@ __metadata: "@hyperlane-xyz/registry": "npm:4.7.0" "@hyperlane-xyz/sdk": "npm:5.6.0" "@hyperlane-xyz/utils": "npm:5.6.0" + "@inquirer/core": "npm:9.0.10" + "@inquirer/figures": "npm:1.0.5" "@inquirer/prompts": "npm:^3.0.0" "@types/chai-as-promised": "npm:^8" "@types/mocha": "npm:^10.0.1" @@ -8197,6 +8199,27 @@ __metadata: languageName: node linkType: hard +"@inquirer/core@npm:9.0.10, @inquirer/core@npm:^9.0.10": + version: 9.0.10 + resolution: "@inquirer/core@npm:9.0.10" + dependencies: + "@inquirer/figures": "npm:^1.0.5" + "@inquirer/type": "npm:^1.5.2" + "@types/mute-stream": "npm:^0.0.4" + "@types/node": "npm:^22.1.0" + "@types/wrap-ansi": "npm:^3.0.0" + ansi-escapes: "npm:^4.3.2" + cli-spinners: "npm:^2.9.2" + cli-width: "npm:^4.1.0" + mute-stream: "npm:^1.0.0" + signal-exit: "npm:^4.1.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^6.2.0" + yoctocolors-cjs: "npm:^2.1.2" + checksum: 1bcb1deb7393d78f2dac5b8774d10692ad50b70e3ebc24684d13259d0c6c863dd1bce8ab4d4a806a6e90d5a2517aa8f9981993b1a256c9be68d9ef5e748481c6 + languageName: node + linkType: hard + "@inquirer/core@npm:^3.0.0": version: 3.0.0 resolution: "@inquirer/core@npm:3.0.0" @@ -8219,27 +8242,6 @@ __metadata: languageName: node linkType: hard -"@inquirer/core@npm:^9.0.10": - version: 9.0.10 - resolution: "@inquirer/core@npm:9.0.10" - dependencies: - "@inquirer/figures": "npm:^1.0.5" - "@inquirer/type": "npm:^1.5.2" - "@types/mute-stream": "npm:^0.0.4" - "@types/node": "npm:^22.1.0" - "@types/wrap-ansi": "npm:^3.0.0" - ansi-escapes: "npm:^4.3.2" - cli-spinners: "npm:^2.9.2" - cli-width: "npm:^4.1.0" - mute-stream: "npm:^1.0.0" - signal-exit: "npm:^4.1.0" - strip-ansi: "npm:^6.0.1" - wrap-ansi: "npm:^6.2.0" - yoctocolors-cjs: "npm:^2.1.2" - checksum: 1bcb1deb7393d78f2dac5b8774d10692ad50b70e3ebc24684d13259d0c6c863dd1bce8ab4d4a806a6e90d5a2517aa8f9981993b1a256c9be68d9ef5e748481c6 - languageName: node - linkType: hard - "@inquirer/editor@npm:^1.2.4": version: 1.2.4 resolution: "@inquirer/editor@npm:1.2.4" @@ -8286,7 +8288,7 @@ __metadata: languageName: node linkType: hard -"@inquirer/figures@npm:^1.0.5": +"@inquirer/figures@npm:1.0.5, @inquirer/figures@npm:^1.0.5": version: 1.0.5 resolution: "@inquirer/figures@npm:1.0.5" checksum: 60a51b2cdef03c89be25071c23d8c4ae427c56d8ac1b00bf054ca7be446674adc4edd66c15465fe6a81ff0726b024bf37f8a2903a8387ef968d33058da3e7a15 From c53e3302b3c70c21cd0b620e8f2365d48c2ce289 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:32:58 +0000 Subject: [PATCH 187/224] Version Packages (#4742) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/core@5.6.0 ### Minor Changes - c55257cf5: Minor token related changes like adding custom hook to 4626 collateral, checking for ERC20 as valid contract in HypERC20Collateral, etc. - 8cc0d9a4a: Added WHypERC4626 as a wrapper for rebasing HypERC4626 ### Patch Changes - 8cc0d9a4a: Add wrapped HypERC4626 for easy defi use - @hyperlane-xyz/utils@5.6.1 ## @hyperlane-xyz/cli@5.6.1 ### Patch Changes - 3474a8450: Explicitly define inquirer/core and inquirier/figures dependencies - @hyperlane-xyz/sdk@5.6.1 - @hyperlane-xyz/utils@5.6.1 ## @hyperlane-xyz/helloworld@5.6.1 ### Patch Changes - Updated dependencies [8cc0d9a4a] - Updated dependencies [c55257cf5] - Updated dependencies [8cc0d9a4a] - @hyperlane-xyz/core@5.6.0 - @hyperlane-xyz/sdk@5.6.1 ## @hyperlane-xyz/sdk@5.6.1 ### Patch Changes - Updated dependencies [8cc0d9a4a] - Updated dependencies [c55257cf5] - Updated dependencies [8cc0d9a4a] - @hyperlane-xyz/core@5.6.0 - @hyperlane-xyz/utils@5.6.1 ## @hyperlane-xyz/widgets@5.6.1 ### Patch Changes - @hyperlane-xyz/sdk@5.6.1 - @hyperlane-xyz/utils@5.6.1 ## @hyperlane-xyz/utils@5.6.1 ## @hyperlane-xyz/infra@5.6.1 ### Patch Changes - @hyperlane-xyz/helloworld@5.6.1 - @hyperlane-xyz/sdk@5.6.1 - @hyperlane-xyz/utils@5.6.1 ## @hyperlane-xyz/ccip-server@5.6.1 ## @hyperlane-xyz/github-proxy@5.6.1 --------- Co-authored-by: github-actions[bot] --- .changeset/early-chicken-develop.md | 5 ---- .changeset/itchy-bananas-know.md | 5 ---- .changeset/perfect-dryers-destroy.md | 5 ---- .changeset/shiny-baboons-hunt.md | 5 ---- solidity/CHANGELOG.md | 12 ++++++++++ solidity/contracts/PackageVersioned.sol | 2 +- solidity/package.json | 4 ++-- typescript/ccip-server/CHANGELOG.md | 2 ++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 8 +++++++ typescript/cli/package.json | 6 ++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 2 ++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 10 ++++++++ typescript/helloworld/package.json | 6 ++--- typescript/infra/CHANGELOG.md | 8 +++++++ typescript/infra/package.json | 8 +++---- typescript/sdk/CHANGELOG.md | 10 ++++++++ typescript/sdk/package.json | 6 ++--- typescript/utils/CHANGELOG.md | 2 ++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 7 ++++++ typescript/widgets/package.json | 6 ++--- yarn.lock | 32 ++++++++++++------------- 25 files changed, 100 insertions(+), 59 deletions(-) delete mode 100644 .changeset/early-chicken-develop.md delete mode 100644 .changeset/itchy-bananas-know.md delete mode 100644 .changeset/perfect-dryers-destroy.md delete mode 100644 .changeset/shiny-baboons-hunt.md diff --git a/.changeset/early-chicken-develop.md b/.changeset/early-chicken-develop.md deleted file mode 100644 index c43d9342e..000000000 --- a/.changeset/early-chicken-develop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': patch ---- - -Explicitly define inquirer/core and inquirier/figures dependencies diff --git a/.changeset/itchy-bananas-know.md b/.changeset/itchy-bananas-know.md deleted file mode 100644 index 188981756..000000000 --- a/.changeset/itchy-bananas-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': patch ---- - -Add wrapped HypERC4626 for easy defi use diff --git a/.changeset/perfect-dryers-destroy.md b/.changeset/perfect-dryers-destroy.md deleted file mode 100644 index f9a906ef1..000000000 --- a/.changeset/perfect-dryers-destroy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': minor ---- - -Minor token related changes like adding custom hook to 4626 collateral, checking for ERC20 as valid contract in HypERC20Collateral, etc. diff --git a/.changeset/shiny-baboons-hunt.md b/.changeset/shiny-baboons-hunt.md deleted file mode 100644 index ef302d93f..000000000 --- a/.changeset/shiny-baboons-hunt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': minor ---- - -Added WHypERC4626 as a wrapper for rebasing HypERC4626 diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index dbffd611f..fbecf3809 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,17 @@ # @hyperlane-xyz/core +## 5.6.0 + +### Minor Changes + +- c55257cf5: Minor token related changes like adding custom hook to 4626 collateral, checking for ERC20 as valid contract in HypERC20Collateral, etc. +- 8cc0d9a4a: Added WHypERC4626 as a wrapper for rebasing HypERC4626 + +### Patch Changes + +- 8cc0d9a4a: Add wrapped HypERC4626 for easy defi use + - @hyperlane-xyz/utils@5.6.1 + ## 5.5.0 ### Minor Changes diff --git a/solidity/contracts/PackageVersioned.sol b/solidity/contracts/PackageVersioned.sol index eb57706c1..b1fa39c8a 100644 --- a/solidity/contracts/PackageVersioned.sol +++ b/solidity/contracts/PackageVersioned.sol @@ -7,5 +7,5 @@ pragma solidity >=0.6.11; **/ abstract contract PackageVersioned { // GENERATED CODE - DO NOT EDIT - string public constant PACKAGE_VERSION = "5.5.0"; + string public constant PACKAGE_VERSION = "5.6.0"; } diff --git a/solidity/package.json b/solidity/package.json index 78c42ca78..f8cbe196c 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.5.0", + "version": "5.6.0", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.6.0", + "@hyperlane-xyz/utils": "5.6.1", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index 6ec43d13c..08febc36f 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/ccip-server +## 5.6.1 + ## 5.6.0 ## 5.5.0 diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index 457654431..5a7c9cdf1 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.6.0", + "version": "5.6.1", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index 1cd6506a1..37fc5fea7 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/cli +## 5.6.1 + +### Patch Changes + +- 3474a8450: Explicitly define inquirer/core and inquirier/figures dependencies + - @hyperlane-xyz/sdk@5.6.1 + - @hyperlane-xyz/utils@5.6.1 + ## 5.6.0 ### Minor Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index e55f6e4a7..9348646b8 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.6.0", + "version": "5.6.1", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.6.0", - "@hyperlane-xyz/utils": "5.6.0", + "@hyperlane-xyz/sdk": "5.6.1", + "@hyperlane-xyz/utils": "5.6.1", "@inquirer/core": "9.0.10", "@inquirer/figures": "1.0.5", "@inquirer/prompts": "^3.0.0", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index d4a8ed991..8937a2bf5 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.6.0'; +export const VERSION = '5.6.1'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md index a71264e35..ae6e2a41a 100644 --- a/typescript/github-proxy/CHANGELOG.md +++ b/typescript/github-proxy/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/github-proxy +## 5.6.1 + ## 5.6.0 ## 5.5.0 diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index d8173c30d..9f804e01d 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.6.0", + "version": "5.6.1", "private": true, "scripts": { "deploy": "wrangler deploy", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index 1d2f1535b..17f77d3d5 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,15 @@ # @hyperlane-xyz/helloworld +## 5.6.1 + +### Patch Changes + +- Updated dependencies [8cc0d9a4a] +- Updated dependencies [c55257cf5] +- Updated dependencies [8cc0d9a4a] + - @hyperlane-xyz/core@5.6.0 + - @hyperlane-xyz/sdk@5.6.1 + ## 5.6.0 ### Patch Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index 927647d06..bc404b472 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.6.0", + "version": "5.6.1", "dependencies": { - "@hyperlane-xyz/core": "5.5.0", + "@hyperlane-xyz/core": "5.6.0", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.6.0", + "@hyperlane-xyz/sdk": "5.6.1", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index 3b623135c..f5f25b3f3 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,13 @@ # @hyperlane-xyz/infra +## 5.6.1 + +### Patch Changes + +- @hyperlane-xyz/helloworld@5.6.1 +- @hyperlane-xyz/sdk@5.6.1 +- @hyperlane-xyz/utils@5.6.1 + ## 5.6.0 ### Minor Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 9d1d090c5..375d06c59 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.6.0", + "version": "5.6.1", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.6.0", + "@hyperlane-xyz/helloworld": "5.6.1", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.6.0", - "@hyperlane-xyz/utils": "5.6.0", + "@hyperlane-xyz/sdk": "5.6.1", + "@hyperlane-xyz/utils": "5.6.1", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index 0cec012ff..ad33e87c2 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,15 @@ # @hyperlane-xyz/sdk +## 5.6.1 + +### Patch Changes + +- Updated dependencies [8cc0d9a4a] +- Updated dependencies [c55257cf5] +- Updated dependencies [8cc0d9a4a] + - @hyperlane-xyz/core@5.6.0 + - @hyperlane-xyz/utils@5.6.1 + ## 5.6.0 ### Minor Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 1a5e86aa8..44e35d35a 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.6.0", + "version": "5.6.1", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.5.0", - "@hyperlane-xyz/utils": "5.6.0", + "@hyperlane-xyz/core": "5.6.0", + "@hyperlane-xyz/utils": "5.6.1", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index e22dca07a..8575e59fd 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/utils +## 5.6.1 + ## 5.6.0 ### Minor Changes diff --git a/typescript/utils/package.json b/typescript/utils/package.json index 9baa234bf..e06c4cf63 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.6.0", + "version": "5.6.1", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index e4698dd65..0ded083ed 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,12 @@ # @hyperlane-xyz/widgets +## 5.6.1 + +### Patch Changes + +- @hyperlane-xyz/sdk@5.6.1 +- @hyperlane-xyz/utils@5.6.1 + ## 5.6.0 ### Patch Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 031a87479..5160014c6 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,15 +1,15 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.6.0", + "version": "5.6.1", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@headlessui/react": "^2.1.8", - "@hyperlane-xyz/sdk": "5.6.0", - "@hyperlane-xyz/utils": "5.6.0", + "@hyperlane-xyz/sdk": "5.6.1", + "@hyperlane-xyz/utils": "5.6.1", "clsx": "^2.1.1", "react-tooltip": "^5.28.0" }, diff --git a/yarn.lock b/yarn.lock index 40836ce5a..279fe75e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7824,8 +7824,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.6.0" - "@hyperlane-xyz/utils": "npm:5.6.0" + "@hyperlane-xyz/sdk": "npm:5.6.1" + "@hyperlane-xyz/utils": "npm:5.6.1" "@inquirer/core": "npm:9.0.10" "@inquirer/figures": "npm:1.0.5" "@inquirer/prompts": "npm:^3.0.0" @@ -7860,13 +7860,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.5.0, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.6.0, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.6.0" + "@hyperlane-xyz/utils": "npm:5.6.1" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7917,13 +7917,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.6.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.6.1, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.5.0" + "@hyperlane-xyz/core": "npm:5.6.0" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.6.0" + "@hyperlane-xyz/sdk": "npm:5.6.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7970,10 +7970,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.6.0" + "@hyperlane-xyz/helloworld": "npm:5.6.1" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.6.0" - "@hyperlane-xyz/utils": "npm:5.6.0" + "@hyperlane-xyz/sdk": "npm:5.6.1" + "@hyperlane-xyz/utils": "npm:5.6.1" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -8039,7 +8039,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.6.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.6.1, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -8047,8 +8047,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.5.0" - "@hyperlane-xyz/utils": "npm:5.6.0" + "@hyperlane-xyz/core": "npm:5.6.0" + "@hyperlane-xyz/utils": "npm:5.6.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -8089,7 +8089,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.6.0, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.6.1, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -8115,8 +8115,8 @@ __metadata: dependencies: "@headlessui/react": "npm:^2.1.8" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.6.0" - "@hyperlane-xyz/utils": "npm:5.6.0" + "@hyperlane-xyz/sdk": "npm:5.6.1" + "@hyperlane-xyz/utils": "npm:5.6.1" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From 15db5c112d90fb0c6a1035ed380be1ce63321af4 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 24 Oct 2024 17:00:41 +0100 Subject: [PATCH 188/224] chore: update Eclipse validator sets to include Stride, minor cleanup (#4747) ### Description - deletes all the mainnet2 artifacts that we don't need - moves the sealevel helper scripts into more explicit directories, and ensures thresholds are appropriate - updates the eclipse ISM ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../sealevel/environments/mainnet2/.gitignore | 1 - .../environments/mainnet2/chain-config.json | 350 --------- .../mainnet2/gas-oracle-configs.json | 20 - .../hyperlane/helloworld-config.json | 30 - .../helloworld/hyperlane/program-ids.json | 42 -- .../helloworld/rc/helloworld-config.json | 32 - .../mainnet2/helloworld/rc/program-ids.json | 42 -- .../solana/hyperlane/multisig-config.json | 106 --- .../solana/nautilus/multisig-config.json | 18 - .../solana/nautilus/program-ids.json | 3 - .../solana/rc/multisig-config.json | 65 -- .../solana/rc/program-ids.json | 3 - .../mainnet2/solana/core/program-ids.json | 8 - .../mainnet2/warp-routes/zbc/program-ids.json | 10 - .../warp-routes/zbc/token-config.json | 16 - .../environments/mainnet3/chain-config.json | 705 +++++++++++++++--- .../hyperlane/multisig-config.json | 228 ++++-- .../scripts/print-multisig-ism-config.ts | 30 - .../print-chain-metadatas.ts | 4 +- .../print-multisig-ism-config.ts | 50 ++ 20 files changed, 819 insertions(+), 944 deletions(-) delete mode 100644 rust/sealevel/environments/mainnet2/.gitignore delete mode 100644 rust/sealevel/environments/mainnet2/chain-config.json delete mode 100644 rust/sealevel/environments/mainnet2/gas-oracle-configs.json delete mode 100644 rust/sealevel/environments/mainnet2/helloworld/hyperlane/helloworld-config.json delete mode 100644 rust/sealevel/environments/mainnet2/helloworld/hyperlane/program-ids.json delete mode 100644 rust/sealevel/environments/mainnet2/helloworld/rc/helloworld-config.json delete mode 100644 rust/sealevel/environments/mainnet2/helloworld/rc/program-ids.json delete mode 100644 rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/hyperlane/multisig-config.json delete mode 100644 rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/multisig-config.json delete mode 100644 rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/program-ids.json delete mode 100644 rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/multisig-config.json delete mode 100644 rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/program-ids.json delete mode 100644 rust/sealevel/environments/mainnet2/solana/core/program-ids.json delete mode 100644 rust/sealevel/environments/mainnet2/warp-routes/zbc/program-ids.json delete mode 100644 rust/sealevel/environments/mainnet2/warp-routes/zbc/token-config.json delete mode 100644 typescript/infra/scripts/print-multisig-ism-config.ts rename typescript/infra/scripts/{ => sealevel-helpers}/print-chain-metadatas.ts (87%) create mode 100644 typescript/infra/scripts/sealevel-helpers/print-multisig-ism-config.ts diff --git a/rust/sealevel/environments/mainnet2/.gitignore b/rust/sealevel/environments/mainnet2/.gitignore deleted file mode 100644 index 1b33b4a79..000000000 --- a/rust/sealevel/environments/mainnet2/.gitignore +++ /dev/null @@ -1 +0,0 @@ -**/**/keys diff --git a/rust/sealevel/environments/mainnet2/chain-config.json b/rust/sealevel/environments/mainnet2/chain-config.json deleted file mode 100644 index 23723ef82..000000000 --- a/rust/sealevel/environments/mainnet2/chain-config.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "bsc": { - "chainId": 56, - "domainId": 56, - "name": "bsc", - "protocol": "ethereum", - "displayName": "Binance Smart Chain", - "displayNameShort": "Binance", - "nativeToken": { - "decimals": 18, - "name": "BNB", - "symbol": "BNB" - }, - "rpcUrls": [ - { - "http": "https://bsc-dataseed.binance.org" - }, - { - "http": "https://rpc.ankr.com/bsc" - } - ], - "blockExplorers": [ - { - "name": "BscScan", - "url": "https://bscscan.com", - "apiUrl": "https://api.bscscan.com/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 15, - "estimateBlockTime": 3 - }, - "gasCurrencyCoinGeckoId": "binancecoin", - "gnosisSafeTransactionServiceUrl": "https://safe-transaction-bsc.safe.global/", - "transactionOverrides": { - "gasPrice": 7000000000 - } - }, - "avalanche": { - "chainId": 43114, - "domainId": 43114, - "name": "avalanche", - "protocol": "ethereum", - "displayName": "Avalanche", - "nativeToken": { - "decimals": 18, - "name": "Avalanche", - "symbol": "AVAX" - }, - "rpcUrls": [ - { - "http": "https://api.avax.network/ext/bc/C/rpc", - "pagination": { - "maxBlockRange": 100000, - "minBlockNumber": 6765067 - } - } - ], - "blockExplorers": [ - { - "name": "SnowTrace", - "url": "https://snowtrace.io", - "apiUrl": "https://api.snowtrace.io/api", - "family": "other" - } - ], - "blocks": { - "confirmations": 3, - "reorgPeriod": 3, - "estimateBlockTime": 2 - }, - "gasCurrencyCoinGeckoId": "avalanche-2", - "gnosisSafeTransactionServiceUrl": "https://safe-transaction-avalanche.safe.global/" - }, - "polygon": { - "chainId": 137, - "domainId": 137, - "name": "polygon", - "protocol": "ethereum", - "displayName": "Polygon", - "nativeToken": { - "name": "Ether", - "symbol": "ETH", - "decimals": 18 - }, - "rpcUrls": [ - { - "http": "https://rpc-mainnet.matic.quiknode.pro", - "pagination": { - "maxBlockRange": 10000, - "minBlockNumber": 19657100 - } - }, - { - "http": "https://polygon-rpc.com" - } - ], - "blockExplorers": [ - { - "name": "PolygonScan", - "url": "https://polygonscan.com", - "apiUrl": "https://api.polygonscan.com/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 3, - "reorgPeriod": 256, - "estimateBlockTime": 2 - }, - "gasCurrencyCoinGeckoId": "matic-network", - "gnosisSafeTransactionServiceUrl": "https://safe-transaction-polygon.safe.global/", - "transactionOverrides": { - "maxFeePerGas": 500000000000, - "maxPriorityFeePerGas": 100000000000 - } - }, - "celo": { - "chainId": 42220, - "domainId": 42220, - "name": "celo", - "protocol": "ethereum", - "displayName": "Celo", - "nativeToken": { - "decimals": 18, - "name": "CELO", - "symbol": "CELO" - }, - "rpcUrls": [ - { - "http": "https://forno.celo.org" - } - ], - "blockExplorers": [ - { - "name": "CeloScan", - "url": "https://celoscan.io", - "apiUrl": "https://api.celoscan.io/api", - "family": "etherscan" - }, - { - "name": "Blockscout", - "url": "https://explorer.celo.org", - "apiUrl": "https://explorer.celo.org/mainnet/api", - "family": "blockscout" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 0, - "estimateBlockTime": 5 - }, - "gnosisSafeTransactionServiceUrl": "https://mainnet-tx-svc.celo-safe-prod.celo-networks-dev.org/" - }, - "arbitrum": { - "chainId": 42161, - "domainId": 42161, - "name": "arbitrum", - "protocol": "ethereum", - "displayName": "Arbitrum", - "nativeToken": { - "name": "Ether", - "symbol": "ETH", - "decimals": 18 - }, - "rpcUrls": [ - { - "http": "https://arb1.arbitrum.io/rpc" - } - ], - "blockExplorers": [ - { - "name": "Arbiscan", - "url": "https://arbiscan.io", - "apiUrl": "https://api.arbiscan.io/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 0, - "estimateBlockTime": 3 - }, - "gasCurrencyCoinGeckoId": "ethereum", - "gnosisSafeTransactionServiceUrl": "https://safe-transaction-arbitrum.safe.global/" - }, - "optimism": { - "chainId": 10, - "domainId": 10, - "name": "optimism", - "protocol": "ethereum", - "displayName": "Optimism", - "nativeToken": { - "name": "Ether", - "symbol": "ETH", - "decimals": 18 - }, - "rpcUrls": [ - { - "http": "https://mainnet.optimism.io" - } - ], - "blockExplorers": [ - { - "name": "Etherscan", - "url": "https://optimistic.etherscan.io", - "apiUrl": "https://api-optimistic.etherscan.io/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 0, - "estimateBlockTime": 3 - }, - "gasCurrencyCoinGeckoId": "ethereum", - "gnosisSafeTransactionServiceUrl": "https://safe-transaction-optimism.safe.global/" - }, - "ethereum": { - "chainId": 1, - "domainId": 1, - "name": "ethereum", - "protocol": "ethereum", - "displayName": "Ethereum", - "nativeToken": { - "name": "Ether", - "symbol": "ETH", - "decimals": 18 - }, - "rpcUrls": [ - { - "http": "https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161" - }, - { - "http": "https://cloudflare-eth.com" - } - ], - "blockExplorers": [ - { - "name": "Etherscan", - "url": "https://etherscan.io", - "apiUrl": "https://api.etherscan.io/api", - "family": "etherscan" - }, - { - "name": "Blockscout", - "url": "https://blockscout.com/eth/mainnet", - "apiUrl": "https://blockscout.com/eth/mainnet/api", - "family": "blockscout" - } - ], - "blocks": { - "confirmations": 3, - "reorgPeriod": 14, - "estimateBlockTime": 13 - }, - "gnosisSafeTransactionServiceUrl": "https://safe-transaction-mainnet.safe.global/", - "transactionOverrides": { - "maxFeePerGas": 150000000000, - "maxPriorityFeePerGas": 5000000000 - } - }, - "moonbeam": { - "chainId": 1284, - "domainId": 1284, - "name": "moonbeam", - "protocol": "ethereum", - "displayName": "Moonbeam", - "nativeToken": { - "decimals": 18, - "name": "GLMR", - "symbol": "GLMR" - }, - "rpcUrls": [ - { - "http": "https://rpc.api.moonbeam.network" - } - ], - "blockExplorers": [ - { - "name": "MoonScan", - "url": "https://moonscan.io", - "apiUrl": "https://api-moonbeam.moonscan.io/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 2, - "reorgPeriod": 2, - "estimateBlockTime": 12 - }, - "gnosisSafeTransactionServiceUrl": "https://transaction.multisig.moonbeam.network" - }, - "gnosis": { - "chainId": 100, - "domainId": 100, - "name": "gnosis", - "protocol": "ethereum", - "displayName": "Gnosis", - "nativeToken": { - "name": "xDai", - "symbol": "xDai", - "decimals": 18 - }, - "rpcUrls": [ - { - "http": "https://rpc.gnosischain.com", - "pagination": { - "maxBlockRange": 10000, - "minBlockNumber": 25997478 - } - } - ], - "blockExplorers": [ - { - "name": "GnosisScan", - "url": "https://gnosisscan.io", - "apiUrl": "https://api.gnosisscan.io/api", - "family": "etherscan" - } - ], - "blocks": { - "confirmations": 1, - "reorgPeriod": 14, - "estimateBlockTime": 5 - }, - "gasCurrencyCoinGeckoId": "xdai", - "gnosisSafeTransactionServiceUrl": "https://safe-transaction-gnosis-chain.safe.global/" - }, - "solanamainnet": { - "chainId": 1399811149, - "name": "solanamainnet", - "rpcUrls": [ - { - "http": "https://api.mainnet-beta.solana.com" - } - ] - }, - "nautilus": { - "chainId": 22222, - "name": "nautilus", - "rpcUrls": [ - { - "http": "https://api.nautilus.nautchain.xyz" - } - ] - } -} diff --git a/rust/sealevel/environments/mainnet2/gas-oracle-configs.json b/rust/sealevel/environments/mainnet2/gas-oracle-configs.json deleted file mode 100644 index 75bc47071..000000000 --- a/rust/sealevel/environments/mainnet2/gas-oracle-configs.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "domain": 56, - "gasOracle": { - "type": "remoteGasData", - "tokenExchangeRate": "100000000000000000000", - "gasPrice": "3000000000", - "tokenDecimals": 18 - } - }, - { - "domain": 22222, - "gasOracle": { - "type": "remoteGasData", - "tokenExchangeRate": "4700000000000000", - "gasPrice": "1000000000", - "tokenDecimals": 18 - } - } -] \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet2/helloworld/hyperlane/helloworld-config.json b/rust/sealevel/environments/mainnet2/helloworld/hyperlane/helloworld-config.json deleted file mode 100644 index 34aaf6284..000000000 --- a/rust/sealevel/environments/mainnet2/helloworld/hyperlane/helloworld-config.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "solanamainnet": {}, - "bsc": { - "foreignDeployment": "0xB97d3bF2fC296c2cAC4056bBC8A783ff39408e20" - }, - "avalanche": { - "foreignDeployment": "0x2A925CD8a5d919c5c6599633090c37fe38A561b6" - }, - "polygon": { - "foreignDeployment": "0x6c0aC8cEA75232aa7BeD8cbe9C4f820E7a77a9C3" - }, - "celo": { - "foreignDeployment": "0x4151773Db70C0b2D4c43Ea44A5FB5803ff1d3e0B" - }, - "arbitrum": { - "foreignDeployment": "0x96271cA0ab9eeFB3Ca481749c0Ca4c705fD4F523" - }, - "optimism": { - "foreignDeployment": "0xA6f0A37DFDe9C2c8F46F010989C47d9edB3a9FA8" - }, - "ethereum": { - "foreignDeployment": "0x9311cEE522A7C122B843b66cC31C6a63e2F92641" - }, - "moonbeam": { - "foreignDeployment": "0xAe067C08703508230357025B38c35Cd12793628c" - }, - "gnosis": { - "foreignDeployment": "0x26f32245fCF5Ad53159E875d5Cae62aEcf19c2d4" - } -} diff --git a/rust/sealevel/environments/mainnet2/helloworld/hyperlane/program-ids.json b/rust/sealevel/environments/mainnet2/helloworld/hyperlane/program-ids.json deleted file mode 100644 index 466662638..000000000 --- a/rust/sealevel/environments/mainnet2/helloworld/hyperlane/program-ids.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "moonbeam": { - "hex": "0x000000000000000000000000ae067c08703508230357025b38c35cd12793628c", - "base58": "1111111111113RcuHPfDctyAnFWHvj8tS1q8UHPh" - }, - "bsc": { - "hex": "0x000000000000000000000000b97d3bf2fc296c2cac4056bbc8a783ff39408e20", - "base58": "1111111111113atAoP8gQ2GYeue77ETUPAf8w9zw" - }, - "optimism": { - "hex": "0x000000000000000000000000a6f0a37dfde9c2c8f46f010989c47d9edb3a9fa8", - "base58": "1111111111113KtqevvpYv7NCiadmp6tRRfivB8K" - }, - "avalanche": { - "hex": "0x0000000000000000000000002a925cd8a5d919c5c6599633090c37fe38a561b6", - "base58": "111111111111bQB6b7XVDHSyvi7XmLrQMT8C3xH" - }, - "ethereum": { - "hex": "0x0000000000000000000000009311cee522a7c122b843b66cc31c6a63e2f92641", - "base58": "11111111111133qb6DzNiJ7whNaYGud2WqqtjxFS" - }, - "solanamainnet": { - "hex": "0x3797d0096b18b5b645c346a66d7f18c6c5738782c6bce24da57a3462bdef82b1", - "base58": "4k1gruSdH1r57V9QQK4aunzfMYzLFfF83jdYkkEwyem6" - }, - "celo": { - "hex": "0x0000000000000000000000004151773db70c0b2d4c43ea44a5fb5803ff1d3e0b", - "base58": "111111111111unDVQcjdeHntE83qvf1vsKCZ4av" - }, - "polygon": { - "hex": "0x0000000000000000000000006c0ac8cea75232aa7bed8cbe9c4f820e7a77a9c3", - "base58": "1111111111112WJXE3PCAsCXYZxU9Kh51sSZEa5G" - }, - "arbitrum": { - "hex": "0x00000000000000000000000096271ca0ab9eefb3ca481749c0ca4c705fd4f523", - "base58": "11111111111136L61X7cdT9tPZ4GKBtzJtrjFAd8" - }, - "gnosis": { - "hex": "0x00000000000000000000000026f32245fcf5ad53159e875d5cae62aecf19c2d4", - "base58": "111111111111YURfyMRiiTWy8X6pYHAqmYPmBpf" - } -} diff --git a/rust/sealevel/environments/mainnet2/helloworld/rc/helloworld-config.json b/rust/sealevel/environments/mainnet2/helloworld/rc/helloworld-config.json deleted file mode 100644 index 5e6ae772b..000000000 --- a/rust/sealevel/environments/mainnet2/helloworld/rc/helloworld-config.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "solanamainnet": { - "interchainSecurityModule": "BYTsxBuKVbwgsZFswzB91nrxveQySghwXzaKqn8exNnC" - }, - "gnosis": { - "foreignDeployment": "0x99ca8c74cE7Cfa9d72A51fbb05F9821f5f826b3a" - }, - "bsc": { - "foreignDeployment": "0xe5554478F167936dB253f79f57c41770bfa00Bae" - }, - "avalanche": { - "foreignDeployment": "0xe1De9910fe71cC216490AC7FCF019e13a34481D7" - }, - "polygon": { - "foreignDeployment": "0xAb65C41a1BC580a52f0b166879122EFdce0cB868" - }, - "celo": { - "foreignDeployment": "0xfE29f6a4468536029Fc9c97d3a9669b9fe38E114" - }, - "arbitrum": { - "foreignDeployment": "0x414B67F62b143d6db6E9b633168Dd6fd4DA20642" - }, - "optimism": { - "foreignDeployment": "0xB4caf2CA864B413DAA502fA18A8D48cD0740fC52" - }, - "ethereum": { - "foreignDeployment": "0xed31c20c5517EaC05decD5F6dCd01Fe6d16fD09D" - }, - "moonbeam": { - "foreignDeployment": "0x3eB9eE2CFC8DCB6F58B5869D33336CFcBf1dC354" - } -} diff --git a/rust/sealevel/environments/mainnet2/helloworld/rc/program-ids.json b/rust/sealevel/environments/mainnet2/helloworld/rc/program-ids.json deleted file mode 100644 index e3c0c46c4..000000000 --- a/rust/sealevel/environments/mainnet2/helloworld/rc/program-ids.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "solanamainnet": { - "hex": "0x29dacc0e7124ea39b1fd43ab0fd30e038cf405c0229890229d0086d0b6516f9c", - "base58": "3pPDp16iVTJFge2sm85Q61hW61UN5xNqeG24gqFhzLFV" - }, - "avalanche": { - "hex": "0x000000000000000000000000e1de9910fe71cc216490ac7fcf019e13a34481d7", - "base58": "11111111111149We9K5tM8ijcyNy9zDMG9RyDBCJ" - }, - "arbitrum": { - "hex": "0x000000000000000000000000414b67f62b143d6db6e9b633168dd6fd4da20642", - "base58": "111111111111um79Yc6Evs5e1m2fdD2x7T1cpXb" - }, - "moonbeam": { - "hex": "0x0000000000000000000000003eb9ee2cfc8dcb6f58b5869d33336cfcbf1dc354", - "base58": "111111111111sgjzaeuHfqhExkdPQ1gJdhcSr4j" - }, - "optimism": { - "hex": "0x000000000000000000000000b4caf2ca864b413daa502fa18a8d48cd0740fc52", - "base58": "1111111111113X64nhkfMi9X5MbxKsiDTeeTmjsw" - }, - "ethereum": { - "hex": "0x000000000000000000000000ed31c20c5517eac05decd5f6dcd01fe6d16fd09d", - "base58": "1111111111114JfPmRiKEsR445qonVzCpsAvXCR2" - }, - "gnosis": { - "hex": "0x00000000000000000000000099ca8c74ce7cfa9d72a51fbb05f9821f5f826b3a", - "base58": "11111111111139Gc7eyQjpZrmWkkYQRyA2Grcvmf" - }, - "bsc": { - "hex": "0x000000000000000000000000e5554478f167936db253f79f57c41770bfa00bae", - "base58": "1111111111114CJxuV4VoAh5NsJy9qCGHqryoTCy" - }, - "polygon": { - "hex": "0x000000000000000000000000ab65c41a1bc580a52f0b166879122efdce0cb868", - "base58": "1111111111113PVkHAU9H7moDSoQvhC3Y2wgmovX" - }, - "celo": { - "hex": "0x000000000000000000000000fe29f6a4468536029fc9c97d3a9669b9fe38e114", - "base58": "1111111111114YNh3uhCWh2NjyPttobeNRyuDHYo" - } -} diff --git a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/hyperlane/multisig-config.json b/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/hyperlane/multisig-config.json deleted file mode 100644 index 49cb69474..000000000 --- a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/hyperlane/multisig-config.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "celo": { - "type": 3, - "threshold": 4, - "validators": [ - "0x1f20274b1210046769d48174c2f0e7c25ca7d5c5", - "0x3bc014bafa43f93d534aed34f750997cdffcf007", - "0xd79d506d741fa735938f7b7847a926e34a6fe6b0", - "0xe4a258bc61e65914c2a477b2a8a433ab4ebdf44b", - "0x6aea63b0be4679c1385c26a92a3ff8aa6a8379f2", - "0xc0085e1a49bcc69e534272adb82c74c0e007e1ca" - ] - }, - "ethereum": { - "type": 3, - "threshold": 4, - "validators": [ - "0x4c327ccb881a7542be77500b2833dc84c839e7b7", - "0x84cb373148ef9112b277e68acf676fefa9a9a9a0", - "0x0d860c2b28bec3af4fd3a5997283e460ff6f2789", - "0xd4c1211f0eefb97a846c4e6d6589832e52fc03db", - "0x600c90404d5c9df885404d2cc5350c9b314ea3a2", - "0x892DC66F5B2f8C438E03f6323394e34A9C24F2D6" - ] - }, - "avalanche": { - "type": 3, - "threshold": 4, - "validators": [ - "0xa7aa52623fe3d78c343008c95894be669e218b8d", - "0xb6004433fb04f643e2d48ae765c0e7f890f0bc0c", - "0xa07e213e0985b21a6128e6c22ab5fb73948b0cc2", - "0x73853ed9a5f6f2e4c521970a94d43469e3cdaea6", - "0xbd2e136cda02ba627ca882e49b184cbe976081c8", - "0x1418126f944a44dad9edbab32294a8c890e7a9e3" - ] - }, - "polygon": { - "type": 3, - "threshold": 4, - "validators": [ - "0x59a001c3451e7f9f3b4759ea215382c1e9aa5fc1", - "0x009fb042d28944017177920c1d40da02bfebf474", - "0xba4b13e23705a5919c1901150d9697e8ffb3ea71", - "0x2faa4071b718972f9b4beec1d8cbaa4eb6cca6c6", - "0x5ae9b0f833dfe09ef455562a1f603f1634504dd6", - "0x6a163d312f7352a95c9b81dca15078d5bf77a442" - ] - }, - "bsc": { - "type": 3, - "threshold": 4, - "validators": [ - "0xcc84b1eb711e5076b2755cf4ad1d2b42c458a45e", - "0xefe34eae2bca1846b895d2d0762ec21796aa196a", - "0x662674e80e189b0861d6835c287693f50ee0c2ff", - "0x8a0f59075af466841808c529624807656309c9da", - "0xdd2ff046ccd748a456b4757a73d47f165469669f", - "0x034c4924c30ec4aa1b7f3ad58548988f0971e1bf" - ] - }, - "arbitrum": { - "type": 3, - "threshold": 4, - "validators": [ - "0xbcb815f38d481a5eba4d7ac4c9e74d9d0fc2a7e7", - "0xd839424e2e5ace0a81152298dc2b1e3bb3c7fb20", - "0xb8085c954b75b7088bcce69e61d12fcef797cd8d", - "0x9856dcb10fd6e5407fa74b5ab1d3b96cc193e9b7", - "0x505dff4e0827aa5065f5e001db888e0569d46490", - "0x25c6779d4610f940bf2488732e10bcffb9d36f81" - ] - }, - "optimism": { - "type": 3, - "threshold": 4, - "validators": [ - "0x9f2296d5cfc6b5176adc7716c7596898ded13d35", - "0x9c10bbe8efa03a8f49dfdb5c549258e3a8dca097", - "0x62144d4a52a0a0335ea5bb84392ef9912461d9dd", - "0xaff4718d5d637466ad07441ee3b7c4af8e328dbd", - "0xc64d1efeab8ae222bc889fe669f75d21b23005d9", - "0xfa174eb2b4921bb652bc1ada3e8b00e7e280bf3c" - ] - }, - "moonbeam": { - "type": 3, - "threshold": 3, - "validators": [ - "0x237243d32d10e3bdbbf8dbcccc98ad44c1c172ea", - "0x9509c8cf0a06955f27342262af501b74874e98fb", - "0xb7113c999e4d587b162dd1a28c73f3f51c6bdcdc", - "0x26725501597d47352a23cd26f122709f69ad53bc" - ] - }, - "gnosis": { - "type": 3, - "threshold": 3, - "validators": [ - "0xd0529ec8df08d0d63c0f023786bfa81e4bb51fd6", - "0x8a72ff8571c53c62c7ca02e8c97a443cd5674383", - "0x4075c2f6bd6d9562067cfe551d49c2bcafa7d692", - "0xa18580444eaeb1c5957e7b66a6bf84b6519f904d" - ] - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/multisig-config.json b/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/multisig-config.json deleted file mode 100644 index 5e08f27c0..000000000 --- a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/multisig-config.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "bsc": { - "type": 3, - "threshold": 1, - "validators": [ - "0x0000000000000000000000000000000000000001" - ] - }, - "nautilus": { - "type": 3, - "threshold": 2, - "validators": [ - "0x9c920af9467595a23cb3433adefc3854d498a437", - "0x87611503e37ce041527c11c24263e8760fccf81f", - "0x573443248cf9929af0001b88f62131f2de29fe9f" - ] - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/program-ids.json b/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/program-ids.json deleted file mode 100644 index 23f0cdd55..000000000 --- a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/nautilus/program-ids.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "program_id": "9k74DkJvS2x9QhG4XfnKsLkqaCDyVfaj8s6FyJyhAeEP" -} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/multisig-config.json b/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/multisig-config.json deleted file mode 100644 index fc090e25d..000000000 --- a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/multisig-config.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "celo": { - "type": 3, - "threshold": 1, - "validators": [ - "0xe7a82e210f512f8e9900d6bc2acbf7981c63e66e" - ] - }, - "ethereum": { - "type": 3, - "threshold": 1, - "validators": [ - "0xaea1adb1c687b061e5b60b9da84cb69e7b5fab44" - ] - }, - "avalanche": { - "type": 3, - "threshold": 1, - "validators": [ - "0x706976391e23dea28152e0207936bd942aba01ce" - ] - }, - "polygon": { - "type": 3, - "threshold": 1, - "validators": [ - "0xef372f6ff7775989b3ac884506ee31c79638c989" - ] - }, - "bsc": { - "type": 3, - "threshold": 1, - "validators": [ - "0x0823081031a4a6f97c6083775c191d17ca96d0ab" - ] - }, - "arbitrum": { - "type": 3, - "threshold": 1, - "validators": [ - "0x1a95b35fb809d57faf1117c1cc29a6c5df289df1" - ] - }, - "optimism": { - "type": 3, - "threshold": 1, - "validators": [ - "0x60e938bf280bbc21bacfd8bf435459d9003a8f98" - ] - }, - "moonbeam": { - "type": 3, - "threshold": 1, - "validators": [ - "0x0df7140811e309dc69638352545151ebb9d5e0fd" - ] - }, - "gnosis": { - "type": 3, - "threshold": 1, - "validators": [ - "0x15f48e78092a4f79febface509cfd76467c6cdbb" - ] - } -} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/program-ids.json b/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/program-ids.json deleted file mode 100644 index 0bf925699..000000000 --- a/rust/sealevel/environments/mainnet2/multisig-ism-message-id/solana/rc/program-ids.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "program_id": "BYTsxBuKVbwgsZFswzB91nrxveQySghwXzaKqn8exNnC" -} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet2/solana/core/program-ids.json b/rust/sealevel/environments/mainnet2/solana/core/program-ids.json deleted file mode 100644 index 53801da0c..000000000 --- a/rust/sealevel/environments/mainnet2/solana/core/program-ids.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "mailbox": "Ge9atjAc3Ltu91VTbNpJDCjZ9CFxFyck4h3YBcTF9XPq", - "validator_announce": "C88Lk5GR6cPxYoJxPbNDDEwsx5Kxn1wZEomvQ2So333g", - "multisig_ism_message_id": "6pHP4EeX2Xek24Be7PPTWCqcpmNEPENW1m9RnZSFSmA1", - "igp_program_id": "HksFWQM1EXJJ5mxo2uZoMfmksXHaNhCunh71NqcQQHZ8", - "overhead_igp_account": "GTj6WzNxLNFydq5zJrV9p13fyqotRoo1MQykNCWuVpbS", - "igp_account": "FCNfmLSZLo5x7oNYmkYU8WdPUu7pj636P9CaMxkmaCp7" -} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet2/warp-routes/zbc/program-ids.json b/rust/sealevel/environments/mainnet2/warp-routes/zbc/program-ids.json deleted file mode 100644 index 7d99aea92..000000000 --- a/rust/sealevel/environments/mainnet2/warp-routes/zbc/program-ids.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "solanamainnet": { - "hex": "0xc5ba229fa2822fe65ac2bd0a93d8371d75292c3415dd381923c1088a3308528b", - "base58": "EJqwFjvVJSAxH8Ur2PYuMfdvoJeutjmH6GkoEFQ4MdSa" - }, - "nautilus": { - "hex": "0x0000000000000000000000004501bbe6e731a4bc5c60c03a77435b2f6d5e9fe7", - "base58": "111111111111xm5qkrK7gZ8Cmjr4ggPLRxy2T8a" - } -} diff --git a/rust/sealevel/environments/mainnet2/warp-routes/zbc/token-config.json b/rust/sealevel/environments/mainnet2/warp-routes/zbc/token-config.json deleted file mode 100644 index 90b0e20ce..000000000 --- a/rust/sealevel/environments/mainnet2/warp-routes/zbc/token-config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "solanamainnet": { - "type": "collateral", - "decimals": 9, - "remoteDecimals": 9, - "token": "wzbcJyhGhQDLTV1S99apZiiBdE4jmYfbw99saMMdP59", - "splTokenProgram": "token", - "interchainSecurityModule": "9k74DkJvS2x9QhG4XfnKsLkqaCDyVfaj8s6FyJyhAeEP", - "owner": "EzppBFV2taxWw8kEjxNYvby6q7W1biJEqwP3iC7YgRe3" - }, - "nautilus": { - "type": "native", - "decimals": 18, - "foreignDeployment": "0x4501bBE6e731A4bC5c60C03A77435b2f6d5e9Fe7" - } -} diff --git a/rust/sealevel/environments/mainnet3/chain-config.json b/rust/sealevel/environments/mainnet3/chain-config.json index e21c91ccc..b2b896b9a 100644 --- a/rust/sealevel/environments/mainnet3/chain-config.json +++ b/rust/sealevel/environments/mainnet3/chain-config.json @@ -11,7 +11,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 888888888, "deployer": { @@ -35,7 +35,50 @@ "http": "https://rpc.ancient8.gg" } ], - "technicalStack": "other" + "technicalStack": "opstack" + }, + "alephzeroevm": { + "blockExplorers": [ + { + "apiUrl": "https://evm-explorer.alephzero.org/api", + "family": "blockscout", + "name": "Aleph Zero Explorer", + "url": "https://evm-explorer.alephzero.org" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 5 + }, + "chainId": 41455, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Aleph Zero EVM", + "displayNameShort": "Aleph Zero EVM", + "domainId": 41455, + "gasCurrencyCoinGeckoId": "aleph-zero", + "index": { + "from": 3421962 + }, + "name": "alephzeroevm", + "nativeToken": { + "decimals": 18, + "name": "AZERO", + "symbol": "AZERO" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.alephzero.raas.gelato.cloud" + }, + { + "http": "https://alephzero.drpc.org" + } + ], + "technicalStack": "arbitrumnitro" }, "arbitrum": { "blockExplorers": [ @@ -49,7 +92,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 42161, "deployer": { @@ -95,7 +138,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 13, - "reorgPeriod": 0 + "reorgPeriod": 32 }, "chainId": 592, "deployer": { @@ -116,7 +159,8 @@ { "http": "https://evm.astar.network" } - ] + ], + "technicalStack": "polkadotsubstrate" }, "astarzkevm": { "blockExplorers": [ @@ -130,7 +174,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 3776, "deployer": { @@ -154,7 +198,8 @@ { "http": "https://astar-zkevm-rpc.dwellir.com" } - ] + ], + "technicalStack": "polygoncdk" }, "avalanche": { "blockExplorers": [ @@ -197,7 +242,8 @@ "minBlockNumber": 6765067 } } - ] + ], + "technicalStack": "other" }, "base": { "blockExplorers": [ @@ -211,7 +257,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 10 }, "chainId": 8453, "deployer": { @@ -239,7 +285,8 @@ { "http": "https://base.blockpi.network/v1/rpc/public" } - ] + ], + "technicalStack": "opstack" }, "bitlayer": { "blockExplorers": [ @@ -253,7 +300,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 20 }, "chainId": 200901, "deployer": { @@ -280,7 +327,8 @@ { "http": "https://rpc.ankr.com/bitlayer" } - ] + ], + "technicalStack": "other" }, "blast": { "blockExplorers": [ @@ -294,7 +342,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 81457, "deployer": { @@ -320,7 +368,7 @@ "http": "https://rpc.ankr.com/blast" } ], - "technicalStack": "other" + "technicalStack": "opstack" }, "bob": { "blockExplorers": [ @@ -334,7 +382,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 60808, "deployer": { @@ -357,7 +405,7 @@ "http": "https://rpc.gobob.xyz" } ], - "technicalStack": "other" + "technicalStack": "opstack" }, "bsc": { "blockExplorers": [ @@ -401,6 +449,7 @@ "http": "https://bscrpc.com" } ], + "technicalStack": "other", "transactionOverrides": { "gasPrice": 3000000000 } @@ -445,21 +494,22 @@ { "http": "https://forno.celo.org" } - ] + ], + "technicalStack": "other" }, "cheesechain": { "blockExplorers": [ { - "apiUrl": "https://fetascan.io/api", + "apiUrl": "https://fetascan.xyz/api", "family": "blockscout", "name": "Fetascan", - "url": "https://fetascan.io" + "url": "https://fetascan.xyz" } ], "blocks": { "confirmations": 1, - "estimateBlockTime": 90, - "reorgPeriod": 0 + "estimateBlockTime": 30, + "reorgPeriod": 1 }, "chainId": 383353, "deployer": { @@ -487,6 +537,48 @@ ], "technicalStack": "arbitrumnitro" }, + "chiliz": { + "blockExplorers": [ + { + "apiUrl": "https://api.routescan.io/v2/network/mainnet/evm/88888/etherscan/api", + "family": "routescan", + "name": "Chiliscan", + "url": "https://chiliscan.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 3, + "reorgPeriod": 9 + }, + "chainId": 88888, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Chiliz", + "domainId": 88888, + "gasCurrencyCoinGeckoId": "chiliz", + "name": "chiliz", + "nativeToken": { + "decimals": 18, + "name": "Chiliz", + "symbol": "CHZ" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.ankr.com/chiliz" + }, + { + "http": "https://chiliz.publicnode.com" + } + ], + "technicalStack": "other", + "transactionOverrides": { + "maxPriorityFeePerGas": 1000000000 + } + }, "coredao": { "blockExplorers": [ { @@ -499,7 +591,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 21 }, "chainId": 1116, "deployer": { @@ -532,7 +624,8 @@ { "http": "https://rpc-core.icecreamswap.com" } - ] + ], + "technicalStack": "other" }, "cyber": { "blockExplorers": [ @@ -546,7 +639,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 7560, "deployer": { @@ -570,7 +663,8 @@ { "http": "https://cyber.alt.technology" } - ] + ], + "technicalStack": "opstack" }, "degenchain": { "blockExplorers": [ @@ -584,7 +678,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 10, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 666666666, "deployer": { @@ -623,7 +717,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 2000, "deployer": { @@ -644,7 +738,8 @@ { "http": "https://rpc.dogechain.dog" } - ] + ], + "technicalStack": "polygoncdk" }, "eclipsemainnet": { "blockExplorers": [ @@ -679,7 +774,8 @@ { "http": "https://mainnetbeta-rpc.eclipse.xyz" } - ] + ], + "technicalStack": "other" }, "endurance": { "blockExplorers": [ @@ -693,7 +789,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 12, - "reorgPeriod": 14 + "reorgPeriod": 15 }, "chainId": 648, "deployer": { @@ -715,7 +811,8 @@ { "http": "https://rpc-endurance.fusionist.io" } - ] + ], + "technicalStack": "other" }, "ethereum": { "blockExplorers": [ @@ -733,9 +830,9 @@ } ], "blocks": { - "confirmations": 3, + "confirmations": 2, "estimateBlockTime": 13, - "reorgPeriod": 14 + "reorgPeriod": 15 }, "chainId": 1, "deployer": { @@ -761,24 +858,21 @@ "http": "https://cloudflare-eth.com" } ], - "transactionOverrides": { - "maxFeePerGas": 150000000000, - "maxPriorityFeePerGas": 5000000000 - } + "technicalStack": "other" }, "everclear": { "blockExplorers": [ { - "apiUrl": "https://everclear.cloud.blockscout.com/api", + "apiUrl": "https://scan.everclear.org/api", "family": "blockscout", "name": "Everclear Explorer", - "url": "https://everclear.cloud.blockscout.com" + "url": "https://scan.everclear.org" } ], "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 2 }, "chainId": 25327, "deployer": { @@ -817,7 +911,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 3 }, "chainId": 14, "deployer": { @@ -847,7 +941,48 @@ { "http": "https://rpc.ankr.com/flare" } - ] + ], + "technicalStack": "other" + }, + "flow": { + "blockExplorers": [ + { + "apiUrl": "https://evm.flowscan.io/api", + "family": "blockscout", + "name": "EVM on Flow Explorer", + "url": "https://evm.flowscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 25 + }, + "chainId": 747, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "EVM on Flow", + "domainId": 747, + "gasCurrencyCoinGeckoId": "flow", + "isTestnet": false, + "name": "flow", + "nativeToken": { + "decimals": 18, + "name": "Flow", + "symbol": "FLOW" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet.evm.nodes.onflow.org" + } + ], + "technicalStack": "other", + "transactionOverrides": { + "gasPrice": 100000000 + } }, "fraxtal": { "blockExplorers": [ @@ -861,7 +996,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 252, "deployer": { @@ -886,7 +1021,8 @@ { "http": "https://fraxtal.drpc.org" } - ] + ], + "technicalStack": "opstack" }, "fusemainnet": { "blockExplorers": [ @@ -900,7 +1036,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 1 + "reorgPeriod": 19 }, "chainId": 122, "deployer": { @@ -931,7 +1067,8 @@ { "http": "https://fuse-pokt.nodies.app" } - ] + ], + "technicalStack": "other" }, "gnosis": { "blockExplorers": [ @@ -945,7 +1082,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 14 + "reorgPeriod": 5 }, "chainId": 100, "deployer": { @@ -971,7 +1108,51 @@ "minBlockNumber": 25997478 } } - ] + ], + "technicalStack": "other" + }, + "immutablezkevm": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.immutable.com/api/eth-rpc", + "family": "blockscout", + "name": "Immutable Explorer", + "url": "https://explorer.immutable.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 20 + }, + "chainId": 13371, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Immutable zkEVM", + "domainId": 13371, + "gasCurrencyCoinGeckoId": "immutable-x", + "name": "immutablezkevm", + "nativeToken": { + "decimals": 18, + "name": "Immutable", + "symbol": "IMX" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.immutable.com" + }, + { + "http": "https://immutable.gateway.tenderly.co" + } + ], + "technicalStack": "other", + "transactionOverrides": { + "maxFeePerGas": 100000000000, + "maxPriorityFeePerGas": 100000000000 + } }, "inevm": { "blockExplorers": [ @@ -985,7 +1166,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 3 }, "chainId": 2525, "deployer": { @@ -1055,7 +1236,8 @@ "http": "https://sentry.tm.injective.network:443" } ], - "slip44": 118 + "slip44": 118, + "technicalStack": "other" }, "kroma": { "blockExplorers": [ @@ -1069,7 +1251,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 255, "deployer": { @@ -1096,7 +1278,8 @@ { "http": "https://1rpc.io/kroma" } - ] + ], + "technicalStack": "opstack" }, "linea": { "blockExplorers": [ @@ -1110,7 +1293,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 59144, "deployer": { @@ -1141,7 +1324,8 @@ { "http": "https://linea.drpc.org" } - ] + ], + "technicalStack": "other" }, "lisk": { "blockExplorers": [ @@ -1155,7 +1339,7 @@ "blocks": { "confirmations": 3, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 1135, "deployer": { @@ -1176,7 +1360,8 @@ { "http": "https://rpc.api.lisk.com" } - ] + ], + "technicalStack": "opstack" }, "lukso": { "blockExplorers": [ @@ -1190,7 +1375,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 12, - "reorgPeriod": 14 + "reorgPeriod": 15 }, "chainId": 42, "deployer": { @@ -1217,7 +1402,47 @@ { "http": "https://42.rpc.thirdweb.com" } - ] + ], + "technicalStack": "other" + }, + "lumia": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.lumia.org/api/eth-rpc", + "family": "blockscout", + "name": "Lumia Prism Explorer", + "url": "https://explorer.lumia.org" + } + ], + "blocks": { + "confirmations": 3, + "estimateBlockTime": 4, + "reorgPeriod": 5 + }, + "chainId": 994873017, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Lumia Prism", + "domainId": 994873017, + "gasCurrencyCoinGeckoId": "orion-protocol", + "name": "lumia", + "nativeToken": { + "decimals": 18, + "name": "Lumia", + "symbol": "LUMIA" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://994873017.rpc.thirdweb.com" + }, + { + "http": "https://mainnet-rpc.lumia.org" + } + ], + "technicalStack": "polygoncdk" }, "mantapacific": { "blockExplorers": [ @@ -1231,7 +1456,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 169, "deployer": { @@ -1258,7 +1483,8 @@ { "http": "https://manta.nirvanalabs.xyz/mantapublic" } - ] + ], + "technicalStack": "opstack" }, "mantle": { "blockExplorers": [ @@ -1272,7 +1498,7 @@ "blocks": { "confirmations": 3, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 2 }, "chainId": 5000, "deployer": { @@ -1295,7 +1521,7 @@ "http": "https://rpc.mantle.xyz" } ], - "technicalStack": "other" + "technicalStack": "opstack" }, "merlin": { "blockExplorers": [ @@ -1309,7 +1535,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 4200, "deployer": { @@ -1333,7 +1559,45 @@ { "http": "https://merlin.blockpi.network/v1/rpc/public" } - ] + ], + "technicalStack": "polygoncdk" + }, + "metall2": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.metall2.com/api", + "family": "blockscout", + "name": "Metal L2 Explorer", + "url": "https://explorer.metall2.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 5 + }, + "chainId": 1750, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Metal L2", + "domainId": 1750, + "gasCurrencyCoinGeckoId": "ethereum", + "isTestnet": false, + "name": "metall2", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.metall2.com" + } + ], + "technicalStack": "opstack" }, "metis": { "blockExplorers": [ @@ -1347,7 +1611,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 1088, "deployer": { @@ -1372,7 +1636,7 @@ "http": "https://andromeda.metis.io/?owner=1088" } ], - "technicalStack": "arbitrumnitro" + "technicalStack": "opstack" }, "mint": { "blockExplorers": [ @@ -1386,7 +1650,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 185, "deployer": { @@ -1408,7 +1672,8 @@ { "http": "https://rpc.mintchain.io" } - ] + ], + "technicalStack": "opstack" }, "mode": { "blockExplorers": [ @@ -1422,7 +1687,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 34443, "deployer": { @@ -1448,7 +1713,7 @@ "http": "https://mode.drpc.org" } ], - "technicalStack": "other" + "technicalStack": "opstack" }, "molten": { "blockExplorers": [ @@ -1461,7 +1726,7 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 1, + "estimateBlockTime": 30, "reorgPeriod": 0 }, "chainId": 360, @@ -1501,7 +1766,7 @@ "blocks": { "confirmations": 2, "estimateBlockTime": 12, - "reorgPeriod": 2 + "reorgPeriod": 10 }, "chainId": 1284, "deployer": { @@ -1524,6 +1789,7 @@ "http": "https://rpc.api.moonbeam.network" } ], + "technicalStack": "polkadotsubstrate", "transactionOverrides": { "maxFeePerGas": 350000000000, "maxPriorityFeePerGas": 50000000000 @@ -1580,6 +1846,7 @@ } ], "slip44": 118, + "technicalStack": "other", "transactionOverrides": { "gasPrice": "0.0075" } @@ -1617,7 +1884,8 @@ { "http": "https://mainnet-rpc.oortech.com" } - ] + ], + "technicalStack": "other" }, "optimism": { "blockExplorers": [ @@ -1631,7 +1899,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 0 + "reorgPeriod": 10 }, "chainId": 10, "deployer": { @@ -1653,7 +1921,8 @@ { "http": "https://mainnet.optimism.io" } - ] + ], + "technicalStack": "opstack" }, "osmosis": { "bech32Prefix": "osmo", @@ -1703,6 +1972,7 @@ } ], "slip44": 118, + "technicalStack": "other", "transactionOverrides": { "gasPrice": "0.025" } @@ -1748,8 +2018,9 @@ "http": "https://rpc.ankr.com/polygon" } ], + "technicalStack": "other", "transactionOverrides": { - "maxFeePerGas": 550000000000, + "maxFeePerGas": 800000000000, "maxPriorityFeePerGas": 50000000000 } }, @@ -1765,7 +2036,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 10, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 1101, "deployer": { @@ -1792,10 +2063,47 @@ "http": "https://rpc.ankr.com/polygon_zkevm" } ], + "technicalStack": "polygoncdk", "transactionOverrides": { "gasPrice": 1000000000 } }, + "polynomial": { + "blockExplorers": [ + { + "apiUrl": "https://polynomialscan.io/api", + "family": "routescan", + "name": "Polynomial Explorer", + "url": "https://polynomialscan.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 5 + }, + "chainId": 8008, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Polynomial", + "domainId": 8008, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "polynomial", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.polynomial.fi" + } + ], + "technicalStack": "opstack" + }, "proofofplay": { "blockExplorers": [ { @@ -1808,7 +2116,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 1, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 70700, "deployer": { @@ -1835,6 +2143,45 @@ ], "technicalStack": "arbitrumnitro" }, + "rari": { + "blockExplorers": [ + { + "apiUrl": "https://mainnet.explorer.rarichain.org/api", + "family": "blockscout", + "name": "Rari Mainnet Explorer", + "url": "https://mainnet.explorer.rarichain.org" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 30, + "reorgPeriod": 0 + }, + "chainId": 1380012617, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "RARI Chain", + "domainId": 1380012617, + "gasCurrencyCoinGeckoId": "ethereum", + "index": { + "from": 541753 + }, + "name": "rari", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet.rpc.rarichain.org/http" + } + ], + "technicalStack": "arbitrumnitro" + }, "real": { "blockExplorers": [ { @@ -1846,7 +2193,7 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 4, + "estimateBlockTime": 30, "reorgPeriod": 0 }, "chainId": 111188, @@ -1886,7 +2233,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 690, "deployer": { @@ -1908,7 +2255,53 @@ { "http": "https://rpc.redstonechain.com" } - ] + ], + "technicalStack": "opstack" + }, + "rootstock": { + "blockExplorers": [ + { + "apiUrl": "https://rootstock.blockscout.com/api", + "family": "blockscout", + "name": "Blockscout", + "url": "https://rootstock.blockscout.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 30, + "reorgPeriod": 4 + }, + "chainId": 30, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Rootstock", + "domainId": 30, + "gasCurrencyCoinGeckoId": "rootstock", + "name": "rootstock", + "nativeToken": { + "decimals": 18, + "name": "Rootstock Smart Bitcoin", + "symbol": "RBTC" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.mainnet.rootstock.io/kXhXHf6TnnfW1POvr4UT0YUvujmuju-M" + }, + { + "http": "https://public-node.rsk.co" + }, + { + "http": "https://mycrypto.rsk.co" + } + ], + "technicalStack": "other", + "transactionOverrides": { + "gasPrice": 70000000 + } }, "sanko": { "blockExplorers": [ @@ -1921,8 +2314,8 @@ ], "blocks": { "confirmations": 1, - "estimateBlockTime": 10, - "reorgPeriod": 0 + "estimateBlockTime": 15, + "reorgPeriod": 1 }, "chainId": 1996, "deployer": { @@ -1961,7 +2354,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 3, - "reorgPeriod": 30 + "reorgPeriod": 17 }, "chainId": 534352, "deployer": { @@ -1984,8 +2377,9 @@ "http": "https://scroll.blockpi.network/v1/rpc/public" } ], + "technicalStack": "other", "transactionOverrides": { - "gasPrice": 2000000000 + "gasPrice": 200000000 } }, "sei": { @@ -2023,6 +2417,7 @@ "http": "https://evm-rpc.sei-apis.com" } ], + "technicalStack": "other", "transactionOverrides": { "gasPrice": 101000000000 } @@ -2039,7 +2434,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 5, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 109, "deployer": { @@ -2063,15 +2458,16 @@ { "http": "https://rpc.shibrpc.com" } - ] + ], + "technicalStack": "other" }, "solanamainnet": { "blockExplorers": [ { - "apiUrl": "https://explorer.solana.com?cluster=mainnet-beta", + "apiUrl": "https://solscan.io", "family": "other", "name": "Solana Explorer", - "url": "https://explorer.solana.com?cluster=mainnet-beta" + "url": "https://solscan.io" } ], "blocks": { @@ -2098,7 +2494,99 @@ { "http": "https://api.mainnet-beta.solana.com" } - ] + ], + "technicalStack": "other" + }, + "stride": { + "bech32Prefix": "stride", + "blockExplorers": [ + { + "apiUrl": "https://www.mintscan.io/stride", + "family": "other", + "name": "Mintscan", + "url": "https://www.mintscan.io/stride" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 5, + "reorgPeriod": 1 + }, + "chainId": "stride-1", + "deployer": { + "name": "Stride Labs", + "url": "https://www.stride.zone" + }, + "displayName": "Stride", + "domainId": 745, + "gasCurrencyCoinGeckoId": "stride", + "grpcUrls": [ + { + "http": "stride-grpc.polkachu.com:12290" + } + ], + "isTestnet": false, + "name": "stride", + "nativeToken": { + "decimals": 6, + "denom": "ustrd", + "name": "Stride", + "symbol": "STRD" + }, + "protocol": "cosmos", + "restUrls": [ + { + "http": "https://stride-api.polkachu.com" + } + ], + "rpcUrls": [ + { + "http": "https://stride-rpc.polkachu.com" + } + ], + "slip44": 118, + "transactionOverrides": { + "gasPrice": "0.0025" + } + }, + "superposition": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.superposition.so/api", + "family": "blockscout", + "name": "Superposition Explorer", + "url": "https://explorer.superposition.so/" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 60, + "reorgPeriod": 0 + }, + "chainId": 55244, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Superposition", + "domainId": 55244, + "gasCurrencyCoinGeckoId": "ethereum", + "index": { + "from": 1201 + }, + "name": "superposition", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.superposition.so" + } + ], + "technicalStack": "arbitrumnitro" }, "taiko": { "blockExplorers": [ @@ -2112,7 +2600,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 12, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 167000, "deployer": { @@ -2149,7 +2637,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 6, - "reorgPeriod": 0 + "reorgPeriod": 10 }, "chainId": 5845, "deployer": { @@ -2171,7 +2659,8 @@ { "http": "https://rpc.tangle.tools" } - ] + ], + "technicalStack": "polkadotsubstrate" }, "viction": { "blockExplorers": [ @@ -2185,7 +2674,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 3 }, "chainId": 88, "deployer": { @@ -2209,7 +2698,8 @@ { "http": "https://viction.blockpi.network/v1/rpc/public" } - ] + ], + "technicalStack": "other" }, "worldchain": { "blockExplorers": [ @@ -2223,7 +2713,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 480, "deployer": { @@ -2244,7 +2734,8 @@ { "http": "https://raas-backend.alchemy.com/rpc/worldchain-mainnet/rollup" } - ] + ], + "technicalStack": "opstack" }, "xai": { "blockExplorers": [ @@ -2258,7 +2749,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 1, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 660279, "deployer": { @@ -2297,7 +2788,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 10, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 196, "deployer": { @@ -2323,7 +2814,8 @@ { "http": "https://rpc.xlayer.tech" } - ] + ], + "technicalStack": "polygoncdk" }, "zetachain": { "blockExplorers": [ @@ -2362,7 +2854,8 @@ { "http": "https://zetachain-mainnet.g.allthatnode.com/archive/evm" } - ] + ], + "technicalStack": "other" }, "zircuit": { "blockExplorers": [ @@ -2376,7 +2869,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 0 + "reorgPeriod": 5 }, "chainId": 48900, "deployer": { @@ -2404,7 +2897,8 @@ { "http": "https://zircuit-mainnet.drpc.org" } - ] + ], + "technicalStack": "opstack" }, "zoramainnet": { "blockExplorers": [ @@ -2418,7 +2912,7 @@ "blocks": { "confirmations": 1, "estimateBlockTime": 2, - "reorgPeriod": 1 + "reorgPeriod": 5 }, "chainId": 7777777, "deployer": { @@ -2440,6 +2934,7 @@ { "http": "https://rpc.zora.energy" } - ] + ], + "technicalStack": "opstack" } } diff --git a/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json b/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json index 595a33b03..2966c15b5 100644 --- a/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json +++ b/rust/sealevel/environments/mainnet3/multisig-ism-message-id/eclipsemainnet/hyperlane/multisig-config.json @@ -1,4 +1,13 @@ { + "alephzeroevm": { + "threshold": 2, + "validators": [ + "0xcae8fab142adc4e434bb7409e40dd932cc3851aa", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" + }, "ancient8": { "threshold": 2, "validators": [ @@ -6,7 +15,7 @@ "0xa5a56e97fb46f0ac3a3d261e404acb998d9a6969", "0x95c7bf235837cb5a609fe6c95870410b9f68bcff" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "arbitrum": { "threshold": 3, @@ -17,7 +26,7 @@ "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", "0xb3ac35d3988bca8c2ffd195b1c6bee18536b317b" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "astar": { "threshold": 2, @@ -26,7 +35,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "astarzkevm": { "threshold": 2, @@ -35,7 +44,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "avalanche": { "threshold": 2, @@ -44,7 +53,7 @@ "0x402e0f8c6e4210d408b6ac00d197d4a099fcd25a", "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "base": { "threshold": 3, @@ -55,7 +64,7 @@ "0xcff391b4e516452d424db66beb9052b041a9ed79", "0x5450447aee7b544c462c9352bef7cad049b0c2dc" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "bitlayer": { "threshold": 2, @@ -64,7 +73,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "blast": { "threshold": 2, @@ -73,7 +82,7 @@ "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36", "0xae53467a5c2a9d9420c188d10fef5e1d9b9a5b80" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "bob": { "threshold": 2, @@ -82,7 +91,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "bsc": { "threshold": 3, @@ -92,7 +101,7 @@ "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", "0x5450447aee7b544c462c9352bef7cad049b0c2dc" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "celo": { "threshold": 3, @@ -103,7 +112,7 @@ "0xb3ac35d3988bca8c2ffd195b1c6bee18536b317b", "0x5450447aee7b544c462c9352bef7cad049b0c2dc" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "cheesechain": { "threshold": 2, @@ -111,7 +120,16 @@ "0x478fb53c6860ae8fc35235ba0d38d49b13128226", "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "chiliz": { + "threshold": 2, + "validators": [ + "0x82d024f453b1a3f3f6606226f06b038da27596f3", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "coredao": { "threshold": 2, @@ -120,7 +138,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "cyber": { "threshold": 2, @@ -129,7 +147,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "degenchain": { "threshold": 2, @@ -138,7 +156,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "dogechain": { "threshold": 2, @@ -147,7 +165,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "endurance": { "threshold": 2, @@ -156,7 +174,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x7419021c0de2772b763e554480158a82a291c1f2" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "ethereum": { "threshold": 4, @@ -169,7 +187,7 @@ "0xb683b742b378632a5f73a2a5a45801b3489bba44", "0xbf1023eff3dba21263bf2db2add67a0d6bcda2de" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "everclear": { "threshold": 2, @@ -178,7 +196,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0xD79DFbF56ee2268f061cc613027a44A880f61Ba2" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "flare": { "threshold": 2, @@ -187,7 +205,16 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "flow": { + "threshold": 2, + "validators": [ + "0x3aee1090318e9c54d1d23194dcd0f2bee00ddc97", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "fraxtal": { "threshold": 2, @@ -196,7 +223,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x25b3a88f7cfd3c9f7d7e32b295673a16a6ddbd91" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "fusemainnet": { "threshold": 2, @@ -205,7 +232,7 @@ "0x6760226b34213d262D41D5291Ed57E81a68b4E0b", "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "gnosis": { "threshold": 3, @@ -215,7 +242,16 @@ "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", "0x5450447aee7b544c462c9352bef7cad049b0c2dc" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "immutablezkevm": { + "threshold": 2, + "validators": [ + "0xa787c2952a4d22f776ee6e87e828e6f75de24330", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "inevm": { "threshold": 2, @@ -224,7 +260,7 @@ "0x6B1d09A97b813D53e9D4b7523DA36604C0B52242", "0x9ab11f38a609940153850df611c9a2175dcffe0f" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "injective": { "threshold": 2, @@ -233,7 +269,7 @@ "0x6B1d09A97b813D53e9D4b7523DA36604C0B52242", "0x9e551b6694bbd295d7d6e6a2540c7d41ce70a3b9" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "kroma": { "threshold": 2, @@ -242,7 +278,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "linea": { "threshold": 2, @@ -251,7 +287,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "lisk": { "threshold": 2, @@ -260,7 +296,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "lukso": { "threshold": 2, @@ -269,10 +305,19 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x101cE77261245140A0871f9407d6233C8230Ec47" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "lumia": { + "threshold": 2, + "validators": [ + "0x9e283254ed2cd2c80f007348c2822fc8e5c2fa5f", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "mantapacific": { - "threshold": 5, + "threshold": 4, "validators": [ "0x8e668c97ad76d0e28375275c41ece4972ab8a5bc", "0x521a3e6bf8d24809fde1c1fd3494a859a16f132c", @@ -282,7 +327,7 @@ "0xcc9a0b6de7fe314bd99223687d784730a75bb957", "0x42b6de2edbaa62c2ea2309ad85d20b3e37d38acf" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "mantle": { "threshold": 2, @@ -291,7 +336,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "merlin": { "threshold": 2, @@ -300,7 +345,16 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "metall2": { + "threshold": 2, + "validators": [ + "0x1b000e1e1f0a032ed382c6d69a2d58f6fe773c09", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "metis": { "threshold": 2, @@ -309,7 +363,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "mint": { "threshold": 2, @@ -318,7 +372,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x0230505530b80186f8cdccfaf9993eb97aebe98a" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "mode": { "threshold": 3, @@ -328,7 +382,7 @@ "0x7e29608c6e5792bbf9128599ca309be0728af7b4", "0x101cE77261245140A0871f9407d6233C8230Ec47" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "molten": { "threshold": 2, @@ -337,7 +391,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "moonbeam": { "threshold": 3, @@ -347,7 +401,7 @@ "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", "0xb3ac35d3988bca8c2ffd195b1c6bee18536b317b" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "neutron": { "threshold": 4, @@ -360,7 +414,7 @@ "0x54b2cca5091b098a1a993dec03c4d1ee9af65999", "0x42b6de2edbaa62c2ea2309ad85d20b3e37d38acf" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "oortmainnet": { "threshold": 2, @@ -369,7 +423,7 @@ "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36", "0x032dE4f94676bF9314331e7D83E8Db4aC74c9E21" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "optimism": { "threshold": 3, @@ -380,14 +434,14 @@ "0xb3ac35d3988bca8c2ffd195b1c6bee18536b317b", "0x5450447aee7b544c462c9352bef7cad049b0c2dc" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "osmosis": { "threshold": 1, "validators": [ "0xea483af11c19fa41b16c31d1534c2a486a92bcac" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "polygon": { "threshold": 3, @@ -397,7 +451,7 @@ "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", "0x5450447aee7b544c462c9352bef7cad049b0c2dc" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "polygonzkevm": { "threshold": 2, @@ -406,7 +460,16 @@ "0x865818fe1db986036d5fd0466dcd462562436d1a", "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "polynomial": { + "threshold": 2, + "validators": [ + "0xa63ad0891e921ad5947d57e05831fabb9816eca7", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "proofofplay": { "threshold": 2, @@ -415,7 +478,16 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "rari": { + "threshold": 2, + "validators": [ + "0x989d6862e09de21337078efbd86843a3eb1133e3", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "real": { "threshold": 2, @@ -424,7 +496,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "redstone": { "threshold": 2, @@ -433,7 +505,16 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "rootstock": { + "threshold": 2, + "validators": [ + "0xcb8e3a72cf427feff27416d0e2ec375a052eaaee", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "sanko": { "threshold": 2, @@ -442,7 +523,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "scroll": { "threshold": 3, @@ -452,7 +533,7 @@ "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", "0xbac4ac39f1d8b5ef15f26fdb1294a7c9aba3f948" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "sei": { "threshold": 3, @@ -462,7 +543,7 @@ "0x101cE77261245140A0871f9407d6233C8230Ec47", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "shibarium": { "threshold": 2, @@ -471,7 +552,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "solanamainnet": { "threshold": 3, @@ -482,7 +563,32 @@ "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", "0xcb6bcbd0de155072a7ff486d9d7286b0f71dcc2d" ], - "type": 3 + "type": "messageIdMultisigIsm" + }, + "stride": { + "threshold": 4, + "validators": [ + "0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8", + "0x88f0E5528131b10e3463C4c68108217Dd33462ac", + "0xa3eaa1216827ad63dd9db43f6168258a89177990", + "0x3f869C36110F00D10dC74cca3ac1FB133cf019ad", + "0x502dC6135d16E74056f609FBAF76846814C197D3", + "0xc36979780c1aD43275182600a61Ce41f1C390FbE", + "0x87460dcEd16a75AECdBffD4189111d30B099f5b0", + "0xf54982134e52Eb7253236943FBffE0886C5bde0C", + "0x5937b7cE1029C3Ec4bD8e1AaCc0C0f9422654D7d", + "0x3a446ed2923c08445af06e53f0acb558c0e0413c" + ], + "type": "messageIdMultisigIsm" + }, + "superposition": { + "threshold": 2, + "validators": [ + "0x5978d0e6afa9270ddb87cff43a8fa7a763a5dfc4", + "0xCF0211faFBb91FD9D06D7E306B30032DC3A1934f", + "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" + ], + "type": "messageIdMultisigIsm" }, "taiko": { "threshold": 3, @@ -492,7 +598,7 @@ "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36", "0x2F007c82672F2Bb97227D4e3F80Ac481bfB40A2a" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "tangle": { "threshold": 2, @@ -501,7 +607,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0xe271ef9a6e312540f099a378865432fa73f26689" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "viction": { "threshold": 2, @@ -510,7 +616,7 @@ "0xa3f93fe365bf99f431d8fde740b140615e24f99b", "0x1f87c368f8e05a85ef9126d984a980a20930cb9c" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "worldchain": { "threshold": 2, @@ -519,7 +625,7 @@ "0x11e2a683e83617f186614071e422b857256a9aae", "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "xai": { "threshold": 2, @@ -528,7 +634,7 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "xlayer": { "threshold": 2, @@ -537,7 +643,7 @@ "0xfed056cC0967F5BC9C6350F6C42eE97d3983394d", "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "zetachain": { "threshold": 3, @@ -547,7 +653,7 @@ "0x101cE77261245140A0871f9407d6233C8230Ec47", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "zircuit": { "threshold": 3, @@ -557,7 +663,7 @@ "0x0180444c9342BD672867Df1432eb3dA354413a6E", "0x1da9176C2CE5cC7115340496fa7D1800a98911CE" ], - "type": 3 + "type": "messageIdMultisigIsm" }, "zoramainnet": { "threshold": 3, @@ -567,6 +673,6 @@ "0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f", "0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36" ], - "type": 3 + "type": "messageIdMultisigIsm" } } diff --git a/typescript/infra/scripts/print-multisig-ism-config.ts b/typescript/infra/scripts/print-multisig-ism-config.ts deleted file mode 100644 index 61ff67fa3..000000000 --- a/typescript/infra/scripts/print-multisig-ism-config.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { IsmType } from '@hyperlane-xyz/sdk'; - -import { multisigIsms } from '../config/multisigIsm.js'; -import { getChains } from '../config/registry.js'; - -import { getArgs, withContext } from './agent-utils.js'; - -// This script exists to print the default multisig ISM validator sets for a given environment -// so they can easily be copied into the Sealevel tooling. :'( - -async function main() { - const args = await withContext(getArgs()) - .describe('local', 'local chain') - .choices('local', getChains()) - .demandOption('local').argv; - - const config = multisigIsms( - args.environment, - args.local, - IsmType.MESSAGE_ID_MULTISIG, - args.context, - ); - - console.log(JSON.stringify(config, null, 2)); -} - -main().catch((err) => { - console.error(err); - process.exit(1); -}); diff --git a/typescript/infra/scripts/print-chain-metadatas.ts b/typescript/infra/scripts/sealevel-helpers/print-chain-metadatas.ts similarity index 87% rename from typescript/infra/scripts/print-chain-metadatas.ts rename to typescript/infra/scripts/sealevel-helpers/print-chain-metadatas.ts index ff8f771fe..49473e5dd 100644 --- a/typescript/infra/scripts/print-chain-metadatas.ts +++ b/typescript/infra/scripts/sealevel-helpers/print-chain-metadatas.ts @@ -1,7 +1,7 @@ import { pick } from '@hyperlane-xyz/utils'; -import { getArgs } from './agent-utils.js'; -import { getEnvironmentConfig } from './core-utils.js'; +import { getArgs } from '../agent-utils.js'; +import { getEnvironmentConfig } from '../core-utils.js'; // This script exists to print the chain metadata configs for a given environment // so they can easily be copied into the Sealevel tooling. :'( diff --git a/typescript/infra/scripts/sealevel-helpers/print-multisig-ism-config.ts b/typescript/infra/scripts/sealevel-helpers/print-multisig-ism-config.ts new file mode 100644 index 000000000..69646ff01 --- /dev/null +++ b/typescript/infra/scripts/sealevel-helpers/print-multisig-ism-config.ts @@ -0,0 +1,50 @@ +import { IsmType } from '@hyperlane-xyz/sdk'; + +import { multisigIsms } from '../../config/multisigIsm.js'; +import { getChains } from '../../config/registry.js'; +import { getArgs, withContext } from '../agent-utils.js'; + +// This script exists to print the default multisig ISM validator sets for a given environment +// so they can easily be copied into the Sealevel tooling. :'( + +async function main() { + const args = await withContext(getArgs()) + .describe('local', 'local chain') + .choices('local', getChains()) + .demandOption('local').argv; + + const config = multisigIsms( + args.environment, + args.local, + IsmType.MESSAGE_ID_MULTISIG, + args.context, + ); + + // Cap any thresholds to 4 due to the Sealevel transaction size limit. + // Any higher than 4 at the moment will cause warp route synthetic deliveries to fail. + // Example message Solana -> Eclipse that mints a synthetic: + // https://explorer.eclipse.xyz/tx/3wcMvqZZjQon9o8nD49e3ci16AUJopZRLAfsAfs16ZrxgoNLoboNvrbV1hQHbnN3KXrWSqHmKnmM28mUvh5Un5Hd/inspect. + // At the time, the Solana threshold was 3. Taking the max tx size of 1232 and the tx's size 1121, + // we can find the number of additional signatures to be: floor((1232 - 1121)/65) = floor(1.707) = 1. + // So the total number of signatures is 3 + 1 = 4. + + const MAX_THRESHOLD = 4; + + for (const chain of Object.keys(config)) { + if (config[chain].threshold > MAX_THRESHOLD) { + console.warn( + `Threshold for ${chain} is ${config[chain].threshold}. Capping to ${MAX_THRESHOLD}.`, + ); + config[chain].threshold = MAX_THRESHOLD; + } + } + + console.warn; + + console.log(JSON.stringify(config, null, 2)); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); From 89c60ab9c0ed7eeb5720aa1e06a5ab4029c6f482 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 24 Oct 2024 17:10:41 +0100 Subject: [PATCH 189/224] feat: update Stride IGP to our own, temporarily whitelist our Stride deployment (#4748) ### Description - We have an IGP on Stride now. We expect not to fully index this till at least Friday - so for now we just whitelist the messages we care about. ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --------- Co-authored-by: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> --- .registryrc | 2 +- rust/main/config/mainnet_config.json | 2 +- typescript/infra/config/environments/mainnet3/agent.ts | 10 +++++++++- .../mainnet3/warp/eclipse-stride-TIA-addresses.json | 8 ++++++++ .../mainnet3/warp/eclipse-stride-stTIA-addresses.json | 8 ++++++++ 5 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 typescript/infra/config/environments/mainnet3/warp/eclipse-stride-TIA-addresses.json create mode 100644 typescript/infra/config/environments/mainnet3/warp/eclipse-stride-stTIA-addresses.json diff --git a/.registryrc b/.registryrc index a694b325b..265b47093 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -65b3c54ede7bf2b56280b913b8ed57bb08f52a36 +18666269e99ad8d2ba45579c4be783478e50e936 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index 7f147b6e0..fee83dfbd 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -4829,7 +4829,7 @@ } ], "slip44": 118, - "interchainGasPaymaster": "0x0000000000000000000000000000000000000000000000000000000000000000", + "interchainGasPaymaster": "0x602D5BF31F85FE90BF812A5EE6E2CC8CF6998A687125CABEDD120983CB88DA54", "mailbox": "0x89945750e089d84581f194e1947a58480b335f18386ad4f761f05feebf5e2454", "merkleTreeHook": "0x7ab4a8c3ba5371e34cd8d5dc584e0d924504fc21c3cbf41c3f64d436176bf007", "validatorAnnounce": "0xf57d954bf3ddb5f1032a0e020a99e931215cf83ceb4de987c781488065aaae0d", diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index fa21db977..d6999cd18 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -27,6 +27,8 @@ import { validatorChainConfig } from './validators.js'; import ancient8EthereumUsdcAddresses from './warp/ancient8-USDC-addresses.json'; import arbitrumTIAAddresses from './warp/arbitrum-TIA-addresses.json'; import arbitrumNeutronEclipAddresses from './warp/arbitrum-neutron-eclip-addresses.json'; +import eclipseStrideTiaAddresses from './warp/eclipse-stride-TIA-addresses.json'; +import eclipseStrideStTiaAddresses from './warp/eclipse-stride-stTIA-addresses.json'; import inevmEthereumUsdcAddresses from './warp/inevm-USDC-addresses.json'; import inevmEthereumUsdtAddresses from './warp/inevm-USDT-addresses.json'; import injectiveInevmInjAddresses from './warp/injective-inevm-addresses.json'; @@ -311,7 +313,13 @@ const gasPaymentEnforcement: GasPaymentEnforcement[] = [ // warp routes that we know are certainly paying for gas. { type: GasPaymentEnforcementPolicyType.None, - matchingList: [...routerMatchingList(injectiveInevmInjAddresses)], + matchingList: [ + ...routerMatchingList(injectiveInevmInjAddresses), + // As we are still indexing the IGP on Stride, temporarily whitelist + // Stride to Eclipse messages. + ...routerMatchingList(eclipseStrideTiaAddresses), + ...routerMatchingList(eclipseStrideStTiaAddresses), + ], }, { type: GasPaymentEnforcementPolicyType.OnChainFeeQuoting, diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-TIA-addresses.json b/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-TIA-addresses.json new file mode 100644 index 000000000..67cf44d89 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-TIA-addresses.json @@ -0,0 +1,8 @@ +{ + "eclipsemainnet": { + "router": "0xa0c167513f4d025217a48891973c3dbe41e10e76230033ef5d676299a18ca7f5" + }, + "stride": { + "router": "stride1pvtesu3ve7qn7ctll2x495mrqf2ysp6fws68grvcu6f7n2ajghgsh2jdj6" + } +} diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-stTIA-addresses.json b/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-stTIA-addresses.json new file mode 100644 index 000000000..538b9fe9a --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-stride-stTIA-addresses.json @@ -0,0 +1,8 @@ +{ + "eclipsemainnet": { + "router": "0x0d258188d0761163da174da890d0c1becdee51a01dbc9e2a6bfcb342140eb509" + }, + "stride": { + "router": "stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee" + } +} From a42616ff3fc297d0fb218d143861a397a491a035 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Fri, 25 Oct 2024 06:41:50 +0530 Subject: [PATCH 190/224] fix(contracts): add rebasing compatibility for `HypERC4626` (#4524) ### Description - Added overrides for transferFrom, totalSupply to reflect the internal share based accounting for the 4626 mirror asset ### Drive-by changes - Overridden `_transfer` to update the Transfer event to display the asset being transfers as amount not the internal shares. ### Related issues - fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/6 ### Backward compatibility Yes ### Testing Fuzz testing --- .changeset/real-starfishes-fold.md | 5 + .../contracts/token/extensions/HypERC4626.sol | 95 +++++++++---- solidity/test/token/HypERC4626Test.t.sol | 133 ++++++++++++++++++ .../EvmERC20WarpRouteReader.hardhat-test.ts | 1 - typescript/sdk/src/token/deploy.ts | 4 +- typescript/sdk/src/token/schemas.ts | 7 +- 6 files changed, 212 insertions(+), 33 deletions(-) create mode 100644 .changeset/real-starfishes-fold.md diff --git a/.changeset/real-starfishes-fold.md b/.changeset/real-starfishes-fold.md new file mode 100644 index 000000000..f161beae6 --- /dev/null +++ b/.changeset/real-starfishes-fold.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': patch +--- + +Added overrides for transferFrom, totalSupply to reflect the internal share based accounting for the 4626 mirror asset diff --git a/solidity/contracts/token/extensions/HypERC4626.sol b/solidity/contracts/token/extensions/HypERC4626.sol index 9ceb5536b..7ad9c1842 100644 --- a/solidity/contracts/token/extensions/HypERC4626.sol +++ b/solidity/contracts/token/extensions/HypERC4626.sol @@ -22,10 +22,13 @@ import {TokenRouter} from "../libs/TokenRouter.sol"; // ============ External Imports ============ import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; /** * @title Hyperlane ERC20 Rebasing Token * @author Abacus Works + * @notice This contract implements a rebasing token that reflects yields from the origin chain */ contract HypERC4626 is HypERC20 { using Math for uint256; @@ -49,6 +52,67 @@ contract HypERC4626 is HypERC20 { _disableInitializers(); } + // ============ Public Functions ============ + + /// Override transfer to handle underlying amounts while using shares internally + /// @inheritdoc ERC20Upgradeable + /// @dev the Transfer event emitted from ERC20Upgradeable will be in terms of shares not assets, so it may be misleading + function transfer( + address to, + uint256 amount + ) public virtual override returns (bool) { + _transfer(_msgSender(), to, assetsToShares(amount)); + return true; + } + + /// Override transferFrom to handle underlying amounts while using shares internally + /// @inheritdoc ERC20Upgradeable + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + address spender = _msgSender(); + uint256 shares = assetsToShares(amount); + _spendAllowance(sender, spender, amount); + _transfer(sender, recipient, shares); + return true; + } + + /// Override totalSupply to return the total assets instead of shares. This reflects the actual circulating supply in terms of assets, accounting for rebasing + /// @inheritdoc ERC20Upgradeable + function totalSupply() public view virtual override returns (uint256) { + return sharesToAssets(totalShares()); + } + + /// This returns the balance of the account in terms of assets, accounting for rebasing + /// @inheritdoc ERC20Upgradeable + function balanceOf( + address account + ) public view virtual override returns (uint256) { + return sharesToAssets(shareBalanceOf(account)); + } + + /// This function provides the total supply in terms of shares + function totalShares() public view returns (uint256) { + return super.totalSupply(); + } + + /// This returns the balance of the account in terms of shares + function shareBalanceOf(address account) public view returns (uint256) { + return super.balanceOf(account); + } + + function assetsToShares(uint256 _amount) public view returns (uint256) { + return _amount.mulDiv(PRECISION, exchangeRate); + } + + function sharesToAssets(uint256 _shares) public view returns (uint256) { + return _shares.mulDiv(exchangeRate, PRECISION); + } + + // ============ Internal Functions ============ + /// Override to send shares instead of assets from synthetic /// @inheritdoc TokenRouter function _transferRemote( @@ -78,6 +142,8 @@ contract HypERC4626 is HypERC20 { emit SentTransferRemote(_destination, _recipient, _amountOrId); } + /// override _handle to update exchange rate + /// @inheritdoc TokenRouter function _handle( uint32 _origin, bytes32 _sender, @@ -97,33 +163,4 @@ contract HypERC4626 is HypERC20 { } super._handle(_origin, _sender, _message); } - - // Override to send shares locally instead of assets - function transfer( - address to, - uint256 amount - ) public virtual override returns (bool) { - address owner = _msgSender(); - _transfer(owner, to, assetsToShares(amount)); - return true; - } - - function shareBalanceOf(address account) public view returns (uint256) { - return super.balanceOf(account); - } - - function balanceOf( - address account - ) public view virtual override returns (uint256) { - uint256 _balance = super.balanceOf(account); - return sharesToAssets(_balance); - } - - function assetsToShares(uint256 _amount) public view returns (uint256) { - return _amount.mulDiv(PRECISION, exchangeRate); - } - - function sharesToAssets(uint256 _shares) public view returns (uint256) { - return _shares.mulDiv(exchangeRate, PRECISION); - } } diff --git a/solidity/test/token/HypERC4626Test.t.sol b/solidity/test/token/HypERC4626Test.t.sol index ef9243148..d5aecb8e2 100644 --- a/solidity/test/token/HypERC4626Test.t.sol +++ b/solidity/test/token/HypERC4626Test.t.sol @@ -113,6 +113,11 @@ contract HypERC4626CollateralTest is HypTokenTest { _connectRouters(domains, addresses); } + function testDisableInitializers() public { + vm.expectRevert("Initializable: contract is already initialized"); + remoteToken.initialize(0, "", "", address(0), address(0), address(0)); + } + function test_collateralDomain() public view { assertEq( remoteRebasingToken.collateralDomain(), @@ -242,6 +247,108 @@ contract HypERC4626CollateralTest is HypTokenTest { ); } + function testTransferFrom() public { + _performRemoteTransferWithoutExpectation(0, transferAmount); + assertEq(remoteToken.balanceOf(BOB), transferAmount); + + uint256 transferAmount2 = 50e18; + vm.prank(BOB); + remoteToken.approve(CAROL, transferAmount2); + + vm.prank(CAROL); + bool success = remoteToken.transferFrom(BOB, DANIEL, transferAmount2); + assertTrue(success, "TransferFrom should succeed"); + + assertEq( + remoteToken.balanceOf(BOB), + transferAmount - transferAmount2, + "BOB's balance should decrease" + ); + assertEq( + remoteToken.balanceOf(DANIEL), + transferAmount2, + "DANIEL's balance should increase" + ); + assertEq( + remoteToken.allowance(BOB, CAROL), + 0, + "Allowance should be zero after transfer" + ); + } + + event Transfer(address indexed from, address indexed to, uint256 value); + + function testTransferEvent() public { + _performRemoteTransferWithoutExpectation(0, transferAmount); + assertEq(remoteToken.balanceOf(BOB), transferAmount); + + uint256 transferAmount2 = 50e18; + vm.expectEmit(true, true, false, true); + emit Transfer(BOB, CAROL, transferAmount2); + + vm.prank(BOB); + remoteToken.transfer(CAROL, transferAmount2); + + assertEq( + remoteToken.balanceOf(BOB), + transferAmount - transferAmount2, + "BOB's balance should decrease" + ); + assertEq( + remoteToken.balanceOf(CAROL), + transferAmount2, + "CAROL's balance should increase" + ); + } + + function testTotalShares() public { + uint256 initialShares = remoteRebasingToken.totalShares(); + assertEq(initialShares, 0, "Initial shares should be zero"); + + _performRemoteTransferWithoutExpectation(0, transferAmount); + uint256 sharesAfterTransfer = remoteRebasingToken.totalShares(); + assertEq( + sharesAfterTransfer, + remoteRebasingToken.assetsToShares(transferAmount), + "Shares should match transferred amount converted to shares" + ); + + _accrueYield(); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); + remoteMailbox.processNextInboundMessage(); + + uint256 sharesAfterYield = remoteRebasingToken.totalShares(); + assertEq( + sharesAfterYield, + sharesAfterTransfer, + "Total shares should remain constant after yield accrual" + ); + } + + function testShareBalanceOf() public { + _performRemoteTransferWithoutExpectation(0, transferAmount); + + uint256 bobShareBalance = remoteRebasingToken.shareBalanceOf(BOB); + assertEq( + bobShareBalance, + remoteRebasingToken.assetsToShares(transferAmount), + "Bob's share balance should match transferred amount converted to shares" + ); + + _accrueYield(); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); + remoteMailbox.processNextInboundMessage(); + + uint256 bobShareBalanceAfterYield = remoteRebasingToken.shareBalanceOf( + BOB + ); + assertEq( + bobShareBalanceAfterYield, + bobShareBalance, + "Bob's share balance should remain constant after yield accrual" + ); + } + function testWithdrawalWithoutYield() public { uint256 bobPrimaryBefore = primaryToken.balanceOf(BOB); _performRemoteTransferWithoutExpectation(0, transferAmount); @@ -480,6 +587,32 @@ contract HypERC4626CollateralTest is HypTokenTest { ); } + function testTotalSupply() public { + uint256 initialSupply = remoteToken.totalSupply(); + assertEq(initialSupply, 0, "Initial supply should be zero"); + + _performRemoteTransferWithoutExpectation(0, transferAmount); + uint256 supplyAfterTransfer = remoteToken.totalSupply(); + assertEq( + supplyAfterTransfer, + transferAmount, + "Supply should match transferred amount" + ); + + _accrueYield(); + localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); + remoteMailbox.processNextInboundMessage(); + + uint256 supplyAfterYield = remoteToken.totalSupply(); + assertApproxEqRelDecimal( + supplyAfterYield, + transferAmount + _discountedYield(), + 1e14, + 0, + "Supply should include yield" + ); + } + function testTransfer_withHookSpecified( uint256, bytes calldata diff --git a/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts b/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts index c6795fc6c..782acc3d2 100644 --- a/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts +++ b/typescript/sdk/src/token/EvmERC20WarpRouteReader.hardhat-test.ts @@ -174,7 +174,6 @@ describe('ERC20WarpRouterReader', async () => { name: TOKEN_NAME, symbol: TOKEN_NAME, decimals: TOKEN_DECIMALS, - totalSupply: TOKEN_SUPPLY, ...baseConfig, }, }; diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index ee2a9a399..1c5519126 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -88,8 +88,10 @@ abstract class TokenDeployer< ]; if (isCollateralConfig(config) || isNativeConfig(config)) { return defaultArgs; - } else if (isSyntheticConfig(config) || isSyntheticRebaseConfig(config)) { + } else if (isSyntheticConfig(config)) { return [config.totalSupply, config.name, config.symbol, ...defaultArgs]; + } else if (isSyntheticRebaseConfig(config)) { + return [0, config.name, config.symbol, ...defaultArgs]; } else { throw new Error('Unknown collateral type when initializing arguments'); } diff --git a/typescript/sdk/src/token/schemas.ts b/typescript/sdk/src/token/schemas.ts index 1ef4a770b..c92f98ea9 100644 --- a/typescript/sdk/src/token/schemas.ts +++ b/typescript/sdk/src/token/schemas.ts @@ -40,8 +40,11 @@ export const NativeConfigSchema = TokenMetadataSchema.partial().extend({ type: z.enum([TokenType.native, TokenType.nativeScaled]), }); -export const CollateralRebaseConfigSchema = - TokenMetadataSchema.partial().extend({ +export const CollateralRebaseConfigSchema = TokenMetadataSchema.omit({ + totalSupply: true, +}) + .partial() + .extend({ type: z.literal(TokenType.collateralVaultRebase), }); From 2a190ff61a3bb355f91b011c5d64ade5f50fdd28 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:43:45 +0100 Subject: [PATCH 191/224] chore: update agent image (#4745) ### Description chore: update agent image ### Drive-by changes ### Related issues ### Backward compatibility ### Testing infra --- typescript/infra/config/environments/mainnet3/agent.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index d6999cd18..68ac9ccb9 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -429,7 +429,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '42d6b50-20241021-155906', + tag: 'a64af8b-20241024-120818', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -438,7 +438,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: 'efd438f-20241016-101828', + tag: 'a64af8b-20241024-120818', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -448,7 +448,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '42d6b50-20241021-155906', + tag: 'a64af8b-20241024-120818', }, resources: scraperResources, }, @@ -463,7 +463,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '42d6b50-20241021-155906', + tag: 'a64af8b-20241024-120818', }, // We're temporarily (ab)using the RC relayer as a way to increase // message throughput. @@ -475,7 +475,7 @@ const releaseCandidate: RootAgentConfig = { validators: { docker: { repo, - tag: '9c056c7-20240911-154357', + tag: 'a64af8b-20241024-120818', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.ReleaseCandidate), From 14e4719f00be336cd7b7b74a342d212fe6a2c0a4 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Fri, 25 Oct 2024 13:51:44 +0100 Subject: [PATCH 192/224] feat: Use H512 as transaction hash in HyperlaneProvider and Scraper (#4759) ### Description Use H512 as transaction hash in HyperlaneProvider and Scraper. ### Related issues - Contributes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4272 ### Backward compatibility Yes ### Testing Manual run of Scraper for Ethereum and Neutron --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- rust/main/Cargo.lock | 1 - rust/main/agents/scraper/Cargo.toml | 1 - .../agents/scraper/src/chain_scraper/mod.rs | 56 +++---- rust/main/agents/scraper/src/conversions.rs | 31 +--- rust/main/agents/scraper/src/db/block.rs | 3 +- rust/main/agents/scraper/src/db/message.rs | 5 +- rust/main/agents/scraper/src/db/payment.rs | 4 +- rust/main/agents/scraper/src/db/txn.rs | 20 ++- .../src/providers/cosmos/provider.rs | 32 ++-- .../src/rpc_clients/provider.rs | 4 +- .../chains/hyperlane-fuel/src/provider.rs | 12 +- .../chains/hyperlane-sealevel/src/provider.rs | 4 +- .../hyperlane-core/src/traits/provider.rs | 6 +- .../main/hyperlane-core/src/traits/signing.rs | 3 +- .../hyperlane-core/src/types/chain_data.rs | 4 +- .../hyperlane-core/src/types/conversions.rs | 138 ++++++++++++++++++ rust/main/hyperlane-core/src/types/mod.rs | 2 + rust/main/utils/hex/src/lib.rs | 38 ----- 18 files changed, 208 insertions(+), 156 deletions(-) create mode 100644 rust/main/hyperlane-core/src/types/conversions.rs diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index 87d2c813e..27b11dcab 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -7670,7 +7670,6 @@ dependencies = [ "ethers", "eyre", "futures", - "hex 0.1.0", "hyperlane-base", "hyperlane-core", "hyperlane-test", diff --git a/rust/main/agents/scraper/Cargo.toml b/rust/main/agents/scraper/Cargo.toml index 7bad1ec7e..0b9e429b9 100644 --- a/rust/main/agents/scraper/Cargo.toml +++ b/rust/main/agents/scraper/Cargo.toml @@ -29,7 +29,6 @@ tokio = { workspace = true, features = ["rt", "macros", "parking_lot"] } tracing-futures.workspace = true tracing.workspace = true -hex = { path = "../../utils/hex" } hyperlane-base = { path = "../../hyperlane-base" } hyperlane-core = { path = "../../hyperlane-core", features = ["agent"] } migration = { path = "migration" } diff --git a/rust/main/agents/scraper/src/chain_scraper/mod.rs b/rust/main/agents/scraper/src/chain_scraper/mod.rs index c23df70a1..0be5b2ef1 100644 --- a/rust/main/agents/scraper/src/chain_scraper/mod.rs +++ b/rust/main/agents/scraper/src/chain_scraper/mod.rs @@ -7,14 +7,15 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; use eyre::Result; +use itertools::Itertools; +use tracing::{trace, warn}; + use hyperlane_base::settings::IndexSettings; use hyperlane_core::{ unwrap_or_none_result, BlockId, BlockInfo, Delivery, HyperlaneDomain, HyperlaneLogStore, HyperlaneMessage, HyperlaneProvider, HyperlaneSequenceAwareIndexerStoreReader, - HyperlaneWatermarkedLogStore, Indexed, InterchainGasPayment, LogMeta, H256, + HyperlaneWatermarkedLogStore, Indexed, InterchainGasPayment, LogMeta, H256, H512, }; -use itertools::Itertools; -use tracing::{trace, warn}; use crate::db::{ BasicBlock, BlockCursor, ScraperDb, StorableDelivery, StorableMessage, StorablePayment, @@ -78,12 +79,10 @@ impl HyperlaneSqlDb { &self, log_meta: impl Iterator, ) -> Result> { - let block_id_by_txn_hash: HashMap = log_meta + let block_id_by_txn_hash: HashMap = log_meta .map(|meta| { ( - meta.transaction_id - .try_into() - .expect("256-bit transaction ids are the maximum supported at this time"), + meta.transaction_id, BlockId::new(meta.block_hash, meta.block_number), ) }) @@ -121,7 +120,7 @@ impl HyperlaneSqlDb { txns: impl Iterator, ) -> Result> { // mapping of txn hash to (txn_id, block_id). - let mut txns: HashMap, i64)> = txns + let mut txns: HashMap, i64)> = txns .map(|TxnWithBlockId { txn_hash, block_id }| (txn_hash, (None, block_id))) .collect(); @@ -145,9 +144,9 @@ impl HyperlaneSqlDb { let mut txns_to_fetch = txns.iter_mut().filter(|(_, id)| id.0.is_none()); let mut txns_to_insert: Vec = Vec::with_capacity(CHUNK_SIZE); - let mut hashes_to_insert: Vec<&H256> = Vec::with_capacity(CHUNK_SIZE); + let mut hashes_to_insert: Vec<&H512> = Vec::with_capacity(CHUNK_SIZE); - for mut chunk in as_chunks::<(&H256, &mut (Option, i64))>(txns_to_fetch, CHUNK_SIZE) { + for mut chunk in as_chunks::<(&H512, &mut (Option, i64))>(txns_to_fetch, CHUNK_SIZE) { for (hash, (_, block_id)) in chunk.iter() { let info = match self.provider.get_txn_by_hash(hash).await { Ok(info) => info, @@ -302,7 +301,7 @@ impl HyperlaneLogStore for HyperlaneSqlDb { if messages.is_empty() { return Ok(0); } - let txns: HashMap = self + let txns: HashMap = self .ensure_blocks_and_txns(messages.iter().map(|r| &r.1)) .await? .map(|t| (t.hash, t)) @@ -310,13 +309,8 @@ impl HyperlaneLogStore for HyperlaneSqlDb { let storable = messages .iter() .filter_map(|(message, meta)| { - txns.get( - &meta - .transaction_id - .try_into() - .expect("256-bit transaction ids are the maximum supported at this time"), - ) - .map(|t| (message.inner().clone(), meta, t.id)) + txns.get(&meta.transaction_id) + .map(|t| (message.inner().clone(), meta, t.id)) }) .map(|(msg, meta, txn_id)| StorableMessage { msg, meta, txn_id }); let stored = self @@ -336,7 +330,7 @@ impl HyperlaneLogStore for HyperlaneSqlDb { if deliveries.is_empty() { return Ok(0); } - let txns: HashMap = self + let txns: HashMap = self .ensure_blocks_and_txns(deliveries.iter().map(|r| &r.1)) .await? .map(|t| (t.hash, t)) @@ -344,13 +338,8 @@ impl HyperlaneLogStore for HyperlaneSqlDb { let storable = deliveries .iter() .filter_map(|(message_id, meta)| { - txns.get( - &meta - .transaction_id - .try_into() - .expect("256-bit transaction ids are the maximum supported at this time"), - ) - .map(|txn| (*message_id.inner(), meta, txn.id)) + txns.get(&meta.transaction_id) + .map(|txn| (*message_id.inner(), meta, txn.id)) }) .map(|(message_id, meta, txn_id)| StorableDelivery { message_id, @@ -378,7 +367,7 @@ impl HyperlaneLogStore for HyperlaneSqlDb { if payments.is_empty() { return Ok(0); } - let txns: HashMap = self + let txns: HashMap = self .ensure_blocks_and_txns(payments.iter().map(|r| &r.1)) .await? .map(|t| (t.hash, t)) @@ -386,13 +375,8 @@ impl HyperlaneLogStore for HyperlaneSqlDb { let storable = payments .iter() .filter_map(|(payment, meta)| { - txns.get( - &meta - .transaction_id - .try_into() - .expect("256-bit transaction ids are the maximum supported at this time"), - ) - .map(|txn| (payment.inner(), meta, txn.id)) + txns.get(&meta.transaction_id) + .map(|txn| (payment.inner(), meta, txn.id)) }) .map(|(payment, meta, txn_id)| StorablePayment { payment, @@ -446,13 +430,13 @@ where #[derive(Debug, Clone)] struct TxnWithId { - hash: H256, + hash: H512, id: i64, } #[derive(Debug, Clone)] struct TxnWithBlockId { - txn_hash: H256, + txn_hash: H512, block_id: i64, } diff --git a/rust/main/agents/scraper/src/conversions.rs b/rust/main/agents/scraper/src/conversions.rs index 84a64a857..9252d5cd4 100644 --- a/rust/main/agents/scraper/src/conversions.rs +++ b/rust/main/agents/scraper/src/conversions.rs @@ -1,36 +1,7 @@ use num_bigint::{BigInt, Sign}; use sea_orm::prelude::BigDecimal; -use hyperlane_core::{H256, U256}; - -// Creates a big-endian hex representation of the address -pub fn address_to_bytes(data: &H256) -> Vec { - if hex::is_h160(data.as_fixed_bytes()) { - // take the last 20 bytes - data.as_fixed_bytes()[12..32].into() - } else { - h256_to_bytes(data) - } -} - -// Creates a big-endian hex representation of the address -pub fn bytes_to_address(data: Vec) -> eyre::Result { - if (data.len() != 20) && (data.len() != 32) { - return Err(eyre::eyre!("Invalid address length")); - } - if data.len() == 20 { - let mut prefix = vec![0; 12]; - prefix.extend(data); - Ok(H256::from_slice(&prefix[..])) - } else { - Ok(H256::from_slice(&data[..])) - } -} - -// Creates a big-endian hex representation of the address hash -pub fn h256_to_bytes(data: &H256) -> Vec { - data.as_fixed_bytes().as_slice().into() -} +use hyperlane_core::U256; pub fn u256_to_decimal(v: U256) -> BigDecimal { let mut buf = [0u8; 32]; diff --git a/rust/main/agents/scraper/src/db/block.rs b/rust/main/agents/scraper/src/db/block.rs index 1af05cd8c..45ff0bf7c 100644 --- a/rust/main/agents/scraper/src/db/block.rs +++ b/rust/main/agents/scraper/src/db/block.rs @@ -5,10 +5,9 @@ use sea_orm::{ }; use tracing::{debug, trace}; -use hyperlane_core::{BlockInfo, H256}; +use hyperlane_core::{address_to_bytes, h256_to_bytes, BlockInfo, H256}; use migration::OnConflict; -use crate::conversions::{address_to_bytes, h256_to_bytes}; use crate::date_time; use crate::db::ScraperDb; diff --git a/rust/main/agents/scraper/src/db/message.rs b/rust/main/agents/scraper/src/db/message.rs index f8b99fec5..423c24058 100644 --- a/rust/main/agents/scraper/src/db/message.rs +++ b/rust/main/agents/scraper/src/db/message.rs @@ -5,10 +5,11 @@ use itertools::Itertools; use sea_orm::{prelude::*, ActiveValue::*, DeriveColumn, EnumIter, Insert, QuerySelect}; use tracing::{debug, instrument, trace}; -use hyperlane_core::{HyperlaneMessage, LogMeta, H256}; +use hyperlane_core::{ + address_to_bytes, bytes_to_address, h256_to_bytes, HyperlaneMessage, LogMeta, H256, +}; use migration::OnConflict; -use crate::conversions::{address_to_bytes, bytes_to_address, h256_to_bytes}; use crate::date_time; use crate::db::ScraperDb; diff --git a/rust/main/agents/scraper/src/db/payment.rs b/rust/main/agents/scraper/src/db/payment.rs index 250f4f3c6..498128c34 100644 --- a/rust/main/agents/scraper/src/db/payment.rs +++ b/rust/main/agents/scraper/src/db/payment.rs @@ -3,10 +3,10 @@ use itertools::Itertools; use sea_orm::{prelude::*, ActiveValue::*, Insert, QuerySelect}; use tracing::{debug, instrument, trace}; -use hyperlane_core::{InterchainGasPayment, LogMeta}; +use hyperlane_core::{h256_to_bytes, InterchainGasPayment, LogMeta}; use migration::OnConflict; -use crate::conversions::{h256_to_bytes, u256_to_decimal}; +use crate::conversions::u256_to_decimal; use crate::date_time; use crate::db::ScraperDb; diff --git a/rust/main/agents/scraper/src/db/txn.rs b/rust/main/agents/scraper/src/db/txn.rs index ff0e70f2b..d5cec03dc 100644 --- a/rust/main/agents/scraper/src/db/txn.rs +++ b/rust/main/agents/scraper/src/db/txn.rs @@ -2,19 +2,17 @@ use std::collections::HashMap; use derive_more::Deref; use eyre::{eyre, Context, Result}; -use hyperlane_core::{TxnInfo, H256}; use sea_orm::{ prelude::*, sea_query::OnConflict, ActiveValue::*, DeriveColumn, EnumIter, Insert, NotSet, QuerySelect, }; use tracing::{debug, instrument, trace}; +use hyperlane_core::{address_to_bytes, bytes_to_h512, h512_to_bytes, TxnInfo, H512}; + use super::generated::transaction; -use crate::{ - conversions::{address_to_bytes, h256_to_bytes, u256_to_decimal}, - date_time, - db::ScraperDb, -}; + +use crate::{conversions::u256_to_decimal, date_time, db::ScraperDb}; #[derive(Debug, Clone, Deref)] pub struct StorableTxn { @@ -43,8 +41,8 @@ impl ScraperDb { /// found be excluded from the hashmap. pub async fn get_txn_ids( &self, - hashes: impl Iterator, - ) -> Result> { + hashes: impl Iterator, + ) -> Result> { #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] enum QueryAs { Id, @@ -53,7 +51,7 @@ impl ScraperDb { // check database to see which txns we already know and fetch their IDs let txns = transaction::Entity::find() - .filter(transaction::Column::Hash.is_in(hashes.map(h256_to_bytes))) + .filter(transaction::Column::Hash.is_in(hashes.map(h512_to_bytes))) .select_only() .column_as(transaction::Column::Id, QueryAs::Id) .column_as(transaction::Column::Hash, QueryAs::Hash) @@ -62,7 +60,7 @@ impl ScraperDb { .await .context("When querying transactions")? .into_iter() - .map(|(id, hash)| Ok((H256::from_slice(&hash), id))) + .map(|(id, hash)| Ok((bytes_to_h512(&hash), id))) .collect::>>()?; trace!(?txns, "Queried transaction info for hashes"); @@ -86,7 +84,7 @@ impl ScraperDb { max_priority_fee_per_gas: Set(txn .max_priority_fee_per_gas .map(u256_to_decimal)), - hash: Unchanged(h256_to_bytes(&txn.hash)), + hash: Unchanged(h512_to_bytes(&txn.hash)), time_created: Set(date_time::now()), gas_used: Set(u256_to_decimal(receipt.gas_used)), gas_price: Set(txn.gas_price.map(u256_to_decimal)), diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index ef0c15345..e718df610 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -17,9 +17,9 @@ use tracing::{error, warn}; use crypto::decompress_public_key; use hyperlane_core::{ - AccountAddressType, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, - ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, HyperlaneProviderError, - TxnInfo, TxnReceiptInfo, H256, U256, + bytes_to_h512, h512_to_bytes, AccountAddressType, BlockInfo, ChainCommunicationError, + ChainInfo, ChainResult, ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, + HyperlaneProviderError, TxnInfo, TxnReceiptInfo, H256, H512, U256, }; use crate::grpc::{WasmGrpcProvider, WasmProvider}; @@ -204,10 +204,10 @@ impl CosmosProvider { /// Extract contract address from transaction. fn contract(tx: &Tx, tx_hash: &H256) -> ChainResult { // We merge two error messages together so that both of them are reported - match Self::contract_address_from_msg_execute_contract(tx, tx_hash) { + match Self::contract_address_from_msg_execute_contract(tx) { Ok(contract) => Ok(contract), Err(msg_execute_contract_error) => { - match Self::contract_address_from_msg_recv_packet(tx, tx_hash) { + match Self::contract_address_from_msg_recv_packet(tx) { Ok(contract) => Ok(contract), Err(msg_recv_packet_error) => { let errors = vec![msg_execute_contract_error, msg_recv_packet_error]; @@ -221,10 +221,7 @@ impl CosmosProvider { } /// Assumes that there is only one `MsgExecuteContract` message in the transaction - fn contract_address_from_msg_execute_contract( - tx: &Tx, - tx_hash: &H256, - ) -> Result { + fn contract_address_from_msg_execute_contract(tx: &Tx) -> Result { use cosmrs::proto::cosmwasm::wasm::v1::MsgExecuteContract as ProtoMsgExecuteContract; let contract_execution_messages = tx @@ -253,10 +250,7 @@ impl CosmosProvider { Ok(contract) } - fn contract_address_from_msg_recv_packet( - tx: &Tx, - tx_hash: &H256, - ) -> Result { + fn contract_address_from_msg_recv_packet(tx: &Tx) -> Result { let packet_data = tx .body .messages @@ -392,7 +386,9 @@ impl HyperlaneProvider for CosmosProvider { Ok(block_info) } - async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult { + async fn get_txn_by_hash(&self, hash: &H512) -> ChainResult { + let hash: H256 = H256::from_slice(&h512_to_bytes(hash)); + let tendermint_hash = Hash::from_bytes(Algorithm::Sha256, hash.as_bytes()) .expect("transaction hash should be of correct size"); @@ -400,7 +396,7 @@ impl HyperlaneProvider for CosmosProvider { let received_hash = H256::from_slice(response.hash.as_bytes()); - if &received_hash != hash { + if received_hash != hash { return Err(ChainCommunicationError::from_other_str(&format!( "received incorrect transaction, expected hash: {:?}, received hash: {:?}", hash, received_hash, @@ -409,12 +405,12 @@ impl HyperlaneProvider for CosmosProvider { let tx = Tx::from_bytes(&response.tx)?; - let contract = Self::contract(&tx, hash)?; + let contract = Self::contract(&tx, &hash)?; let (sender, nonce) = self.sender_and_nonce(&tx)?; - let gas_price = self.calculate_gas_price(hash, &tx); + let gas_price = self.calculate_gas_price(&hash, &tx); let tx_info = TxnInfo { - hash: hash.to_owned(), + hash: hash.into(), gas_limit: U256::from(response.tx_result.gas_wanted), max_priority_fee_per_gas: None, max_fee_per_gas: None, diff --git a/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs index c8ef3d78c..d89cf9f43 100644 --- a/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs +++ b/rust/main/chains/hyperlane-ethereum/src/rpc_clients/provider.rs @@ -7,7 +7,7 @@ use async_trait::async_trait; use derive_new::new; use ethers::prelude::Middleware; use ethers_core::{abi::Address, types::BlockNumber}; -use hyperlane_core::{ethers_core_types, ChainInfo, HyperlaneCustomErrorWrapper, U256}; +use hyperlane_core::{ethers_core_types, ChainInfo, HyperlaneCustomErrorWrapper, H512, U256}; use tokio::time::sleep; use tracing::instrument; @@ -84,7 +84,7 @@ where #[instrument(err, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue - async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult { + async fn get_txn_by_hash(&self, hash: &H512) -> ChainResult { let txn = get_with_retry_on_none( hash, |h| self.provider.get_transaction(*h), diff --git a/rust/main/chains/hyperlane-fuel/src/provider.rs b/rust/main/chains/hyperlane-fuel/src/provider.rs index a72f8a6c5..cdd32650e 100644 --- a/rust/main/chains/hyperlane-fuel/src/provider.rs +++ b/rust/main/chains/hyperlane-fuel/src/provider.rs @@ -17,9 +17,9 @@ use fuels::{ }; use futures::future::join_all; use hyperlane_core::{ - BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, - HyperlaneMessage, HyperlaneProvider, HyperlaneProviderError, Indexed, LogMeta, TxnInfo, H256, - H512, U256, + h512_to_bytes, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, HyperlaneChain, + HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, HyperlaneProviderError, Indexed, LogMeta, + TxnInfo, H256, H512, U256, }; use crate::{make_client, make_provider, prelude::FuelIntoH256, ConnectionConf}; @@ -314,7 +314,9 @@ impl HyperlaneProvider for FuelProvider { /// Used by scraper #[allow(clippy::clone_on_copy)] // TODO: `rustc` 1.80.1 clippy issue #[allow(clippy::match_like_matches_macro)] // TODO: `rustc` 1.80.1 clippy issue - async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult { + async fn get_txn_by_hash(&self, hash: &H512) -> ChainResult { + let hash = H256::from_slice(&h512_to_bytes(hash)); + let transaction_res = self .provider .get_transaction_by_id(&hash.0.into()) @@ -370,7 +372,7 @@ impl HyperlaneProvider for FuelProvider { }; Ok(TxnInfo { - hash: hash.clone(), + hash: hash.into(), gas_limit: gas_limit.into(), max_priority_fee_per_gas: None, max_fee_per_gas: None, diff --git a/rust/main/chains/hyperlane-sealevel/src/provider.rs b/rust/main/chains/hyperlane-sealevel/src/provider.rs index aaf32ac59..932a7191e 100644 --- a/rust/main/chains/hyperlane-sealevel/src/provider.rs +++ b/rust/main/chains/hyperlane-sealevel/src/provider.rs @@ -3,7 +3,7 @@ use std::{str::FromStr, sync::Arc}; use async_trait::async_trait; use hyperlane_core::{ BlockInfo, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, - HyperlaneProviderError, TxnInfo, H256, U256, + HyperlaneProviderError, TxnInfo, H256, H512, U256, }; use solana_sdk::bs58; use solana_sdk::pubkey::Pubkey; @@ -68,7 +68,7 @@ impl HyperlaneProvider for SealevelProvider { Ok(block_info) } - async fn get_txn_by_hash(&self, _hash: &H256) -> ChainResult { + async fn get_txn_by_hash(&self, _hash: &H512) -> ChainResult { todo!() // FIXME } diff --git a/rust/main/hyperlane-core/src/traits/provider.rs b/rust/main/hyperlane-core/src/traits/provider.rs index 47070bc2a..63b4d01dd 100644 --- a/rust/main/hyperlane-core/src/traits/provider.rs +++ b/rust/main/hyperlane-core/src/traits/provider.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use auto_impl::auto_impl; use thiserror::Error; -use crate::{BlockInfo, ChainInfo, ChainResult, HyperlaneChain, TxnInfo, H256, U256}; +use crate::{BlockInfo, ChainInfo, ChainResult, HyperlaneChain, TxnInfo, H256, H512, U256}; /// Interface for a provider. Allows abstraction over different provider types /// for different chains. @@ -20,7 +20,7 @@ pub trait HyperlaneProvider: HyperlaneChain + Send + Sync + Debug { async fn get_block_by_height(&self, height: u64) -> ChainResult; /// Get txn info for a given txn hash - async fn get_txn_by_hash(&self, hash: &H256) -> ChainResult; + async fn get_txn_by_hash(&self, hash: &H512) -> ChainResult; /// Returns whether a contract exists at the provided address async fn is_contract(&self, address: &H256) -> ChainResult; @@ -40,7 +40,7 @@ pub enum HyperlaneProviderError { NoGasUsed, /// Could not find a transaction by hash #[error("Could not find transaction from provider with hash {0:?}")] - CouldNotFindTransactionByHash(H256), + CouldNotFindTransactionByHash(H512), /// Could not find a block by height #[error("Could not find block from provider with height {0:?}")] CouldNotFindBlockByHeight(u64), diff --git a/rust/main/hyperlane-core/src/traits/signing.rs b/rust/main/hyperlane-core/src/traits/signing.rs index 34e5676c4..5859d3c25 100644 --- a/rust/main/hyperlane-core/src/traits/signing.rs +++ b/rust/main/hyperlane-core/src/traits/signing.rs @@ -1,10 +1,11 @@ +use std::fmt::{Debug, Formatter}; + use async_trait::async_trait; use auto_impl::auto_impl; use serde::{ ser::{SerializeStruct, Serializer}, Deserialize, Serialize, }; -use std::fmt::{Debug, Formatter}; use crate::utils::bytes_to_hex; use crate::{Signature, H160, H256}; diff --git a/rust/main/hyperlane-core/src/types/chain_data.rs b/rust/main/hyperlane-core/src/types/chain_data.rs index 5f5ecb2e3..219f6989d 100644 --- a/rust/main/hyperlane-core/src/types/chain_data.rs +++ b/rust/main/hyperlane-core/src/types/chain_data.rs @@ -1,6 +1,6 @@ use derive_new::new; -use crate::{H256, U256}; +use crate::{H256, H512, U256}; /// Info about a given block in the chain. #[derive(Debug, Clone, Default)] @@ -27,7 +27,7 @@ pub struct ChainInfo { #[derive(Debug, Clone)] pub struct TxnInfo { /// Hash of this transaction - pub hash: H256, + pub hash: H512, /// Amount of gas which was allocated for running the transaction pub gas_limit: U256, /// Represents the maximum tx fee that will go to the miner as part of the diff --git a/rust/main/hyperlane-core/src/types/conversions.rs b/rust/main/hyperlane-core/src/types/conversions.rs new file mode 100644 index 000000000..5336e0e2b --- /dev/null +++ b/rust/main/hyperlane-core/src/types/conversions.rs @@ -0,0 +1,138 @@ +use uint::unroll; + +use crate::{H256, H512}; + +/// Creates a big-endian hex representation of the address +pub fn address_to_bytes(data: &H256) -> Vec { + if is_h160(data.as_fixed_bytes()) { + // take the last 20 bytes + data.as_fixed_bytes()[12..32].into() + } else { + h256_to_bytes(data) + } +} + +/// Creates a big-endian hex representation of the address +pub fn bytes_to_address(data: Vec) -> eyre::Result { + if (data.len() != 20) && (data.len() != 32) { + return Err(eyre::eyre!("Invalid address length")); + } + if data.len() == 20 { + let mut prefix = vec![0; 12]; + prefix.extend(data); + Ok(H256::from_slice(&prefix[..])) + } else { + Ok(H256::from_slice(&data[..])) + } +} + +/// Creates a big-endian hex representation of the address hash +pub fn h256_to_bytes(data: &H256) -> Vec { + data.as_fixed_bytes().as_slice().into() +} + +/// Creates a big-endian hex representation of the address hash +pub fn h512_to_bytes(data: &H512) -> Vec { + if is_h256(data.as_fixed_bytes()) { + // take the last 32 bytes + data.as_fixed_bytes()[32..64].into() + } else { + data.as_fixed_bytes().as_slice().into() + } +} + +/// Convert bytes into H512 with padding +pub fn bytes_to_h512(data: &[u8]) -> H512 { + assert!(data.len() <= 64); + + if data.len() == 64 { + return H512::from_slice(data); + } + + let mut buf = [0; 64]; + buf[64 - data.len()..64].copy_from_slice(data); + + H512::from_slice(&buf) +} + +/// Checks if a byte slice fits within 160 bits. Assumes a big-endian encoding; +/// ignores leading zeros. Current implementation only supports up to a 32 byte +/// array but this could easily be extended if needed. +pub const fn is_h160(data: &[u8; S]) -> bool { + assert!(S <= 32); + if S <= 20 { + true + } else { + let mut z = data[0]; + unroll! { + for i in 0..11 { + if S >= i + 22 { + z |= data[i + 1] + } + } + } + + z == 0 + } +} + +/// Checks if a byte slice fits within 32 bytes. Assumes a big-endian encoding; +/// ignores leading zeros. Current implementation only supports up to a 64 byte long +/// array but this could easily be extended if needed. +pub const fn is_h256(data: &[u8; S]) -> bool { + assert!(S <= 64); + if S <= 32 { + true + } else { + unroll! { + for i in 0..32 { + if data[i] != 0 { + return false; + } + } + } + + true + } +} + +#[cfg(test)] +mod test { + #[test] + fn is_h160() { + let v: [u8; 32] = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xd1, + 0xc9, 0x44, 0x69, 0x70, 0x08, 0x33, 0x71, 0x7f, 0xa8, 0xa3, 0x01, 0x72, 0x78, 0xbc, + 0x1c, 0xa8, 0x03, 0x1c, + ]; + assert!(super::is_h160(&v)); + + let v: [u8; 32] = [ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xd1, + 0xc9, 0x44, 0x69, 0x70, 0x08, 0x33, 0x71, 0x7f, 0xa8, 0xa3, 0x01, 0x72, 0x78, 0xbc, + 0x1c, 0xa8, 0x03, 0x1c, + ]; + assert!(!super::is_h160(&v)); + } + + #[test] + fn is_h256() { + let v: [u8; 64] = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xfa, 0xd1, + 0xc9, 0x44, 0x69, 0x70, 0x08, 0x33, 0x71, 0x7f, 0xa8, 0xa3, 0x01, 0x72, 0x78, 0xbc, + 0x1c, 0xa8, 0x03, 0x1c, 0x04, 0x1d, 0x05, 0x1e, + ]; + assert!(super::is_h256(&v)); + + let v: [u8; 64] = [ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xfa, 0xd1, + 0xc9, 0x44, 0x69, 0x70, 0x08, 0x33, 0x71, 0x7f, 0xa8, 0xa3, 0x01, 0x72, 0x78, 0xbc, + 0x1c, 0xa8, 0x03, 0x1c, 0x04, 0x1d, 0x05, 0x1e, + ]; + assert!(!super::is_h256(&v)); + } +} diff --git a/rust/main/hyperlane-core/src/types/mod.rs b/rust/main/hyperlane-core/src/types/mod.rs index a8973a72b..84df52d18 100644 --- a/rust/main/hyperlane-core/src/types/mod.rs +++ b/rust/main/hyperlane-core/src/types/mod.rs @@ -12,6 +12,7 @@ pub use announcement::*; pub use block_id::BlockId; pub use chain_data::*; pub use checkpoint::*; +pub use conversions::*; pub use indexing::*; pub use log_metadata::*; pub use merkle_tree::*; @@ -27,6 +28,7 @@ mod announcement; mod block_id; mod chain_data; mod checkpoint; +mod conversions; mod indexing; mod log_metadata; mod merkle_tree; diff --git a/rust/main/utils/hex/src/lib.rs b/rust/main/utils/hex/src/lib.rs index 46b4d2894..719a0b786 100644 --- a/rust/main/utils/hex/src/lib.rs +++ b/rust/main/utils/hex/src/lib.rs @@ -29,27 +29,6 @@ const FROM_HEX_CHARS: [u8; 256] = [ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ]; -/// Checks if a byte slice fits within 160 bits. Assumes a big-endian encoding; -/// ignores leading zeros. Current implementation only supports up to a 32 byte -/// array but this could easily be extended if needed. -pub const fn is_h160(data: &[u8; S]) -> bool { - assert!(S <= 32); - if S <= 20 { - true - } else { - let mut z = data[0]; - unroll! { - for i in 0..11 { - if S >= i + 22 { - z |= data[i + 1] - } - } - } - - z == 0 - } -} - /// This formats a 160bit byte slice as a lowercase hex string without any /// prefixing (will include leading zeros). pub fn format_h160_raw(data: &[u8; 20]) -> String { @@ -150,23 +129,6 @@ impl Error for InvalidHexCharacter {} mod test { use crate::FROM_HEX_CHARS; - #[test] - fn is_h160() { - let v: [u8; 32] = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xd1, - 0xc9, 0x44, 0x69, 0x70, 0x08, 0x33, 0x71, 0x7f, 0xa8, 0xa3, 0x01, 0x72, 0x78, 0xbc, - 0x1c, 0xa8, 0x03, 0x1c, - ]; - assert!(super::is_h160(&v)); - - let v: [u8; 32] = [ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xd1, - 0xc9, 0x44, 0x69, 0x70, 0x08, 0x33, 0x71, 0x7f, 0xa8, 0xa3, 0x01, 0x72, 0x78, 0xbc, - 0x1c, 0xa8, 0x03, 0x1c, - ]; - assert!(!super::is_h160(&v)); - } - #[test] fn format_h160() { let v: [u8; 20] = [ From 1bd8e3e384baa72bef1e1186f36590e220bf075e Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:58:55 +0100 Subject: [PATCH 193/224] feat: Stride <> Eclipse TIA and stTIA (#4749) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../gas-oracle-configs-eclipsemainnet.json | 43 +++++++++++-------- .../TIA-stride-eclipse/program-ids.json | 10 +++++ .../TIA-stride-eclipse/token-config.json | 17 ++++++++ .../stTIA-stride-eclipse/program-ids.json | 10 +++++ .../stTIA-stride-eclipse/token-config.json | 17 ++++++++ .../warp/STTIA-eclipsestride-deployments.yaml | 24 +++++++++++ .../warp/TIA-eclipsestride-deployments.yaml | 23 ++++++++++ .../getEclipseStrideSTTIAWarpConfig.ts | 29 +++++++++++++ .../getEclipseStrideTIAWarpConfig.ts | 29 +++++++++++++ .../environments/mainnet3/warp/warpIds.ts | 2 + typescript/infra/config/warp.ts | 4 ++ typescript/infra/src/warp/helm.ts | 2 +- 12 files changed, 192 insertions(+), 18 deletions(-) create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/program-ids.json create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/token-config.json create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/program-ids.json create mode 100644 rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/token-config.json create mode 100644 typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml create mode 100644 typescript/infra/config/environments/mainnet3/warp/TIA-eclipsestride-deployments.yaml create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.ts create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.ts diff --git a/rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json b/rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json index 95b108c96..b459e88d4 100644 --- a/rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json +++ b/rust/sealevel/environments/mainnet3/eclipsemainnet/gas-oracle-configs-eclipsemainnet.json @@ -1,20 +1,29 @@ [ - { - "domain": 1, - "gasOracle": { - "type": "remoteGasData", - "tokenExchangeRate": "15000000000000000000", - "gasPrice": "10000000000", - "tokenDecimals": 18 - } - }, - { - "domain": 1399811149, - "gasOracle": { - "type": "remoteGasData", - "tokenExchangeRate": "887000000000000000", - "gasPrice": "15", - "tokenDecimals": 9 - } + { + "domain": 1, + "gasOracle": { + "type": "remoteGasData", + "tokenExchangeRate": "15000000000000000000", + "gasPrice": "10000000000", + "tokenDecimals": 18 } + }, + { + "domain": 1399811149, + "gasOracle": { + "type": "remoteGasData", + "tokenExchangeRate": "887000000000000000", + "gasPrice": "15", + "tokenDecimals": 9 + } + }, + { + "domain": 745, + "gasOracle": { + "type": "remoteGasData", + "tokenExchangeRate": "435246388284187", + "gasPrice": "7", + "tokenDecimals": 6 + } + } ] diff --git a/rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/program-ids.json new file mode 100644 index 000000000..6f10e1014 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/program-ids.json @@ -0,0 +1,10 @@ +{ + "stride": { + "hex": "0x0b1798722ccf813f617ffa8d52d36302544807497434740d98e693e9abb245d1", + "base58": "kJMTJuh4tzhzfTV261wh2cisqb7NNev6ZE6czwB3ss6" + }, + "eclipsemainnet": { + "hex": "0xa0c167513f4d025217a48891973c3dbe41e10e76230033ef5d676299a18ca7f5", + "base58": "BpXHAiktwjx7fN6M9ST9wr6qKAsH27wZFhdHEhReJsR6" + } +} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/token-config.json new file mode 100644 index 000000000..f501f4ee8 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/TIA-stride-eclipse/token-config.json @@ -0,0 +1,17 @@ +{ + "eclipsemainnet": { + "type": "synthetic", + "decimals": 6, + "remoteDecimals": 6, + "name": "Celestia", + "symbol": "TIA", + "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/b21b78514a42e8c050b36472c8325fd4b5177366/deployments/warp_routes/TIA/metadata.json", + "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" + }, + "stride": { + "type": "collateral", + "decimals": 6, + "token": "ibc/BF3B4F53F3694B66E13C23107C84B6485BD2B96296BB7EC680EA77BBA75B4801", + "foreignDeployment": "0x0b1798722ccf813f617ffa8d52d36302544807497434740d98e693e9abb245d1" + } +} diff --git a/rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/program-ids.json b/rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/program-ids.json new file mode 100644 index 000000000..1af852d36 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/program-ids.json @@ -0,0 +1,10 @@ +{ + "stride": { + "hex": "0x8d7a6737fdd9545dc77d1c5cc2d26cb1321f6c67f0facb030149da9cc58f0cbe", + "base58": "AXGjtKVpzYdXYX155z6qYQC4Up7fi5LPKNXAK32gi3x9" + }, + "eclipsemainnet": { + "hex": "0x0d258188d0761163da174da890d0c1becdee51a01dbc9e2a6bfcb342140eb509", + "base58": "tKUHyJ5NxhnwU94JUmzh1ekukDcHHX8mZF6fqxbMwX6" + } +} \ No newline at end of file diff --git a/rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/token-config.json b/rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/token-config.json new file mode 100644 index 000000000..c59c12bb6 --- /dev/null +++ b/rust/sealevel/environments/mainnet3/warp-routes/stTIA-stride-eclipse/token-config.json @@ -0,0 +1,17 @@ +{ + "eclipsemainnet": { + "type": "synthetic", + "decimals": 6, + "remoteDecimals": 6, + "name": "Stride Staked TIA", + "symbol": "stTIA", + "uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/dee58183e51f4eb43e84dbac0e595a4b389dbe80/deployments/warp_routes/stTIA/metadata.json", + "interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj" + }, + "stride": { + "type": "collateral", + "decimals": 6, + "token": "stutia", + "foreignDeployment": "0x8d7a6737fdd9545dc77d1c5cc2d26cb1321f6c67f0facb030149da9cc58f0cbe" + } +} diff --git a/typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml new file mode 100644 index 000000000..18e934fff --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml @@ -0,0 +1,24 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +description: Hyperlane Warp Route artifacts +timestamp: '2024-10-18T14:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + stride: + protocolType: cosmos + type: collateral + hypAddress: stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee + # dummy tokenAddress since stTIA is native + tokenAddress: 'stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee' + name: Stride Staked TIA + symbol: stTIA + decimals: 6 + eclipsemainnet: + protocolType: sealevel + type: synthetic + hypAddress: 'tKUHyJ5NxhnwU94JUmzh1ekukDcHHX8mZF6fqxbMwX6' + tokenAddress: 'V5m1Cc9VK61mKL8xVYrjR7bjD2BC5VpADLa6ws3G8KM' + isSpl2022: true + name: Turbo Eth + symbol: tETH + decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/TIA-eclipsestride-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/TIA-eclipsestride-deployments.yaml new file mode 100644 index 000000000..999e8ea95 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/TIA-eclipsestride-deployments.yaml @@ -0,0 +1,23 @@ +# Configs and artifacts for the deployment of Hyperlane Warp Routes +description: Hyperlane Warp Route artifacts +timestamp: '2024-10-18T14:00:00.000Z' +deployer: Abacus Works (Hyperlane) +data: + config: + stride: + protocolType: cosmos + type: collateral + hypAddress: stride1pvtesu3ve7qn7ctll2x495mrqf2ysp6fws68grvcu6f7n2ajghgsh2jdj6 + tokenAddress: ibc/BF3B4F53F3694B66E13C23107C84B6485BD2B96296BB7EC680EA77BBA75B4801 + name: Celestia + symbol: TIA + decimals: 6 + eclipsemainnet: + protocolType: sealevel + type: synthetic + hypAddress: 'BpXHAiktwjx7fN6M9ST9wr6qKAsH27wZFhdHEhReJsR6' + tokenAddress: '9RryNMhAVJpAwAGjCAMKbbTFwgjapqPkzpGMfTQhEjf8' + isSpl2022: true + name: Turbo Eth + symbol: tETH + decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.ts new file mode 100644 index 000000000..eaf935f9b --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.ts @@ -0,0 +1,29 @@ +import { + ChainMap, + RouterConfig, + TokenRouterConfig, + TokenType, +} from '@hyperlane-xyz/sdk'; + +export const getEclipseStrideTiaWarpConfig = async ( + _routerConfig: ChainMap, +): Promise> => { + // @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig + const eclipsemainnet: TokenRouterConfig = { + type: TokenType.synthetic, + foreignDeployment: 'BpXHAiktwjx7fN6M9ST9wr6qKAsH27wZFhdHEhReJsR6', + gas: 300_000, + }; + + // @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig + const stride: TokenRouterConfig = { + type: TokenType.collateral, + foreignDeployment: + 'stride1pvtesu3ve7qn7ctll2x495mrqf2ysp6fws68grvcu6f7n2ajghgsh2jdj6', + }; + + return { + eclipsemainnet, + stride, + }; +}; diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.ts new file mode 100644 index 000000000..aa2cf6a10 --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.ts @@ -0,0 +1,29 @@ +import { + ChainMap, + RouterConfig, + TokenRouterConfig, + TokenType, +} from '@hyperlane-xyz/sdk'; + +export const getEclipseStrideStTiaWarpConfig = async ( + _routerConfig: ChainMap, +): Promise> => { + // @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig + const eclipsemainnet: TokenRouterConfig = { + type: TokenType.synthetic, + foreignDeployment: 'tKUHyJ5NxhnwU94JUmzh1ekukDcHHX8mZF6fqxbMwX6', + gas: 300_000, + }; + + // @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig + const stride: TokenRouterConfig = { + type: TokenType.collateral, + foreignDeployment: + 'stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee', + }; + + return { + eclipsemainnet, + stride, + }; +}; diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index debc81326..a90601c35 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -6,6 +6,8 @@ export enum WarpRouteIds { ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet', EclipseSolanaWIF = 'WIF/eclipsemainnet-solanamainnet', + EclipseStrideSTTIA = 'stTIA/eclipse-stride', + EclipseStrideTIA = 'TIA/eclipse-stride', EthereumInevmUSDC = 'USDC/ethereum-inevm', EthereumInevmUSDT = 'USDT/ethereum-inevm', EthereumEclipseTETH = 'tETH/eclipsemainnet-ethereum', diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 2b7c44ee4..84086342e 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -12,6 +12,8 @@ import { getAncient8EthereumUSDCWarpConfig } from './environments/mainnet3/warp/ import { getArbitrumEthereumZircuitAmphrETHWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.js'; import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronEclipWarpConfig.js'; import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js'; +import { getEclipseStrideTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.js'; +import { getEclipseStrideStTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.js'; import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js'; import { getEthereumInevmUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDTWarpConfig.js'; import { getEthereumSeiFastUSDWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.js'; @@ -50,6 +52,8 @@ export const warpConfigGetterMap: Record< [WarpRouteIds.EthereumVictionUSDT]: getEthereumVictionUSDTWarpConfig, [WarpRouteIds.EthereumZircuitPZETH]: getRenzoPZETHWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, + [WarpRouteIds.EclipseStrideTIA]: getEclipseStrideTiaWarpConfig, + [WarpRouteIds.EclipseStrideSTTIA]: getEclipseStrideStTiaWarpConfig, }; export async function getWarpConfig( diff --git a/typescript/infra/src/warp/helm.ts b/typescript/infra/src/warp/helm.ts index f5aa0e981..e7296ad0c 100644 --- a/typescript/infra/src/warp/helm.ts +++ b/typescript/infra/src/warp/helm.ts @@ -27,7 +27,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager { return { image: { repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '6945b20-20241022-155935', + tag: 'ee5ec6b-20241025-133236', }, configFilePath: pathRelativeToMonorepoRoot, fullnameOverride: this.helmReleaseName, From d5bdb2c28a9332c8cc54faddd39147cb9a0f824e Mon Sep 17 00:00:00 2001 From: Mohammed Hussan Date: Fri, 25 Oct 2024 15:31:17 +0100 Subject: [PATCH 194/224] feat(warpMonitor): Support collateral value monitoring (#4545) ### Description - Support continuous value monitoring by allowing promethues to scrape value metrics for native and collateral tokens - Uses the `CoinGeckoTokenPriceGetter` - Added `getTokenPriceByIds` helper method to the `CoinGeckoTokenPriceGetter`, to support fetching prices using the coin gecko id only - Add a warp_route_id label to metrics ### Testing Manual --- .../mainnet3/warp/EZETH-deployments.yaml | 1 + .../warp/ancient8-USDC-deployments.yaml | 1 + .../warp/bsc-lumia-LUMIA-deployments.yaml | 1 + .../warp/eclipse-SOL-deployments.yaml | 1 + .../warp/eclipse-USDC-deployments.yaml | 2 + .../warp/eclipse-WIF-deployments.yaml | 1 + .../warp/ethereumUSDC-inevm-deployments.yaml | 1 + .../warp/ethereumUSDT-inevm-deployments.yaml | 1 + .../warp/injective-inevm-deployments.yaml | 1 + .../neutron-mantapacific-deployments.yaml | 1 + .../warp/sei-FASTUSD-deployments.yaml | 1 + .../viction-ethereum-ETH-deployments.yaml | 1 + .../viction-ethereum-USDC-deployments.yaml | 1 + .../viction-ethereum-USDT-deployments.yaml | 1 + typescript/infra/package.json | 2 +- .../monitor-warp-routes-balances.ts | 283 ++++++++++++++---- typescript/sdk/src/gas/token-prices.ts | 93 +++--- .../sdk/src/metadata/warpRouteConfig.ts | 1 + yarn.lock | 12 +- 19 files changed, 316 insertions(+), 90 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml index b83663645..26a0a5807 100644 --- a/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/EZETH-deployments.yaml @@ -10,6 +10,7 @@ data: symbol: ezETH hypAddress: '0xC59336D8edDa9722B4f1Ec104007191Ec16f7087' tokenAddress: '0xbf5495Efe5DB9ce00f80364C8B423567e58d2110' + tokenCoinGeckoId: renzo-restaked-eth decimals: 18 bsc: protocolType: ethereum diff --git a/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-deployments.yaml index 07be06027..d87b3fa0a 100644 --- a/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/ancient8-USDC-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: '0x8b4192B9Ad1fCa440A5808641261e5289e6de95D' tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' # USDC + tokenCoinGeckoId: usd-coin name: USDC symbol: USDC decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml index 9db075248..d106ac884 100644 --- a/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/bsc-lumia-LUMIA-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: '0xdD313D475f8A9d81CBE2eA953a357f52e10BA357' tokenAddress: '0xd9343a049d5dbd89cd19dc6bca8c48fb3a0a42a7' + tokenCoinGeckoId: lumia name: Lumia Token symbol: LUMIA decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml index 0469f45eb..711e6d428 100644 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-SOL-deployments.yaml @@ -9,6 +9,7 @@ data: protocolType: sealevel type: native hypAddress: '8DtAGQpcMuD5sG3KdxDy49ydqXUggR1LQtebh2TECbAc' + tokenCoinGeckoId: solana name: Solana symbol: SOL decimals: 9 diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml index 2955d2c84..7405cb94d 100644 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-USDC-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: '0xe1De9910fe71cC216490AC7FCF019e13a34481D7' tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' # USDC + tokenCoinGeckoId: usd-coin name: USDC symbol: USDC decimals: 6 @@ -18,6 +19,7 @@ data: type: collateral hypAddress: '3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm' tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' + tokenCoinGeckoId: usd-coin isSpl2022: false name: USDC symbol: USDC diff --git a/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml index 94e44a8b1..1b7245c91 100644 --- a/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/eclipse-WIF-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: 'CuQmsT4eSF4dYiiGUGYYQxJ7c58pUAD5ADE3BbFGzQKx' tokenAddress: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm' + tokenCoinGeckoId: dogwifcoin name: dogwifhat symbol: WIF decimals: 9 diff --git a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDC-inevm-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/ethereumUSDC-inevm-deployments.yaml index 0d8ff7755..90f22e0df 100644 --- a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDC-inevm-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/ethereumUSDC-inevm-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: '0xED56728fb977b0bBdacf65bCdD5e17Bb7e84504f' tokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' # USDC + tokenCoinGeckoId: usd-coin name: USDC symbol: USDC decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDT-inevm-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/ethereumUSDT-inevm-deployments.yaml index 25ec599f7..91976ddd9 100644 --- a/typescript/infra/config/environments/mainnet3/warp/ethereumUSDT-inevm-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/ethereumUSDT-inevm-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: '0xab852e67bf03E74C89aF67C4BA97dd1088D3dA19' tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7' # USDT + tokenCoinGeckoId: tether name: Tether USD symbol: USDT decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/injective-inevm-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/injective-inevm-deployments.yaml index efabaf59d..cd39382ea 100644 --- a/typescript/infra/config/environments/mainnet3/warp/injective-inevm-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/injective-inevm-deployments.yaml @@ -9,6 +9,7 @@ data: protocolType: cosmos type: native hypAddress: inj1mv9tjvkaw7x8w8y9vds8pkfq46g2vcfkjehc6k + tokenCoinGeckoId: injective-protocol name: Injective Coin symbol: INJ decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/neutron-mantapacific-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/neutron-mantapacific-deployments.yaml index ae13acf3d..bf4e1770a 100644 --- a/typescript/infra/config/environments/mainnet3/warp/neutron-mantapacific-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/neutron-mantapacific-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: neutron1ch7x3xgpnj62weyes8vfada35zff6z59kt2psqhnx9gjnt2ttqdqtva3pa tokenAddress: ibc/773B4D0A3CD667B2275D5A4A7A2F0909C0BA0F4059C0B9181E680DDF4965DCC7 + tokenCoinGeckoId: celestia name: Celestia symbol: TIA decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml index 885c1a4db..ed9672e41 100644 --- a/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/sei-FASTUSD-deployments.yaml @@ -8,6 +8,7 @@ data: type: collateral hypAddress: '0x9AD81058c6C3Bf552C9014CB30E824717A0ee21b' tokenAddress: '0x15700B564Ca08D9439C58cA5053166E8317aa138' + tokenCoinGeckoId: elixir-deusd # unique setup where we want deUSD to be deposited as collateral and we want fastUSD to be minted as a synthetic on sei name: fastUSD symbol: fastUSD decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-ETH-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-ETH-deployments.yaml index 8923facc0..c3e03b54d 100644 --- a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-ETH-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-ETH-deployments.yaml @@ -9,6 +9,7 @@ data: protocolType: ethereum type: native hypAddress: '0x15b5D6B614242B118AA404528A7f3E2Ad241e4A4' + tokenCoinGeckoId: ethereum name: Ether symbol: ETH decimals: 18 diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDC-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDC-deployments.yaml index a278a93e8..8a84e6a7c 100644 --- a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDC-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDC-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: '0x31Dca7762930f56D81292f85E65c9D67575804fE' tokenAddress: '0x31Dca7762930f56D81292f85E65c9D67575804fE' # USDC + tokenCoinGeckoId: usd-coin name: USD Coin symbol: USDC decimals: 6 diff --git a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDT-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDT-deployments.yaml index 8ddaa1e08..a22598042 100644 --- a/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDT-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/viction-ethereum-USDT-deployments.yaml @@ -10,6 +10,7 @@ data: type: collateral hypAddress: '0x4221a16A01F61c2b38A03C52d828a7041f6AAA49' tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7' # USDT + tokenCoinGeckoId: tether name: Tether USD symbol: USDT decimals: 6 diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 375d06c59..81361ac85 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -14,7 +14,7 @@ "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", "@hyperlane-xyz/helloworld": "5.6.1", - "@hyperlane-xyz/registry": "4.7.0", + "@hyperlane-xyz/registry": "4.10.0", "@hyperlane-xyz/sdk": "5.6.1", "@hyperlane-xyz/utils": "5.6.1", "@inquirer/prompts": "^5.3.8", diff --git a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts index 3d946a9e6..2d588a89c 100644 --- a/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts +++ b/typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts @@ -9,10 +9,12 @@ import { IXERC20__factory, } from '@hyperlane-xyz/core'; import { ERC20__factory } from '@hyperlane-xyz/core'; +import { createWarpRouteConfigId } from '@hyperlane-xyz/registry'; import { ChainMap, ChainMetadata, ChainName, + CoinGeckoTokenPriceGetter, CosmNativeTokenAdapter, CwNativeTokenAdapter, MultiProtocolProvider, @@ -38,17 +40,41 @@ import { getEnvironmentConfig } from '../core-utils.js'; const logger = rootLogger.child({ module: 'warp-balance-monitor' }); const metricsRegister = new Registry(); + +interface WarpRouteMetrics { + chain_name: ChainName; + token_address: string; + token_name: string; + wallet_address: string; + token_type: TokenType; + warp_route_id: string; + related_chain_names: string; +} + +type WarpRouteMetricLabels = keyof WarpRouteMetrics; + +const warpRouteMetricLabels: WarpRouteMetricLabels[] = [ + 'chain_name', + 'token_address', + 'token_name', + 'wallet_address', + 'token_type', + 'warp_route_id', + 'related_chain_names', +]; + const warpRouteTokenBalance = new Gauge({ name: 'hyperlane_warp_route_token_balance', help: 'HypERC20 token balance of a Warp Route', registers: [metricsRegister], - labelNames: [ - 'chain_name', - 'token_address', - 'token_name', - 'wallet_address', - 'token_type', - ], + labelNames: warpRouteMetricLabels, +}); + +const warpRouteCollateralValue = new Gauge({ + name: 'hyperlane_warp_route_collateral_value', + help: 'Total value of collateral held in a HypERC20Collateral or HypNative contract of a Warp Route', + registers: [metricsRegister], + labelNames: warpRouteMetricLabels, }); const xERC20LimitsGauge = new Gauge({ @@ -66,6 +92,11 @@ interface xERC20Limit { burnMax: number; } +interface WarpRouteInfo { + balance: number; + valueUSD?: number; +} + export function readWarpRouteConfig(filePath: string) { const config = readYaml(filePath); if (!config) throw new Error(`No warp config found at ${filePath}`); @@ -112,7 +143,8 @@ async function main(): Promise { async function checkBalance( tokenConfig: WarpRouteConfig, multiProtocolProvider: MultiProtocolProvider, -): Promise> { + tokenPriceGetter: CoinGeckoTokenPriceGetter, +): Promise> { const output = objMap( tokenConfig, async (chain: ChainName, token: WarpRouteConfig[ChainName]) => { @@ -122,8 +154,12 @@ async function checkBalance( case ProtocolType.Ethereum: { const provider = multiProtocolProvider.getEthersV5Provider(chain); const nativeBalance = await provider.getBalance(token.hypAddress); - return parseFloat( - ethers.utils.formatUnits(nativeBalance, token.decimals), + + return getNativeTokenWarpInfo( + nativeBalance, + token.decimals, + tokenPriceGetter, + chain, ); } case ProtocolType.Sealevel: { @@ -142,8 +178,12 @@ async function checkBalance( const balance = ethers.BigNumber.from( await adapter.getBalance(token.hypAddress), ); - return parseFloat( - ethers.utils.formatUnits(balance, token.decimals), + + return getNativeTokenWarpInfo( + balance, + token.decimals, + tokenPriceGetter, + chain, ); } case ProtocolType.Cosmos: { @@ -156,8 +196,12 @@ async function checkBalance( { ibcDenom: token.ibcDenom }, ); const tokenBalance = await adapter.getBalance(token.hypAddress); - return parseFloat( - ethers.utils.formatUnits(tokenBalance, token.decimals), + + return getNativeTokenWarpInfo( + tokenBalance, + token.decimals, + tokenPriceGetter, + chain, ); } } @@ -177,8 +221,11 @@ async function checkBalance( token.hypAddress, ); - return parseFloat( - ethers.utils.formatUnits(collateralBalance, token.decimals), + return getCollateralTokenWarpInfo( + collateralBalance, + token.decimals, + tokenPriceGetter, + token.tokenCoinGeckoId, ); } case ProtocolType.Sealevel: { @@ -198,8 +245,12 @@ async function checkBalance( const collateralBalance = ethers.BigNumber.from( await adapter.getBalance(token.hypAddress), ); - return parseFloat( - ethers.utils.formatUnits(collateralBalance, token.decimals), + + return getCollateralTokenWarpInfo( + collateralBalance, + token.decimals, + tokenPriceGetter, + token.tokenCoinGeckoId, ); } case ProtocolType.Cosmos: { @@ -216,8 +267,12 @@ async function checkBalance( const collateralBalance = ethers.BigNumber.from( await adapter.getBalance(token.hypAddress), ); - return parseFloat( - ethers.utils.formatUnits(collateralBalance, token.decimals), + + return getCollateralTokenWarpInfo( + collateralBalance, + token.decimals, + tokenPriceGetter, + token.tokenCoinGeckoId, ); } } @@ -232,9 +287,11 @@ async function checkBalance( provider, ); const syntheticBalance = await tokenContract.totalSupply(); - return parseFloat( - ethers.utils.formatUnits(syntheticBalance, token.decimals), - ); + return { + balance: parseFloat( + ethers.utils.formatUnits(syntheticBalance, token.decimals), + ), + }; } case ProtocolType.Sealevel: { if (!token.tokenAddress) @@ -253,13 +310,15 @@ async function checkBalance( const syntheticBalance = ethers.BigNumber.from( await adapter.getTotalSupply(), ); - return parseFloat( - ethers.utils.formatUnits(syntheticBalance, token.decimals), - ); + return { + balance: parseFloat( + ethers.utils.formatUnits(syntheticBalance, token.decimals), + ), + }; } case ProtocolType.Cosmos: // TODO - cosmos synthetic - return 0; + return { balance: 0 }; } break; } @@ -275,9 +334,11 @@ async function checkBalance( const xerc20 = IXERC20__factory.connect(xerc20Address, provider); const syntheticBalance = await xerc20.totalSupply(); - return parseFloat( - ethers.utils.formatUnits(syntheticBalance, token.decimals), - ); + return { + balance: parseFloat( + ethers.utils.formatUnits(syntheticBalance, token.decimals), + ), + }; } default: throw new Error( @@ -307,8 +368,11 @@ async function checkBalance( xerc20LockboxAddress, ); - return parseFloat( - ethers.utils.formatUnits(collateralBalance, token.decimals), + return getCollateralTokenWarpInfo( + collateralBalance, + token.decimals, + tokenPriceGetter, + token.tokenCoinGeckoId, ); } default: @@ -318,7 +382,7 @@ async function checkBalance( } } } - return 0; + return { balance: 0 }; }, ); @@ -327,22 +391,44 @@ async function checkBalance( export function updateTokenBalanceMetrics( tokenConfig: WarpRouteConfig, - balances: ChainMap, + balances: ChainMap, ) { objMap(tokenConfig, (chain: ChainName, token: WarpRouteConfig[ChainName]) => { - warpRouteTokenBalance - .labels({ - chain_name: chain, - token_address: token.tokenAddress ?? ethers.constants.AddressZero, - token_name: token.name, - wallet_address: token.hypAddress, - token_type: token.type, - }) - .set(balances[chain]); + const metrics: WarpRouteMetrics = { + chain_name: chain, + token_address: token.tokenAddress ?? ethers.constants.AddressZero, + token_name: token.name, + wallet_address: token.hypAddress, + token_type: token.type, + warp_route_id: createWarpRouteConfigId( + token.symbol, + Object.keys(tokenConfig) as ChainName[], + ), + related_chain_names: Object.keys(tokenConfig) + .filter((chainName) => chainName !== chain) + .sort() + .join(','), + }; + + warpRouteTokenBalance.labels(metrics).set(balances[chain].balance); + if (balances[chain].valueUSD) { + warpRouteCollateralValue + .labels(metrics) + .set(balances[chain].valueUSD as number); + logger.debug('Collateral value updated for chain', { + chain, + related_chain_names: metrics.related_chain_names, + warp_route_id: metrics.warp_route_id, + token: metrics.token_name, + value: balances[chain].valueUSD, + }); + } logger.debug('Wallet balance updated for chain', { chain, - token: token.name, - balance: balances[chain], + related_chain_names: metrics.related_chain_names, + warp_route_id: metrics.warp_route_id, + token: metrics.token_name, + balance: balances[chain].balance, }); }); } @@ -468,27 +554,120 @@ const getXERC20Limit = async ( }; }; +async function getTokenPriceByChain( + chain: ChainName, + tokenPriceGetter: CoinGeckoTokenPriceGetter, +): Promise { + try { + return await tokenPriceGetter.getTokenPrice(chain); + } catch (e) { + logger.warn('Error getting token price', e); + return undefined; + } +} + +async function getNativeTokenValue( + chain: ChainName, + balanceFloat: number, + tokenPriceGetter: CoinGeckoTokenPriceGetter, +): Promise { + const price = await getTokenPriceByChain(chain, tokenPriceGetter); + logger.debug(`${chain} native token price ${price}`); + if (!price) return undefined; + return balanceFloat * price; +} + +async function getNativeTokenWarpInfo( + balance: ethers.BigNumber | bigint, + decimal: number, + tokenPriceGetter: CoinGeckoTokenPriceGetter, + chain: ChainName, +): Promise { + const balanceFloat = parseFloat(ethers.utils.formatUnits(balance, decimal)); + const value = await getNativeTokenValue( + chain, + balanceFloat, + tokenPriceGetter, + ); + return { balance: balanceFloat, valueUSD: value }; +} + +async function getCollateralTokenPrice( + tokenCoinGeckoId: string | undefined, + tokenPriceGetter: CoinGeckoTokenPriceGetter, +): Promise { + if (!tokenCoinGeckoId) return undefined; + const prices = await tokenPriceGetter.getTokenPriceByIds([tokenCoinGeckoId]); + if (!prices) return undefined; + return prices[0]; +} + +async function getCollateralTokenValue( + tokenCoinGeckoId: string | undefined, + balanceFloat: number, + tokenPriceGetter: CoinGeckoTokenPriceGetter, +): Promise { + const price = await getCollateralTokenPrice( + tokenCoinGeckoId, + tokenPriceGetter, + ); + logger.debug(`${tokenCoinGeckoId} token price ${price}`); + if (!price) return undefined; + return balanceFloat * price; +} + +async function getCollateralTokenWarpInfo( + balance: ethers.BigNumber | bigint, + decimal: number, + tokenPriceGetter: CoinGeckoTokenPriceGetter, + tokenCoinGeckoId?: string, +): Promise { + const balanceFloat = parseFloat(ethers.utils.formatUnits(balance, decimal)); + const value = await getCollateralTokenValue( + tokenCoinGeckoId, + balanceFloat, + tokenPriceGetter, + ); + return { balance: balanceFloat, valueUSD: value }; +} + async function checkWarpRouteMetrics( checkFrequency: number, tokenConfig: WarpRouteConfig, chainMetadata: ChainMap, ) { + const tokenPriceGetter = + CoinGeckoTokenPriceGetter.withDefaultCoinGecko(chainMetadata); + setInterval(async () => { try { const multiProtocolProvider = new MultiProtocolProvider(chainMetadata); - const balances = await checkBalance(tokenConfig, multiProtocolProvider); + const balances = await checkBalance( + tokenConfig, + multiProtocolProvider, + tokenPriceGetter, + ); logger.info('Token Balances:', balances); updateTokenBalanceMetrics(tokenConfig, balances); } catch (e) { logger.error('Error checking balances', e); } - try { - const xERC20Limits = await getXERC20Limits(tokenConfig, chainMetadata); - logger.info('xERC20 Limits:', xERC20Limits); - updateXERC20LimitsMetrics(xERC20Limits); - } catch (e) { - logger.error('Error checking xERC20 limits', e); + // only check xERC20 limits if there are xERC20 tokens in the config + if ( + Object.keys(tokenConfig).some( + (chain) => + tokenConfig[chain].type === TokenType.XERC20 || + tokenConfig[chain].type === TokenType.XERC20Lockbox, + ) + ) { + try { + const xERC20Limits = await getXERC20Limits(tokenConfig, chainMetadata); + logger.info('xERC20 Limits:', xERC20Limits); + updateXERC20LimitsMetrics(xERC20Limits); + } catch (e) { + logger.error('Error checking xERC20 limits', e); + } } }, checkFrequency); } diff --git a/typescript/sdk/src/gas/token-prices.ts b/typescript/sdk/src/gas/token-prices.ts index 26d17cd8b..d60949630 100644 --- a/typescript/sdk/src/gas/token-prices.ts +++ b/typescript/sdk/src/gas/token-prices.ts @@ -23,23 +23,23 @@ type TokenPriceCacheEntry = { }; class TokenPriceCache { - protected cache: Map; + protected cache: Map; protected freshSeconds: number; protected evictionSeconds: number; constructor(freshSeconds = 60, evictionSeconds = 3 * 60 * 60) { - this.cache = new Map(); + this.cache = new Map(); this.freshSeconds = freshSeconds; this.evictionSeconds = evictionSeconds; } - put(chain: ChainName, price: number): void { + put(id: string, price: number): void { const now = new Date(); - this.cache.set(chain, { timestamp: now, price }); + this.cache.set(id, { timestamp: now, price }); } - isFresh(chain: ChainName): boolean { - const entry = this.cache.get(chain); + isFresh(id: string): boolean { + const entry = this.cache.get(id); if (!entry) return false; const expiryTime = new Date( @@ -49,17 +49,17 @@ class TokenPriceCache { return now < expiryTime; } - fetch(chain: ChainName): number { - const entry = this.cache.get(chain); + fetch(id: string): number { + const entry = this.cache.get(id); if (!entry) { - throw new Error(`no entry found for ${chain} in token price cache`); + throw new Error(`no entry found for ${id} in token price cache`); } const evictionTime = new Date( entry.timestamp.getTime() + 1000 * this.evictionSeconds, ); const now = new Date(); if (now > evictionTime) { - throw new Error(`evicted entry found for ${chain} in token price cache`); + throw new Error(`evicted entry found for ${id} in token price cache`); } return entry.price; } @@ -97,20 +97,30 @@ export class CoinGeckoTokenPriceGetter implements TokenPriceGetter { ); } - async getTokenPrice(chain: ChainName): Promise { - const [price] = await this.getTokenPrices([chain]); + async getTokenPrice( + chain: ChainName, + currency: string = 'usd', + ): Promise { + const [price] = await this.getTokenPrices([chain], currency); return price; } async getTokenExchangeRate( base: ChainName, quote: ChainName, + currency: string = 'usd', ): Promise { - const [basePrice, quotePrice] = await this.getTokenPrices([base, quote]); + const [basePrice, quotePrice] = await this.getTokenPrices( + [base, quote], + currency, + ); return basePrice / quotePrice; } - private async getTokenPrices(chains: ChainName[]): Promise { + private async getTokenPrices( + chains: ChainName[], + currency: string = 'usd', + ): Promise { const isMainnet = chains.map((c) => !this.metadata[c].isTestnet); const allMainnets = isMainnet.every((v) => v === true); const allTestnets = isMainnet.every((v) => v === false); @@ -125,32 +135,43 @@ export class CoinGeckoTokenPriceGetter implements TokenPriceGetter { ); } - const toQuery = chains.filter((c) => !this.cache.isFresh(c)); + const ids = chains.map( + (chain) => this.metadata[chain].gasCurrencyCoinGeckoId || chain, + ); + + await this.getTokenPriceByIds(ids, currency); + return chains.map((chain) => + this.cache.fetch(this.metadata[chain].gasCurrencyCoinGeckoId || chain), + ); + } + + public async getTokenPriceByIds( + ids: string[], + currency: string = 'usd', + ): Promise { + const toQuery = ids.filter((id) => !this.cache.isFresh(id)); + await sleep(this.sleepMsBetweenRequests); + if (toQuery.length > 0) { + let response: any; try { - await this.queryTokenPrices(toQuery); + response = await this.coinGecko.simple.price({ + ids: toQuery, + vs_currencies: [currency], + }); + + if (response.success === true) { + const prices = toQuery.map((id) => response.data[id][currency]); + toQuery.map((id, i) => this.cache.put(id, prices[i])); + } else { + rootLogger.warn('Failed to query token prices', response.message); + return undefined; + } } catch (e) { - rootLogger.warn('Failed to query token prices', e); + rootLogger.warn('Error when querying token prices', e); + return undefined; } } - return chains.map((chain) => this.cache.fetch(chain)); - } - - private async queryTokenPrices(chains: ChainName[]): Promise { - const currency = 'usd'; - // The CoinGecko API expects, in some cases, IDs that do not match - // ChainNames. - const ids = chains.map( - (chain) => this.metadata[chain].gasCurrencyCoinGeckoId || chain, - ); - // Coingecko rate limits, so we are adding this sleep - await sleep(this.sleepMsBetweenRequests); - const response = await this.coinGecko.simple.price({ - ids, - vs_currencies: [currency], - }); - const prices = ids.map((id) => response.data[id][currency]); - // Update the cache with the newly fetched prices - chains.map((chain, i) => this.cache.put(chain, prices[i])); + return ids.map((id) => this.cache.fetch(id)); } } diff --git a/typescript/sdk/src/metadata/warpRouteConfig.ts b/typescript/sdk/src/metadata/warpRouteConfig.ts index 2fd69ce03..8c1ee346c 100644 --- a/typescript/sdk/src/metadata/warpRouteConfig.ts +++ b/typescript/sdk/src/metadata/warpRouteConfig.ts @@ -10,6 +10,7 @@ const TokenConfigSchema = z.object({ type: z.nativeEnum(TokenType), hypAddress: z.string(), // HypERC20Collateral, HypERC20Synthetic, HypNativeToken address tokenAddress: z.string().optional(), // external token address needed for collateral type eg tokenAddress.balanceOf(hypAddress) + tokenCoinGeckoId: z.string().optional(), // CoinGecko id for token name: z.string(), symbol: z.string(), decimals: z.number(), diff --git a/yarn.lock b/yarn.lock index 279fe75e6..161abbd88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7971,7 +7971,7 @@ __metadata: "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" "@hyperlane-xyz/helloworld": "npm:5.6.1" - "@hyperlane-xyz/registry": "npm:4.7.0" + "@hyperlane-xyz/registry": "npm:4.10.0" "@hyperlane-xyz/sdk": "npm:5.6.1" "@hyperlane-xyz/utils": "npm:5.6.1" "@inquirer/prompts": "npm:^5.3.8" @@ -8029,6 +8029,16 @@ __metadata: languageName: unknown linkType: soft +"@hyperlane-xyz/registry@npm:4.10.0": + version: 4.10.0 + resolution: "@hyperlane-xyz/registry@npm:4.10.0" + dependencies: + yaml: "npm:2.4.5" + zod: "npm:^3.21.2" + checksum: 22bb18f426cbada8b97db0894fe5d0980dfc08ecbd5174c978b7aeb6d8df9706f93d7e9cf0630644d2455ad05feee714dc2a38ec515a717b0b257184637902fb + languageName: node + linkType: hard + "@hyperlane-xyz/registry@npm:4.7.0": version: 4.7.0 resolution: "@hyperlane-xyz/registry@npm:4.7.0" From a36fc5fb2772e9cb61c5946b6abefb8aeb6c97da Mon Sep 17 00:00:00 2001 From: Tien Dao <15717476+tiendn@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:23:19 +0700 Subject: [PATCH 195/224] fix: isObject utils fn should return only boolean value (#4756) ### Description When `isObject` pass with param `null/undefined` it returns `null/undefined` We should strict return boolean value ### Drive-by changes ```diff export function isObject(item: any): boolean { - return item && typeof item === 'object' && !Array.isArray(item); + return !!item && typeof item === 'object' && !Array.isArray(item); } ``` ### Related issues ### Backward compatibility ### Testing Has updated with test `object.test.ts` --- .changeset/quiet-spoons-sleep.md | 5 +++++ typescript/utils/src/objects.test.ts | 9 +++++++++ typescript/utils/src/objects.ts | 4 ++-- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 .changeset/quiet-spoons-sleep.md diff --git a/.changeset/quiet-spoons-sleep.md b/.changeset/quiet-spoons-sleep.md new file mode 100644 index 000000000..41bafd9c4 --- /dev/null +++ b/.changeset/quiet-spoons-sleep.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/utils': patch +--- + +fix: isObject utils fn should return only boolean value diff --git a/typescript/utils/src/objects.test.ts b/typescript/utils/src/objects.test.ts index d5ed72a6b..beab06bc3 100644 --- a/typescript/utils/src/objects.test.ts +++ b/typescript/utils/src/objects.test.ts @@ -4,6 +4,7 @@ import { deepCopy, deepEquals, diffObjMerge, + isObject, objMerge, objOmit, } from './objects.js'; @@ -74,6 +75,14 @@ describe('Object utilities', () => { expect(omitted1_2).to.eql({ a: 1, b: { d: 'string' } }); }); + it('isObject', () => { + expect(isObject({})).to.be.true; + expect(isObject([])).to.be.false; + expect(isObject(null)).to.be.false; + expect(isObject(undefined)).to.be.false; + expect(isObject(42)).to.be.false; + }); + describe('diffObjMerge', () => { it('should merge objects with equal values', () => { const actual = { a: 1, b: 2 }; diff --git a/typescript/utils/src/objects.ts b/typescript/utils/src/objects.ts index 403caa849..1917cbff6 100644 --- a/typescript/utils/src/objects.ts +++ b/typescript/utils/src/objects.ts @@ -5,8 +5,8 @@ import { ethersBigNumberSerializer } from './logging.js'; import { isNullish } from './typeof.js'; import { assert } from './validation.js'; -export function isObject(item: any) { - return item && typeof item === 'object' && !Array.isArray(item); +export function isObject(item: any): boolean { + return !!item && typeof item === 'object' && !Array.isArray(item); } export function deepEquals(v1: any, v2: any) { From 5fd4267e7949f4499c28bf9ef31552a965f30fcd Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Fri, 25 Oct 2024 16:51:44 +0100 Subject: [PATCH 196/224] fix: ensure recipients on Sealevel warp transfers are 32 bytes (#4760) ### Description Ran into an issue trying to send from Sealevel -> Cosmos where the recipient was 20 bytes. This hasn't been an issue so far because: - no previous Sealevel -> Cosmos transfers have been done in the UI - Sealevel -> EVM transfers are successful bc `addressToBytes` actually pads the 20 byte EVM addresses to 32 bytes - Sealevel -> Sealevel transfers are fine because Sealevel addys are always 32 bytes ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .changeset/olive-maps-applaud.md | 6 ++++++ .../sdk/src/token/adapters/SealevelTokenAdapter.ts | 3 ++- typescript/utils/src/addresses.test.ts | 12 ++++++++++++ typescript/utils/src/addresses.ts | 8 ++++++++ typescript/utils/src/index.ts | 1 + 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 .changeset/olive-maps-applaud.md diff --git a/.changeset/olive-maps-applaud.md b/.changeset/olive-maps-applaud.md new file mode 100644 index 000000000..1562fca15 --- /dev/null +++ b/.changeset/olive-maps-applaud.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/utils': patch +'@hyperlane-xyz/sdk': patch +--- + +Supported non-32 byte non-EVM recipients when sending warps from Sealevel diff --git a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts index 8287fa07b..1df0d8637 100644 --- a/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/SealevelTokenAdapter.ts @@ -21,6 +21,7 @@ import { addressToBytes, eqAddress, median, + padBytesToLength, } from '@hyperlane-xyz/utils'; import { BaseSealevelAdapter } from '../../app/MultiProtocolApp.js'; @@ -295,7 +296,7 @@ export abstract class SealevelHypTokenAdapter instruction: SealevelHypTokenInstruction.TransferRemote, data: new SealevelTransferRemoteInstruction({ destination_domain: destination, - recipient: addressToBytes(recipient), + recipient: padBytesToLength(addressToBytes(recipient), 32), amount_or_id: BigInt(weiAmountOrId), }), }); diff --git a/typescript/utils/src/addresses.test.ts b/typescript/utils/src/addresses.test.ts index d25e33cf8..2313ce384 100644 --- a/typescript/utils/src/addresses.test.ts +++ b/typescript/utils/src/addresses.test.ts @@ -4,6 +4,7 @@ import { addressToBytes, bytesToProtocolAddress, isZeroishAddress, + padBytesToLength, } from './addresses.js'; import { ProtocolType } from './types.js'; @@ -42,6 +43,17 @@ describe('Address utilities', () => { }); }); + describe('padBytesToLength', () => { + it('Pads bytes to a given length', () => { + const bytes = Buffer.from([1, 2, 3]); + expect(padBytesToLength(bytes, 5).equals(Buffer.from([0, 0, 1, 2, 3]))); + }); + it('Rejects bytes that exceed the target length', () => { + const bytes = Buffer.from([1, 2, 3]); + expect(() => padBytesToLength(bytes, 2)).to.throw(Error); + }); + }); + describe('bytesToProtocolAddress', () => { it('Converts bytes to address', () => { expect( diff --git a/typescript/utils/src/addresses.ts b/typescript/utils/src/addresses.ts index 88532464f..01f9fdb10 100644 --- a/typescript/utils/src/addresses.ts +++ b/typescript/utils/src/addresses.ts @@ -316,6 +316,14 @@ export function bytesToBytes32(bytes: Uint8Array): string { ); } +// Pad bytes to a certain length, padding with 0s at the start +export function padBytesToLength(bytes: Uint8Array, length: number) { + if (bytes.length > length) { + throw new Error(`bytes must be ${length} bytes or less`); + } + return Buffer.concat([Buffer.alloc(length - bytes.length), bytes]); +} + export function bytesToAddressEvm(bytes: Uint8Array): Address { return bytes32ToAddress(Buffer.from(bytes).toString('hex')); } diff --git a/typescript/utils/src/index.ts b/typescript/utils/src/index.ts index 0c18543dd..0c82c6782 100644 --- a/typescript/utils/src/index.ts +++ b/typescript/utils/src/index.ts @@ -35,6 +35,7 @@ export { normalizeAddressCosmos, normalizeAddressEvm, normalizeAddressSealevel, + padBytesToLength, shortenAddress, strip0x, } from './addresses.js'; From 34222c00fef72e0e92030689839764128c549473 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:23:47 +0000 Subject: [PATCH 197/224] Version Packages (#4751) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @hyperlane-xyz/core@5.6.1 ### Patch Changes - a42616ff3: Added overrides for transferFrom, totalSupply to reflect the internal share based accounting for the 4626 mirror asset - Updated dependencies [5fd4267e7] - Updated dependencies [a36fc5fb2] - @hyperlane-xyz/utils@5.6.2 ## @hyperlane-xyz/cli@5.6.2 ### Patch Changes - Updated dependencies [5fd4267e7] - Updated dependencies [a36fc5fb2] - @hyperlane-xyz/utils@5.6.2 - @hyperlane-xyz/sdk@5.6.2 ## @hyperlane-xyz/helloworld@5.6.2 ### Patch Changes - Updated dependencies [5fd4267e7] - Updated dependencies [a42616ff3] - @hyperlane-xyz/sdk@5.6.2 - @hyperlane-xyz/core@5.6.1 ## @hyperlane-xyz/sdk@5.6.2 ### Patch Changes - 5fd4267e7: Supported non-32 byte non-EVM recipients when sending warps from Sealevel - Updated dependencies [5fd4267e7] - Updated dependencies [a36fc5fb2] - Updated dependencies [a42616ff3] - @hyperlane-xyz/utils@5.6.2 - @hyperlane-xyz/core@5.6.1 ## @hyperlane-xyz/utils@5.6.2 ### Patch Changes - 5fd4267e7: Supported non-32 byte non-EVM recipients when sending warps from Sealevel - a36fc5fb2: fix: isObject utils fn should return only boolean value ## @hyperlane-xyz/widgets@5.6.2 ### Patch Changes - Updated dependencies [5fd4267e7] - Updated dependencies [a36fc5fb2] - @hyperlane-xyz/utils@5.6.2 - @hyperlane-xyz/sdk@5.6.2 ## @hyperlane-xyz/infra@5.6.2 ### Patch Changes - Updated dependencies [5fd4267e7] - Updated dependencies [a36fc5fb2] - @hyperlane-xyz/utils@5.6.2 - @hyperlane-xyz/sdk@5.6.2 - @hyperlane-xyz/helloworld@5.6.2 ## @hyperlane-xyz/ccip-server@5.6.2 ## @hyperlane-xyz/github-proxy@5.6.2 --------- Co-authored-by: github-actions[bot] --- .changeset/olive-maps-applaud.md | 6 ----- .changeset/quiet-spoons-sleep.md | 5 ---- .changeset/real-starfishes-fold.md | 5 ---- solidity/CHANGELOG.md | 9 +++++++ solidity/contracts/PackageVersioned.sol | 2 +- solidity/package.json | 4 ++-- typescript/ccip-server/CHANGELOG.md | 2 ++ typescript/ccip-server/package.json | 2 +- typescript/cli/CHANGELOG.md | 9 +++++++ typescript/cli/package.json | 6 ++--- typescript/cli/src/version.ts | 2 +- typescript/github-proxy/CHANGELOG.md | 2 ++ typescript/github-proxy/package.json | 2 +- typescript/helloworld/CHANGELOG.md | 9 +++++++ typescript/helloworld/package.json | 6 ++--- typescript/infra/CHANGELOG.md | 10 ++++++++ typescript/infra/package.json | 8 +++---- typescript/sdk/CHANGELOG.md | 11 +++++++++ typescript/sdk/package.json | 6 ++--- typescript/utils/CHANGELOG.md | 7 ++++++ typescript/utils/package.json | 2 +- typescript/widgets/CHANGELOG.md | 9 +++++++ typescript/widgets/package.json | 6 ++--- yarn.lock | 32 ++++++++++++------------- 24 files changed, 107 insertions(+), 55 deletions(-) delete mode 100644 .changeset/olive-maps-applaud.md delete mode 100644 .changeset/quiet-spoons-sleep.md delete mode 100644 .changeset/real-starfishes-fold.md diff --git a/.changeset/olive-maps-applaud.md b/.changeset/olive-maps-applaud.md deleted file mode 100644 index 1562fca15..000000000 --- a/.changeset/olive-maps-applaud.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/utils': patch -'@hyperlane-xyz/sdk': patch ---- - -Supported non-32 byte non-EVM recipients when sending warps from Sealevel diff --git a/.changeset/quiet-spoons-sleep.md b/.changeset/quiet-spoons-sleep.md deleted file mode 100644 index 41bafd9c4..000000000 --- a/.changeset/quiet-spoons-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/utils': patch ---- - -fix: isObject utils fn should return only boolean value diff --git a/.changeset/real-starfishes-fold.md b/.changeset/real-starfishes-fold.md deleted file mode 100644 index f161beae6..000000000 --- a/.changeset/real-starfishes-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/core': patch ---- - -Added overrides for transferFrom, totalSupply to reflect the internal share based accounting for the 4626 mirror asset diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index fbecf3809..3bbfb9ebc 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,14 @@ # @hyperlane-xyz/core +## 5.6.1 + +### Patch Changes + +- a42616ff3: Added overrides for transferFrom, totalSupply to reflect the internal share based accounting for the 4626 mirror asset +- Updated dependencies [5fd4267e7] +- Updated dependencies [a36fc5fb2] + - @hyperlane-xyz/utils@5.6.2 + ## 5.6.0 ### Minor Changes diff --git a/solidity/contracts/PackageVersioned.sol b/solidity/contracts/PackageVersioned.sol index b1fa39c8a..44913c2d9 100644 --- a/solidity/contracts/PackageVersioned.sol +++ b/solidity/contracts/PackageVersioned.sol @@ -7,5 +7,5 @@ pragma solidity >=0.6.11; **/ abstract contract PackageVersioned { // GENERATED CODE - DO NOT EDIT - string public constant PACKAGE_VERSION = "5.6.0"; + string public constant PACKAGE_VERSION = "5.6.1"; } diff --git a/solidity/package.json b/solidity/package.json index f8cbe196c..5f7eef442 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "5.6.0", + "version": "5.6.1", "dependencies": { "@arbitrum/nitro-contracts": "^1.2.1", "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "5.6.1", + "@hyperlane-xyz/utils": "5.6.2", "@layerzerolabs/lz-evm-oapp-v2": "2.0.2", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3", diff --git a/typescript/ccip-server/CHANGELOG.md b/typescript/ccip-server/CHANGELOG.md index 08febc36f..96e835745 100644 --- a/typescript/ccip-server/CHANGELOG.md +++ b/typescript/ccip-server/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/ccip-server +## 5.6.2 + ## 5.6.1 ## 5.6.0 diff --git a/typescript/ccip-server/package.json b/typescript/ccip-server/package.json index 5a7c9cdf1..35442643c 100644 --- a/typescript/ccip-server/package.json +++ b/typescript/ccip-server/package.json @@ -1,6 +1,6 @@ { "name": "@hyperlane-xyz/ccip-server", - "version": "5.6.1", + "version": "5.6.2", "description": "CCIP server", "typings": "dist/index.d.ts", "typedocMain": "src/index.ts", diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index 37fc5fea7..dfe8451c3 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,14 @@ # @hyperlane-xyz/cli +## 5.6.2 + +### Patch Changes + +- Updated dependencies [5fd4267e7] +- Updated dependencies [a36fc5fb2] + - @hyperlane-xyz/utils@5.6.2 + - @hyperlane-xyz/sdk@5.6.2 + ## 5.6.1 ### Patch Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index 9348646b8..50d2d4f49 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,13 +1,13 @@ { "name": "@hyperlane-xyz/cli", - "version": "5.6.1", + "version": "5.6.2", "description": "A command-line utility for common Hyperlane operations", "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.6.1", - "@hyperlane-xyz/utils": "5.6.1", + "@hyperlane-xyz/sdk": "5.6.2", + "@hyperlane-xyz/utils": "5.6.2", "@inquirer/core": "9.0.10", "@inquirer/figures": "1.0.5", "@inquirer/prompts": "^3.0.0", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index 8937a2bf5..087c0bddb 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.6.1'; +export const VERSION = '5.6.2'; diff --git a/typescript/github-proxy/CHANGELOG.md b/typescript/github-proxy/CHANGELOG.md index ae6e2a41a..d23057e7d 100644 --- a/typescript/github-proxy/CHANGELOG.md +++ b/typescript/github-proxy/CHANGELOG.md @@ -1,5 +1,7 @@ # @hyperlane-xyz/github-proxy +## 5.6.2 + ## 5.6.1 ## 5.6.0 diff --git a/typescript/github-proxy/package.json b/typescript/github-proxy/package.json index 9f804e01d..28d122eb4 100644 --- a/typescript/github-proxy/package.json +++ b/typescript/github-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/github-proxy", "description": "Github proxy that adds the API key to requests", - "version": "5.6.1", + "version": "5.6.2", "private": true, "scripts": { "deploy": "wrangler deploy", diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index 17f77d3d5..171117f07 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,14 @@ # @hyperlane-xyz/helloworld +## 5.6.2 + +### Patch Changes + +- Updated dependencies [5fd4267e7] +- Updated dependencies [a42616ff3] + - @hyperlane-xyz/sdk@5.6.2 + - @hyperlane-xyz/core@5.6.1 + ## 5.6.1 ### Patch Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index bc404b472..722eed273 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,11 +1,11 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "5.6.1", + "version": "5.6.2", "dependencies": { - "@hyperlane-xyz/core": "5.6.0", + "@hyperlane-xyz/core": "5.6.1", "@hyperlane-xyz/registry": "4.7.0", - "@hyperlane-xyz/sdk": "5.6.1", + "@hyperlane-xyz/sdk": "5.6.2", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index f5f25b3f3..eee615625 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,15 @@ # @hyperlane-xyz/infra +## 5.6.2 + +### Patch Changes + +- Updated dependencies [5fd4267e7] +- Updated dependencies [a36fc5fb2] + - @hyperlane-xyz/utils@5.6.2 + - @hyperlane-xyz/sdk@5.6.2 + - @hyperlane-xyz/helloworld@5.6.2 + ## 5.6.1 ### Patch Changes diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 81361ac85..c5fb41ac2 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "5.6.1", + "version": "5.6.2", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -13,10 +13,10 @@ "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@google-cloud/secret-manager": "^5.5.0", - "@hyperlane-xyz/helloworld": "5.6.1", + "@hyperlane-xyz/helloworld": "5.6.2", "@hyperlane-xyz/registry": "4.10.0", - "@hyperlane-xyz/sdk": "5.6.1", - "@hyperlane-xyz/utils": "5.6.1", + "@hyperlane-xyz/sdk": "5.6.2", + "@hyperlane-xyz/utils": "5.6.2", "@inquirer/prompts": "^5.3.8", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "1.3.0", diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index ad33e87c2..a37619fdf 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,16 @@ # @hyperlane-xyz/sdk +## 5.6.2 + +### Patch Changes + +- 5fd4267e7: Supported non-32 byte non-EVM recipients when sending warps from Sealevel +- Updated dependencies [5fd4267e7] +- Updated dependencies [a36fc5fb2] +- Updated dependencies [a42616ff3] + - @hyperlane-xyz/utils@5.6.2 + - @hyperlane-xyz/core@5.6.1 + ## 5.6.1 ### Patch Changes diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 44e35d35a..133a57927 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,14 +1,14 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "5.6.1", + "version": "5.6.2", "dependencies": { "@arbitrum/sdk": "^4.0.0", "@aws-sdk/client-s3": "^3.74.0", "@cosmjs/cosmwasm-stargate": "^0.32.4", "@cosmjs/stargate": "^0.32.4", - "@hyperlane-xyz/core": "5.6.0", - "@hyperlane-xyz/utils": "5.6.1", + "@hyperlane-xyz/core": "5.6.1", + "@hyperlane-xyz/utils": "5.6.2", "@safe-global/api-kit": "1.3.0", "@safe-global/protocol-kit": "1.3.0", "@safe-global/safe-deployments": "1.37.8", diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index 8575e59fd..bc910f9f8 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @hyperlane-xyz/utils +## 5.6.2 + +### Patch Changes + +- 5fd4267e7: Supported non-32 byte non-EVM recipients when sending warps from Sealevel +- a36fc5fb2: fix: isObject utils fn should return only boolean value + ## 5.6.1 ## 5.6.0 diff --git a/typescript/utils/package.json b/typescript/utils/package.json index e06c4cf63..6329e1203 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "5.6.1", + "version": "5.6.2", "dependencies": { "@cosmjs/encoding": "^0.32.4", "@solana/web3.js": "^1.78.0", diff --git a/typescript/widgets/CHANGELOG.md b/typescript/widgets/CHANGELOG.md index 0ded083ed..0371d680c 100644 --- a/typescript/widgets/CHANGELOG.md +++ b/typescript/widgets/CHANGELOG.md @@ -1,5 +1,14 @@ # @hyperlane-xyz/widgets +## 5.6.2 + +### Patch Changes + +- Updated dependencies [5fd4267e7] +- Updated dependencies [a36fc5fb2] + - @hyperlane-xyz/utils@5.6.2 + - @hyperlane-xyz/sdk@5.6.2 + ## 5.6.1 ### Patch Changes diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index 5160014c6..20fe43cb1 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -1,15 +1,15 @@ { "name": "@hyperlane-xyz/widgets", "description": "Common react components for Hyperlane projects", - "version": "5.6.1", + "version": "5.6.2", "peerDependencies": { "react": "^18", "react-dom": "^18" }, "dependencies": { "@headlessui/react": "^2.1.8", - "@hyperlane-xyz/sdk": "5.6.1", - "@hyperlane-xyz/utils": "5.6.1", + "@hyperlane-xyz/sdk": "5.6.2", + "@hyperlane-xyz/utils": "5.6.2", "clsx": "^2.1.1", "react-tooltip": "^5.28.0" }, diff --git a/yarn.lock b/yarn.lock index 161abbd88..ecd030eab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7824,8 +7824,8 @@ __metadata: "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.6.1" - "@hyperlane-xyz/utils": "npm:5.6.1" + "@hyperlane-xyz/sdk": "npm:5.6.2" + "@hyperlane-xyz/utils": "npm:5.6.2" "@inquirer/core": "npm:9.0.10" "@inquirer/figures": "npm:1.0.5" "@inquirer/prompts": "npm:^3.0.0" @@ -7860,13 +7860,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:5.6.0, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:5.6.1, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@arbitrum/nitro-contracts": "npm:^1.2.1" "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:5.6.1" + "@hyperlane-xyz/utils": "npm:5.6.2" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/solidity-examples": "npm:^1.1.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" @@ -7917,13 +7917,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:5.6.1, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:5.6.2, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:5.6.0" + "@hyperlane-xyz/core": "npm:5.6.1" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.6.1" + "@hyperlane-xyz/sdk": "npm:5.6.2" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -7970,10 +7970,10 @@ __metadata: "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" "@google-cloud/secret-manager": "npm:^5.5.0" - "@hyperlane-xyz/helloworld": "npm:5.6.1" + "@hyperlane-xyz/helloworld": "npm:5.6.2" "@hyperlane-xyz/registry": "npm:4.10.0" - "@hyperlane-xyz/sdk": "npm:5.6.1" - "@hyperlane-xyz/utils": "npm:5.6.1" + "@hyperlane-xyz/sdk": "npm:5.6.2" + "@hyperlane-xyz/utils": "npm:5.6.2" "@inquirer/prompts": "npm:^5.3.8" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" @@ -8049,7 +8049,7 @@ __metadata: languageName: node linkType: hard -"@hyperlane-xyz/sdk@npm:5.6.1, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:5.6.2, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: @@ -8057,8 +8057,8 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.74.0" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4" - "@hyperlane-xyz/core": "npm:5.6.0" - "@hyperlane-xyz/utils": "npm:5.6.1" + "@hyperlane-xyz/core": "npm:5.6.1" + "@hyperlane-xyz/utils": "npm:5.6.2" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@safe-global/api-kit": "npm:1.3.0" @@ -8099,7 +8099,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:5.6.1, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:5.6.2, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: @@ -8125,8 +8125,8 @@ __metadata: dependencies: "@headlessui/react": "npm:^2.1.8" "@hyperlane-xyz/registry": "npm:4.7.0" - "@hyperlane-xyz/sdk": "npm:5.6.1" - "@hyperlane-xyz/utils": "npm:5.6.1" + "@hyperlane-xyz/sdk": "npm:5.6.2" + "@hyperlane-xyz/utils": "npm:5.6.2" "@storybook/addon-essentials": "npm:^7.6.14" "@storybook/addon-interactions": "npm:^7.6.14" "@storybook/addon-links": "npm:^7.6.14" From 892a1d82826e2ca6b25e791259065d9a6dd17952 Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:00:51 +0100 Subject: [PATCH 198/224] fix: tokenAddress for native sttia (#4762) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../mainnet3/warp/STTIA-eclipsestride-deployments.yaml | 3 +-- typescript/infra/src/warp/helm.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml b/typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml index 18e934fff..9938ad9f9 100644 --- a/typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml +++ b/typescript/infra/config/environments/mainnet3/warp/STTIA-eclipsestride-deployments.yaml @@ -8,8 +8,7 @@ data: protocolType: cosmos type: collateral hypAddress: stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee - # dummy tokenAddress since stTIA is native - tokenAddress: 'stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee' + tokenAddress: 'stutia' name: Stride Staked TIA symbol: stTIA decimals: 6 diff --git a/typescript/infra/src/warp/helm.ts b/typescript/infra/src/warp/helm.ts index e7296ad0c..bbb98a6d5 100644 --- a/typescript/infra/src/warp/helm.ts +++ b/typescript/infra/src/warp/helm.ts @@ -27,7 +27,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager { return { image: { repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: 'ee5ec6b-20241025-133236', + tag: '8e2f616-20241025-163752', }, configFilePath: pathRelativeToMonorepoRoot, fullnameOverride: this.helmReleaseName, From 04108155d84d6ad09b130ff7451b6a42f03e749b Mon Sep 17 00:00:00 2001 From: Tien Dao <15717476+tiendn@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:10:00 +0700 Subject: [PATCH 199/224] fix: Add unit tests for math utility functions and fix median calculation (#4753) ### Description This pull request introduces the following changes to the math utility functions: #### Fix Median Calculation: Corrected the median function to handle even-length arrays properly by averaging the two middle numbers. #### Add Unit Tests: Implemented unit tests for the math utility functions using Chai to ensure their correctness and reliability. The functions tested include: - `median`: Tests for both odd and even-length arrays. - `sum`: Verifies the sum of an array of numbers. - `mean`: Checks the calculation of the mean. - `stdDev`: Validates the standard deviation calculation, including cases with negative numbers. - `randomInt`: Ensures the generated random integer falls within the specified range. ### Drive-by changes - Code: Updated the median function in math.ts to correctly calculate the median for even-length arrays. - Tests: Added a new test file math.test.ts with comprehensive test cases for each function. ### Related issues Fixes [#[4754]](https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4754) ### Backward compatibility Yes ### Testing - All tests have been executed and passed successfully, confirming the correctness of the functions. - Special attention was given to edge cases, such as arrays with negative numbers and random integer generation. --- .changeset/healthy-boats-lie.md | 5 ++++ typescript/utils/src/math.test.ts | 48 +++++++++++++++++++++++++++++++ typescript/utils/src/math.ts | 2 +- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 .changeset/healthy-boats-lie.md create mode 100644 typescript/utils/src/math.test.ts diff --git a/.changeset/healthy-boats-lie.md b/.changeset/healthy-boats-lie.md new file mode 100644 index 000000000..2eb1bb0a4 --- /dev/null +++ b/.changeset/healthy-boats-lie.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/utils': patch +--- + +fix median utils func + add test diff --git a/typescript/utils/src/math.test.ts b/typescript/utils/src/math.test.ts new file mode 100644 index 000000000..e2f484d65 --- /dev/null +++ b/typescript/utils/src/math.test.ts @@ -0,0 +1,48 @@ +import { expect } from 'chai'; + +import { mean, median, randomInt, stdDev, sum } from './math.js'; + +describe('Math Utility Functions', () => { + describe('median', () => { + it('should return the median of an odd-length array', () => { + expect(median([1, 3, 2])).to.equal(2); + }); + + it('should return the median of an even-length array', () => { + expect(median([1, 2, 3, 4])).to.equal(2.5); + }); + + it('should return the median of an even-length array with non sorted numbers', () => { + expect(median([1, 2, 0, 4, 5, 6])).to.equal(3); + }); + }); + + describe('sum', () => { + it('should return the sum of an array', () => { + expect(sum([1, 2, 3, 4])).to.equal(10); + }); + }); + + describe('mean', () => { + it('should return the mean of an array', () => { + expect(mean([1, 2, 3, 4])).to.equal(2.5); + }); + }); + + describe('stdDev', () => { + it('should return the standard deviation of an array', () => { + expect(stdDev([1, 2, 3, 4])).to.be.closeTo(1.118, 0.001); + }); + }); + + describe('randomInt', () => { + it('should return a random integer within the specified range', () => { + const min = 1; + const max = 10; + const result = randomInt(max, min); + expect(result).to.be.at.least(min); + expect(result).to.be.below(max); + expect(result % 1).to.equal(0); // its an integer + }); + }); +}); diff --git a/typescript/utils/src/math.ts b/typescript/utils/src/math.ts index ebca6e75e..4cc71bf80 100644 --- a/typescript/utils/src/math.ts +++ b/typescript/utils/src/math.ts @@ -2,7 +2,7 @@ export function median(a: number[]): number { const sorted = a.slice().sort(); const mid = Math.floor(sorted.length / 2); const median = - sorted.length % 2 == 0 ? (sorted[mid] + sorted[mid + 1]) / 2 : sorted[mid]; + sorted.length % 2 == 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]; return median; } From cd666d5d0c179a50590b4399ddc5d8589be1d7d7 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Mon, 28 Oct 2024 13:08:14 +0000 Subject: [PATCH 200/224] feat: add TIA and stTIA ATA payer observability (#4763) ### Description Adds TIA and stTIA ATA payer observability ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../infra/config/environments/mainnet3/funding.ts | 2 +- .../infra/scripts/funding/fund-keys-from-deployer.ts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index e69298dc3..89e34339a 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '436988a-20241017-151047', + tag: '25ae727-20241025-165028', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron diff --git a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts index d262e52c8..5eebaab1e 100644 --- a/typescript/infra/scripts/funding/fund-keys-from-deployer.ts +++ b/typescript/infra/scripts/funding/fund-keys-from-deployer.ts @@ -138,6 +138,16 @@ const sealevelAccountsToTrack: ChainMap = { pubkey: new PublicKey('CijxTbPs9JZxTUfo8Hmz2imxzHtKnDFD3kZP3RPy34uJ'), walletName: 'SOL/eclipsemainnet-solanamainnet/ata-payer', }, + { + // stTIA warp route ATA payer + pubkey: new PublicKey('Bg3bAM3gEhdam5mbPqkiMi3mLZkoAieakMRdMHo6mbcn'), + walletName: 'stTIA/eclipsemainnet-stride/ata-payer', + }, + { + // TIA warp route ATA payer + pubkey: new PublicKey('AZs4Rw6H6YwJBKoHBCfChCitHnHvQcVGgrJwGh4bKmAf'), + walletName: 'TIA/eclipsemainnet-stride/ata-payer', + }, ], }; From 5dabdf38876cfa77f60a858a4d6d53c80e5b0b18 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 28 Oct 2024 11:00:51 -0400 Subject: [PATCH 201/224] feat: do not exhaustively derive routing config in TS relayer (#4765) ### Description CLI commands using HyperlaneRelayer (`--relay`) were very slow due to exhaustive routing ISM/hook derivation. This short-circuits the derivation when there is a known "message context" to evaluate the routing hook and ISMs for. ### Related issues ### Backward compatibility Yes ### Testing Manual --- .changeset/cold-dingos-give.md | 5 +++++ typescript/sdk/src/core/HyperlaneRelayer.ts | 20 ++++++++++++++++---- typescript/sdk/src/hook/EvmHookReader.ts | 8 +++++++- typescript/sdk/src/ism/EvmIsmReader.ts | 9 +++++++-- 4 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 .changeset/cold-dingos-give.md diff --git a/.changeset/cold-dingos-give.md b/.changeset/cold-dingos-give.md new file mode 100644 index 000000000..d9eaf08d3 --- /dev/null +++ b/.changeset/cold-dingos-give.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Optimize HyperlaneRelayer routing config derivation diff --git a/typescript/sdk/src/core/HyperlaneRelayer.ts b/typescript/sdk/src/core/HyperlaneRelayer.ts index 27341a773..cb0ba570e 100644 --- a/typescript/sdk/src/core/HyperlaneRelayer.ts +++ b/typescript/sdk/src/core/HyperlaneRelayer.ts @@ -75,12 +75,18 @@ export class HyperlaneRelayer { async getHookConfig( chain: ChainName, hook: Address, + messageContext?: DispatchedMessage, ): Promise { let config: DerivedHookConfig | undefined; if (this.cache?.hook[chain]?.[hook]) { config = this.cache.hook[chain][hook] as DerivedHookConfig | undefined; } else { - const evmHookReader = new EvmHookReader(this.multiProvider, chain); + const evmHookReader = new EvmHookReader( + this.multiProvider, + chain, + undefined, + messageContext, + ); config = await evmHookReader.deriveHookConfig(hook); } @@ -98,12 +104,18 @@ export class HyperlaneRelayer { async getIsmConfig( chain: ChainName, ism: Address, + messageContext?: DispatchedMessage, ): Promise { let config: DerivedIsmConfig | undefined; if (this.cache?.ism[chain]?.[ism]) { config = this.cache.ism[chain][ism] as DerivedIsmConfig | undefined; } else { - const evmIsmReader = new EvmIsmReader(this.multiProvider, chain); + const evmIsmReader = new EvmIsmReader( + this.multiProvider, + chain, + undefined, + messageContext, + ); config = await evmIsmReader.deriveIsmConfig(ism); } @@ -124,7 +136,7 @@ export class HyperlaneRelayer { ): Promise { const originChain = this.core.getOrigin(message); const hook = await this.core.getSenderHookAddress(message); - return this.getHookConfig(originChain, hook); + return this.getHookConfig(originChain, hook, message); } async getRecipientIsmConfig( @@ -132,7 +144,7 @@ export class HyperlaneRelayer { ): Promise { const destinationChain = this.core.getDestination(message); const ism = await this.core.getRecipientIsmAddress(message); - return this.getIsmConfig(destinationChain, ism); + return this.getIsmConfig(destinationChain, ism, message); } async relayMessage( diff --git a/typescript/sdk/src/hook/EvmHookReader.ts b/typescript/sdk/src/hook/EvmHookReader.ts index 518b63e58..1ed1f42ab 100644 --- a/typescript/sdk/src/hook/EvmHookReader.ts +++ b/typescript/sdk/src/hook/EvmHookReader.ts @@ -26,6 +26,7 @@ import { } from '@hyperlane-xyz/utils'; import { DEFAULT_CONTRACT_READ_CONCURRENCY } from '../consts/concurrency.js'; +import { DispatchedMessage } from '../core/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { ChainNameOrId } from '../types.js'; import { HyperlaneReader } from '../utils/HyperlaneReader.js'; @@ -96,6 +97,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { protected readonly concurrency: number = multiProvider.tryGetRpcConcurrency( chain, ) ?? DEFAULT_CONTRACT_READ_CONCURRENCY, + protected readonly messageContext?: DispatchedMessage, ) { super(multiProvider, chain); } @@ -379,6 +381,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { address: Address, ): Promise> { const hook = DomainRoutingHook__factory.connect(address, this.provider); + this.assertHookType(await hook.hookType(), OnchainHookType.ROUTING); const owner = await hook.owner(); @@ -403,6 +406,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { address, this.provider, ); + this.assertHookType( await hook.hookType(), OnchainHookType.FALLBACK_ROUTING, @@ -430,7 +434,9 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { private async fetchDomainHooks( hook: DomainRoutingHook | FallbackDomainRoutingHook, ): Promise { - const domainIds = this.multiProvider.getKnownDomainIds(); + const domainIds = this.messageContext + ? [this.messageContext.parsed.destination] + : this.multiProvider.getKnownDomainIds(); const domainHooks: RoutingHookConfig['domains'] = {}; await concurrentMap(this.concurrency, domainIds, async (domainId) => { diff --git a/typescript/sdk/src/ism/EvmIsmReader.ts b/typescript/sdk/src/ism/EvmIsmReader.ts index c7d766e8c..47e58d2b7 100644 --- a/typescript/sdk/src/ism/EvmIsmReader.ts +++ b/typescript/sdk/src/ism/EvmIsmReader.ts @@ -1,4 +1,4 @@ -import { ethers } from 'ethers'; +import { BigNumber, ethers } from 'ethers'; import { ArbL2ToL1Ism__factory, @@ -21,6 +21,7 @@ import { } from '@hyperlane-xyz/utils'; import { DEFAULT_CONTRACT_READ_CONCURRENCY } from '../consts/concurrency.js'; +import { DispatchedMessage } from '../core/types.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { ChainNameOrId } from '../types.js'; import { HyperlaneReader } from '../utils/HyperlaneReader.js'; @@ -66,6 +67,7 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { protected readonly concurrency: number = multiProvider.tryGetRpcConcurrency( chain, ) ?? DEFAULT_CONTRACT_READ_CONCURRENCY, + protected readonly messageContext?: DispatchedMessage, ) { super(multiProvider, chain); } @@ -129,11 +131,14 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { address, this.provider, ); + const owner = await ism.owner(); this.assertModuleType(await ism.moduleType(), ModuleType.ROUTING); + const domainIds = this.messageContext + ? [BigNumber.from(this.messageContext.parsed.origin)] + : await ism.domains(); const domains: RoutingIsmConfig['domains'] = {}; - const domainIds = await ism.domains(); await concurrentMap(this.concurrency, domainIds, async (domainId) => { const chainName = this.multiProvider.tryGetChainName(domainId.toNumber()); From c622bfbcf54fec17a54662a62f063b31f7807096 Mon Sep 17 00:00:00 2001 From: Tien Dao <15717476+tiendn@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:36:26 +0700 Subject: [PATCH 202/224] test: Coverage more @hyperlane-xyz/utils test (#4758) ### Description Add more coverage `utils` package test ### Drive-by changes ### Related issues ### Backward compatibility ### Testing More unittests function --- typescript/utils/package.json | 3 + typescript/utils/src/arrays.test.ts | 54 +++++++++ typescript/utils/src/async.test.ts | 146 +++++++++++++++++++++++ typescript/utils/src/base58.test.ts | 37 ++++++ typescript/utils/src/base64.test.ts | 74 ++++++++++++ typescript/utils/src/checkpoints.test.ts | 120 +++++++++++++++++++ typescript/utils/src/checkpoints.ts | 2 +- typescript/utils/src/env.test.ts | 18 +++ typescript/utils/src/ids.test.ts | 52 ++++++++ typescript/utils/src/logging.test.ts | 39 ++++++ typescript/utils/src/math.test.ts | 5 + typescript/utils/src/sets.test.ts | 39 ++++++ typescript/utils/src/strings.test.ts | 57 +++++++++ typescript/utils/src/typeof.test.ts | 42 +++++++ typescript/utils/src/validation.test.ts | 13 ++ typescript/utils/src/yaml.test.ts | 33 +++++ yarn.lock | 3 + 17 files changed, 736 insertions(+), 1 deletion(-) create mode 100644 typescript/utils/src/arrays.test.ts create mode 100644 typescript/utils/src/async.test.ts create mode 100644 typescript/utils/src/base58.test.ts create mode 100644 typescript/utils/src/base64.test.ts create mode 100644 typescript/utils/src/checkpoints.test.ts create mode 100644 typescript/utils/src/env.test.ts create mode 100644 typescript/utils/src/ids.test.ts create mode 100644 typescript/utils/src/logging.test.ts create mode 100644 typescript/utils/src/sets.test.ts create mode 100644 typescript/utils/src/strings.test.ts create mode 100644 typescript/utils/src/typeof.test.ts create mode 100644 typescript/utils/src/validation.test.ts create mode 100644 typescript/utils/src/yaml.test.ts diff --git a/typescript/utils/package.json b/typescript/utils/package.json index 6329e1203..e3b85b1e8 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -14,9 +14,12 @@ "devDependencies": { "@types/lodash-es": "^4.17.12", "@types/mocha": "^10.0.1", + "@types/sinon": "^17.0.1", + "@types/sinon-chai": "^3.2.12", "chai": "4.5.0", "mocha": "^10.2.0", "prettier": "^2.8.8", + "sinon": "^13.0.2", "typescript": "5.3.3" }, "homepage": "https://www.hyperlane.xyz", diff --git a/typescript/utils/src/arrays.test.ts b/typescript/utils/src/arrays.test.ts new file mode 100644 index 000000000..88273591b --- /dev/null +++ b/typescript/utils/src/arrays.test.ts @@ -0,0 +1,54 @@ +import { expect } from 'chai'; + +import { chunk, exclude, randomElement } from './arrays.js'; + +describe('Arrays utilities', () => { + describe('chunk', () => { + it('should split an array into chunks of the specified size', () => { + const result = chunk([1, 2, 3, 4, 5], 2); + expect(result).to.deep.equal([[1, 2], [3, 4], [5]]); + }); + + it('should return an empty array when input is empty', () => { + const result = chunk([], 2); + expect(result).to.deep.equal([]); + }); + + it('should handle chunk size larger than array length', () => { + const result = chunk([1, 2], 5); + expect(result).to.deep.equal([[1, 2]]); + }); + }); + + describe('exclude', () => { + it('should exclude the specified item from the list', () => { + const result = exclude(2, [1, 2, 3, 2]); + expect(result).to.deep.equal([1, 3]); + }); + + it('should return the same list if item is not found', () => { + const result = exclude(4, [1, 2, 3]); + expect(result).to.deep.equal([1, 2, 3]); + }); + + it('should return an empty list if all items are excluded', () => { + const result = exclude(1, [1, 1, 1]); + expect(result).to.deep.equal([]); + }); + }); + + describe('randomElement', () => { + beforeEach(() => {}); + + it('should return a random element from the list', () => { + const list = [10, 20, 30]; + const result = randomElement(list); + expect(result).to.be.oneOf(list); + }); + + it('should handle an empty list gracefully', () => { + const result = randomElement([]); + expect(result).to.be.undefined; + }); + }); +}); diff --git a/typescript/utils/src/async.test.ts b/typescript/utils/src/async.test.ts new file mode 100644 index 000000000..004abb1d1 --- /dev/null +++ b/typescript/utils/src/async.test.ts @@ -0,0 +1,146 @@ +import { expect } from 'chai'; + +import { + concurrentMap, + fetchWithTimeout, + pollAsync, + raceWithContext, + retryAsync, + runWithTimeout, + sleep, + timeout, +} from './async.js'; + +describe('Async Utilities', () => { + describe('sleep', () => { + it('should resolve after sleep duration', async () => { + const start = Date.now(); + await sleep(100); + const duration = Date.now() - start; + expect(duration).to.be.at.least(100); + expect(duration).to.be.lessThan(200); + }); + }); + + describe('timeout', () => { + it('should timeout a promise', async () => { + const promise = new Promise((resolve) => setTimeout(resolve, 200)); + try { + await timeout(promise, 100); + throw new Error('Expected timeout error'); + } catch (error: any) { + expect(error.message).to.equal('Timeout reached'); + } + }); + }); + + describe('runWithTimeout', () => { + it('should run a callback with a timeout', async () => { + const result = await runWithTimeout(100, async () => { + await sleep(50); + return 'success'; + }); + expect(result).to.equal('success'); + }); + }); + + describe('fetchWithTimeout', () => { + it('should fetch with timeout', async () => { + // Mock fetch for testing + global.fetch = async () => { + await sleep(50); + return new Response('ok'); + }; + + const response = await fetchWithTimeout('https://example.com', {}, 100); + expect(await response.text()).to.equal('ok'); + }); + }); + + describe('retryAsync', () => { + it('should retry async function with exponential backoff', async () => { + let attempt = 0; + const runner = async () => { + attempt++; + if (attempt < 3) throw new Error('fail'); + return 'success'; + }; + + const result = await retryAsync(runner, 5, 10); + expect(result).to.equal('success'); + }); + }); + + describe('pollAsync', () => { + it('should poll async function until success', async () => { + let attempt = 0; + const runner = async () => { + attempt++; + if (attempt < 3) throw new Error('fail'); + return 'success'; + }; + + const result = await pollAsync(runner, 10, 5); + expect(result).to.equal('success'); + }); + + it('should fail after reaching max retries', async () => { + let attempt = 0; + const runner = async () => { + attempt++; + throw new Error('fail'); + }; + + try { + await pollAsync(runner, 10, 3); // Set maxAttempts to 3 + throw new Error('Expected pollAsync to throw an error'); + } catch (error: any) { + expect(attempt).to.equal(3); // Ensure it attempted 3 times + expect(error.message).to.equal('fail'); + } + }); + }); + + describe('raceWithContext', () => { + it('should race with context', async () => { + const promises = [ + sleep(50).then(() => 'first'), + sleep(100).then(() => 'second'), + ]; + + const result = await raceWithContext(promises); + expect(result.resolved).to.equal('first'); + expect(result.index).to.equal(0); + }); + }); + + describe('concurrentMap', () => { + it('should map concurrently with correct results', async () => { + const xs = [1, 2, 3, 4, 5, 6]; + const mapFn = async (val: number) => { + await new Promise((resolve) => setTimeout(resolve, 50)); // Simulate async work + return val * 2; + }; + const result = await concurrentMap(2, xs, mapFn); + expect(result).to.deep.equal([2, 4, 6, 8, 10, 12]); + }); + + it('should respect concurrency limit', async () => { + const xs = [1, 2, 3, 4, 5, 6]; + const concurrency = 2; + let activeTasks = 0; + let maxActiveTasks = 0; + + const mapFn = async (val: number) => { + activeTasks++; + maxActiveTasks = Math.max(maxActiveTasks, activeTasks); + await new Promise((resolve) => setTimeout(resolve, 50)); // Simulate async work + activeTasks--; + return val * 2; + }; + + await concurrentMap(concurrency, xs, mapFn); + expect(maxActiveTasks).to.equal(concurrency); + }); + }); +}); diff --git a/typescript/utils/src/base58.test.ts b/typescript/utils/src/base58.test.ts new file mode 100644 index 000000000..45416c787 --- /dev/null +++ b/typescript/utils/src/base58.test.ts @@ -0,0 +1,37 @@ +import { expect } from 'chai'; +import { utils } from 'ethers'; + +import { base58ToBuffer, bufferToBase58, hexOrBase58ToHex } from './base58.js'; + +describe('Base58 Utilities', () => { + describe('base58ToBuffer', () => { + it('should convert a base58 string to a buffer', () => { + const base58String = '3mJr7AoUXx2Wqd'; + const expectedBuffer = Buffer.from(utils.base58.decode(base58String)); + expect(base58ToBuffer(base58String)).to.deep.equal(expectedBuffer); + }); + }); + + describe('bufferToBase58', () => { + it('should convert a buffer to a base58 string', () => { + const buffer = Buffer.from([1, 2, 3, 4]); + const expectedBase58String = utils.base58.encode(buffer); + expect(bufferToBase58(buffer)).to.equal(expectedBase58String); + }); + }); + + describe('hexOrBase58ToHex', () => { + it('should return the hex string as is if it starts with 0x', () => { + const hexString = '0x1234abcd'; + expect(hexOrBase58ToHex(hexString)).to.equal(hexString); + }); + + it('should convert a base58 string to a hex string', () => { + const base58String = '3mJr7AoUXx2Wqd'; + const expectedHexString = utils.hexlify( + Buffer.from(utils.base58.decode(base58String)), + ); + expect(hexOrBase58ToHex(base58String)).to.equal(expectedHexString); + }); + }); +}); diff --git a/typescript/utils/src/base64.test.ts b/typescript/utils/src/base64.test.ts new file mode 100644 index 000000000..ca6cfc151 --- /dev/null +++ b/typescript/utils/src/base64.test.ts @@ -0,0 +1,74 @@ +import { expect } from 'chai'; +import Sinon from 'sinon'; + +import { fromBase64, toBase64 } from './base64.js'; +import { rootLogger } from './logging.js'; + +describe('Base64 Utility Functions', () => { + let loggerStub: sinon.SinonStub; + + beforeEach(() => { + loggerStub = Sinon.stub(rootLogger, 'error'); + }); + + afterEach(() => { + loggerStub.restore(); + }); + + describe('toBase64', () => { + it('should encode a valid object to a base64 string', () => { + const data = { key: 'value' }; + const result = toBase64(data); + expect(result).to.be.a('string'); + expect(result).to.equal(btoa(JSON.stringify(data))); + }); + + it('should return undefined for null or undefined input', () => { + expect(toBase64(null)).to.be.undefined; + expect(toBase64(undefined)).to.be.undefined; + }); + + it('should log an error for invalid input', () => { + toBase64(null); + expect(loggerStub.calledOnce).to.be.true; + expect( + loggerStub.calledWith( + 'Unable to serialize + encode data to base64', + null, + ), + ).to.be.true; + }); + }); + + describe('fromBase64', () => { + it('should decode a valid base64 string to an object', () => { + const data = { key: 'value' }; + const base64String = btoa(JSON.stringify(data)); + const result = fromBase64(base64String); + expect(result).to.deep.equal(data); + }); + + it('should return undefined for null or undefined input', () => { + expect(fromBase64(null as any)).to.be.undefined; + expect(fromBase64(undefined as any)).to.be.undefined; + }); + + it('should handle array input and decode the first element', () => { + const data = { key: 'value' }; + const base64String = btoa(JSON.stringify(data)); + const result = fromBase64([base64String, 'anotherString']); + expect(result).to.deep.equal(data); + }); + + it('should log an error for invalid base64 input', () => { + fromBase64('invalidBase64'); + expect(loggerStub.calledOnce).to.be.true; + expect( + loggerStub.calledWith( + 'Unable to decode + deserialize data from base64', + 'invalidBase64', + ), + ).to.be.true; + }); + }); +}); diff --git a/typescript/utils/src/checkpoints.test.ts b/typescript/utils/src/checkpoints.test.ts new file mode 100644 index 000000000..c35f73b9d --- /dev/null +++ b/typescript/utils/src/checkpoints.test.ts @@ -0,0 +1,120 @@ +import { expect } from 'chai'; + +import { + isCheckpoint, + isS3Checkpoint, + isS3CheckpointWithId, + isValidSignature, +} from './checkpoints.js'; +import { Checkpoint, S3Checkpoint, S3CheckpointWithId } from './types.js'; + +describe('Checkpoints', () => { + describe('isValidSignature', () => { + it('should return true for valid string signature', () => { + const signature = '0x' + 'a'.repeat(130); // Example of a valid hex string + expect(isValidSignature(signature)).to.be.true; + }); + + it('should return true for valid object signature', () => { + const signature = { + r: '0x' + 'a'.repeat(64), + s: '0x' + 'b'.repeat(64), + v: 27, + }; + expect(isValidSignature(signature)).to.be.true; + }); + + it('should return false for invalid signature', () => { + const signature = { + r: '0x' + 'a'.repeat(64), + s: '0x' + 'b'.repeat(64), + v: 'invalid', + }; + expect(isValidSignature(signature)).to.be.false; + }); + }); + + describe('isCheckpoint', () => { + it('should return true for valid checkpoint', () => { + const checkpoint: Checkpoint = { + root: '0x' + 'a'.repeat(64), + index: 1, + merkle_tree_hook_address: '0x' + 'b'.repeat(40), + mailbox_domain: 123, + }; + expect(isCheckpoint(checkpoint)).to.be.true; + }); + + it('should return false for invalid checkpoint', () => { + const checkpoint = { + root: 'invalid', + index: 'invalid', + merkle_tree_hook_address: 'invalid', + mailbox_domain: 'invalid', + }; + expect(isCheckpoint(checkpoint)).to.be.false; + }); + }); + + describe('isS3Checkpoint', () => { + it('should return true for valid S3Checkpoint', () => { + const s3Checkpoint: S3Checkpoint = { + signature: '0x' + 'a'.repeat(130), + value: { + root: '0x' + 'a'.repeat(64), + index: 1, + merkle_tree_hook_address: '0x' + 'b'.repeat(40), + mailbox_domain: 123, + }, + }; + expect(isS3Checkpoint(s3Checkpoint)).to.be.true; + }); + + it('should return false for invalid S3Checkpoint', () => { + const s3Checkpoint = { + signature: 'invalid', + value: { + root: 'invalid', + index: 'invalid', + merkle_tree_hook_address: 'invalid', + mailbox_domain: 'invalid', + }, + }; + expect(isS3Checkpoint(s3Checkpoint)).to.be.false; + }); + }); + + describe('isS3CheckpointWithId', () => { + it('should return true for valid S3CheckpointWithId', () => { + const s3CheckpointWithId: S3CheckpointWithId = { + signature: '0x' + 'a'.repeat(130), + value: { + checkpoint: { + root: '0x' + 'a'.repeat(64), + index: 1, + merkle_tree_hook_address: '0x' + 'b'.repeat(40), + mailbox_domain: 123, + }, + message_id: '0x' + 'c'.repeat(64), + }, + }; + expect(isS3CheckpointWithId(s3CheckpointWithId)).to.be.true; + }); + + it('should return false for invalid S3CheckpointWithId', () => { + const s3CheckpointWithId = { + signature: 'invalid', + value: { + checkpoint: { + root: 'invalid', + index: 'invalid', + merkle_tree_hook_address: 'invalid', + mailbox_domain: 'invalid', + }, + message_id: 'invalid', + }, + }; + expect(isS3CheckpointWithId(s3CheckpointWithId)).to.be.false; + }); + }); +}); diff --git a/typescript/utils/src/checkpoints.ts b/typescript/utils/src/checkpoints.ts index d83d54c68..88afc705e 100644 --- a/typescript/utils/src/checkpoints.ts +++ b/typescript/utils/src/checkpoints.ts @@ -7,7 +7,7 @@ import { SignatureLike, } from './types.js'; -function isValidSignature(signature: any): signature is SignatureLike { +export function isValidSignature(signature: any): signature is SignatureLike { return typeof signature === 'string' ? utils.isHexString(signature) : utils.isHexString(signature.r) && diff --git a/typescript/utils/src/env.test.ts b/typescript/utils/src/env.test.ts new file mode 100644 index 000000000..3772fcb4d --- /dev/null +++ b/typescript/utils/src/env.test.ts @@ -0,0 +1,18 @@ +import { expect } from 'chai'; + +import { safelyAccessEnvVar } from './env.js'; + +describe('Env Utilities', () => { + describe('safelyAccessEnvVar', () => { + it('should return the environment variable', () => { + process.env.TEST_VAR = '0xTEST_VAR'; + expect(safelyAccessEnvVar('TEST_VAR')).to.equal('0xTEST_VAR'); + expect(safelyAccessEnvVar('TEST_VAR', true)).to.equal('0xtest_var'); + }); + + it('should return undefined if the environment variable is not set', () => { + expect(safelyAccessEnvVar('NON_EXISTENT_VAR')).to.be.undefined; + expect(safelyAccessEnvVar('NON_EXISTENT_VAR', true)).to.be.undefined; + }); + }); +}); diff --git a/typescript/utils/src/ids.test.ts b/typescript/utils/src/ids.test.ts new file mode 100644 index 000000000..5008eeaf1 --- /dev/null +++ b/typescript/utils/src/ids.test.ts @@ -0,0 +1,52 @@ +import { expect } from 'chai'; +import { utils } from 'ethers'; + +import { canonizeId, evmId } from './ids.js'; + +describe('ID Utilities', () => { + describe('canonizeId', () => { + it('should convert a 20-byte ID to a 32-byte ID', () => { + const id = '0x1234567890123456789012345678901234567890'; + const result = canonizeId(id); + expect(result).to.be.instanceOf(Uint8Array); + expect(result.length).to.equal(32); + expect(utils.hexlify(result)).to.equal( + '0x0000000000000000000000001234567890123456789012345678901234567890', + ); + }); + + it('should throw an error for IDs longer than 32 bytes', () => { + const id = '0x' + '12'.repeat(33); + expect(() => canonizeId(id)).to.throw('Too long'); + }); + + it('should throw an error for IDs not 20 or 32 bytes', () => { + const id = '0x1234567890'; + expect(() => canonizeId(id)).to.throw( + 'bad input, expect address or bytes32', + ); + }); + }); + + describe('evmId', () => { + it('should convert a 32-byte ID to a 20-byte EVM address', () => { + const id = + '0x' + '00'.repeat(12) + '1234567890123456789012345678901234567890'; + const result = evmId(id); + expect(result).to.equal('0x1234567890123456789012345678901234567890'); + }); + + it('should return the same 20-byte ID as a 20-byte EVM address', () => { + const id = '0x1234567890123456789012345678901234567890'; + const result = evmId(id); + expect(result).to.equal(id); + }); + + it('should throw an error for IDs not 20 or 32 bytes', () => { + const id = '0x1234567890'; + expect(() => evmId(id)).to.throw( + 'Invalid id length. expected 20 or 32. Got 5', + ); + }); + }); +}); diff --git a/typescript/utils/src/logging.test.ts b/typescript/utils/src/logging.test.ts new file mode 100644 index 000000000..812ac8f5a --- /dev/null +++ b/typescript/utils/src/logging.test.ts @@ -0,0 +1,39 @@ +import { expect } from 'chai'; +import { BigNumber } from 'ethers'; + +import { ethersBigNumberSerializer } from './logging.js'; + +describe('Logging Utilities', () => { + describe('ethersBigNumberSerializer', () => { + it('should serialize a BigNumber object correctly', () => { + const key = 'testKey'; + const value = { + type: 'BigNumber', + hex: '0x1a', + }; + const result = ethersBigNumberSerializer(key, value); + expect(result).to.equal(BigNumber.from(value.hex).toString()); + }); + + it('should return the value unchanged if it is not a BigNumber', () => { + const key = 'testKey'; + const value = { some: 'object' }; + const result = ethersBigNumberSerializer(key, value); + expect(result).to.equal(value); + }); + + it('should return the value unchanged if it is null', () => { + const key = 'testKey'; + const value = null; + const result = ethersBigNumberSerializer(key, value); + expect(result).to.equal(value); + }); + + it('should return the value unchanged if it is not an object', () => { + const key = 'testKey'; + const value = 'string'; + const result = ethersBigNumberSerializer(key, value); + expect(result).to.equal(value); + }); + }); +}); diff --git a/typescript/utils/src/math.test.ts b/typescript/utils/src/math.test.ts index e2f484d65..85cbee588 100644 --- a/typescript/utils/src/math.test.ts +++ b/typescript/utils/src/math.test.ts @@ -20,6 +20,7 @@ describe('Math Utility Functions', () => { describe('sum', () => { it('should return the sum of an array', () => { expect(sum([1, 2, 3, 4])).to.equal(10); + expect(sum([1, -2, 3, 4])).to.equal(6); }); }); @@ -33,6 +34,10 @@ describe('Math Utility Functions', () => { it('should return the standard deviation of an array', () => { expect(stdDev([1, 2, 3, 4])).to.be.closeTo(1.118, 0.001); }); + + it('should return the standard deviation of an array with negative numbers', () => { + expect(stdDev([-1, -2, -3, -4])).to.be.closeTo(1.118, 0.001); + }); }); describe('randomInt', () => { diff --git a/typescript/utils/src/sets.test.ts b/typescript/utils/src/sets.test.ts new file mode 100644 index 000000000..3f4195b4d --- /dev/null +++ b/typescript/utils/src/sets.test.ts @@ -0,0 +1,39 @@ +import { expect } from 'chai'; + +import { difference, setEquality, symmetricDifference } from './sets.js'; + +describe('Set Operations', () => { + describe('difference', () => { + it('should return the difference of two sets', () => { + const setA = new Set([1, 2, 3, undefined]); + const setB = new Set([2, 3, 4]); + const result = difference(setA, setB); + expect(result).to.deep.equal(new Set([1, undefined])); + }); + }); + + describe('symmetricDifference', () => { + it('should return the symmetric difference of two sets', () => { + const setA = new Set([1, 2, 3]); + const setB = new Set([2, 3, 4]); + const result = symmetricDifference(setA, setB); + expect(result).to.deep.equal(new Set([1, 4])); + }); + }); + + describe('setEquality', () => { + it('should return true for equal sets', () => { + const setA = new Set([1, 2, 3]); + const setB = new Set([1, 2, 3]); + const result = setEquality(setA, setB); + expect(result).to.be.true; + }); + + it('should return false for non-equal sets', () => { + const setA = new Set([1, 2, 3]); + const setB = new Set([1, 2, 4]); + const result = setEquality(setA, setB); + expect(result).to.be.false; + }); + }); +}); diff --git a/typescript/utils/src/strings.test.ts b/typescript/utils/src/strings.test.ts new file mode 100644 index 000000000..3cf479823 --- /dev/null +++ b/typescript/utils/src/strings.test.ts @@ -0,0 +1,57 @@ +import { expect } from 'chai'; +import { Readable } from 'stream'; + +import { + errorToString, + fromHexString, + sanitizeString, + streamToString, + toHexString, + toTitleCase, + trimToLength, +} from './strings.js'; + +describe('String Utilities', () => { + it('should convert string to title case', () => { + expect(toTitleCase('hello world')).to.equal('Hello World'); + expect(toTitleCase('HELLO WORLD')).to.equal('Hello World'); + expect(toTitleCase('4ELLO WORLD')).to.equal('4ello World'); + expect(toTitleCase('')).to.equal(''); + }); + + it('should sanitize string by removing non-alphanumeric characters', () => { + expect(sanitizeString('Hello, World!')).to.equal('helloworld'); + expect(sanitizeString('123-456')).to.equal('123456'); + expect(sanitizeString('')).to.equal(''); + }); + + it('should trim string to specified length', () => { + expect(trimToLength('Hello, World!', 5)).to.equal('Hello...'); + expect(trimToLength('Short', 10)).to.equal('Short'); + expect(trimToLength('', 10)).to.equal(''); + }); + + it('should convert stream to string', async () => { + const stream = new Readable(); + stream.push('Hello, '); + stream.push('World!'); + stream.push(null); + + const result = await streamToString(stream); + expect(result).to.equal('Hello, World!'); + }); + + it('should convert error to string', () => { + expect(errorToString('Error message')).to.equal('Error message'); + expect(errorToString({ message: 'Error object' })).to.equal('Error object'); + expect(errorToString(404)).to.equal('Error code: 404'); + expect(errorToString(null)).to.equal('Unknown Error'); + }); + + it('should convert hex string to buffer and back', () => { + const hexString = '0x48656c6c6f'; + const buffer = fromHexString(hexString); + expect(buffer.toString('utf8')).to.equal('Hello'); + expect(toHexString(buffer)).to.equal(hexString); + }); +}); diff --git a/typescript/utils/src/typeof.test.ts b/typescript/utils/src/typeof.test.ts new file mode 100644 index 000000000..31382a374 --- /dev/null +++ b/typescript/utils/src/typeof.test.ts @@ -0,0 +1,42 @@ +import { expect } from 'chai'; + +import { isNullish, isNumeric } from './typeof.js'; + +describe('isNullish', () => { + it('should return true for null', () => { + expect(isNullish(null)).to.be.true; + }); + + it('should return true for undefined', () => { + expect(isNullish(undefined)).to.be.true; + }); + + it('should return false for non-nullish values', () => { + expect(isNullish('')).to.be.false; + expect(isNullish(0)).to.be.false; + expect(isNullish(false)).to.be.false; + }); +}); + +describe('isNumeric', () => { + it('should return true for numeric strings', () => { + expect(isNumeric('123')).to.be.true; + }); + + it('should return true for numbers', () => { + expect(isNumeric(123)).to.be.true; + }); + + it('should return true for negative numbers', () => { + expect(isNumeric(-123)).to.be.true; + }); + + it('should return true for floating point numbers', () => { + expect(isNumeric(123.45)).to.be.true; + }); + + it('should return false for non-numeric strings', () => { + expect(isNumeric('abc')).to.be.false; + expect(isNumeric('123abc')).to.be.false; + }); +}); diff --git a/typescript/utils/src/validation.test.ts b/typescript/utils/src/validation.test.ts new file mode 100644 index 000000000..7521a4ebf --- /dev/null +++ b/typescript/utils/src/validation.test.ts @@ -0,0 +1,13 @@ +import { expect } from 'chai'; + +import { assert } from './validation.js'; + +describe('assert', () => { + it('should not throw an error when the predicate is true', () => { + expect(() => assert(true, 'Error message')).to.not.throw(); + }); + + it('should throw an error when the predicate is false', () => { + expect(() => assert(false, 'Error message')).to.throw('Error message'); + }); +}); diff --git a/typescript/utils/src/yaml.test.ts b/typescript/utils/src/yaml.test.ts new file mode 100644 index 000000000..3e69dd309 --- /dev/null +++ b/typescript/utils/src/yaml.test.ts @@ -0,0 +1,33 @@ +import { expect } from 'chai'; + +import { tryParseJsonOrYaml } from './yaml.js'; + +describe('tryParseJsonOrYaml', () => { + it('should parse valid JSON string', () => { + const jsonString = '{"key": "value"}'; + const result: any = tryParseJsonOrYaml(jsonString); + expect(result.success).to.be.true; + expect(result.data).to.deep.equal({ key: 'value' }); + }); + + it('should parse valid YAML string', () => { + const yamlString = 'key: value'; + const result: any = tryParseJsonOrYaml(yamlString); + expect(result.success).to.be.true; + expect(result.data).to.deep.equal({ key: 'value' }); + }); + + it('should fail for invalid JSON string', () => { + const invalidJsonString = '{"key": "value"'; + const result: any = tryParseJsonOrYaml(invalidJsonString); + expect(result.success).to.be.false; + expect(result.error).to.equal('Input is not valid JSON or YAML'); + }); + + it('should fail for invalid YAML string', () => { + const invalidYamlString = 'key: value:'; + const result: any = tryParseJsonOrYaml(invalidYamlString); + expect(result.success).to.be.false; + expect(result.error).to.equal('Input is not valid JSON or YAML'); + }); +}); diff --git a/yarn.lock b/yarn.lock index ecd030eab..884d2b208 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8107,6 +8107,8 @@ __metadata: "@solana/web3.js": "npm:^1.78.0" "@types/lodash-es": "npm:^4.17.12" "@types/mocha": "npm:^10.0.1" + "@types/sinon": "npm:^17.0.1" + "@types/sinon-chai": "npm:^3.2.12" bignumber.js: "npm:^9.1.1" chai: "npm:4.5.0" ethers: "npm:^5.7.2" @@ -8114,6 +8116,7 @@ __metadata: mocha: "npm:^10.2.0" pino: "npm:^8.19.0" prettier: "npm:^2.8.8" + sinon: "npm:^13.0.2" typescript: "npm:5.3.3" yaml: "npm:2.4.5" languageName: unknown From e104cf6aa31bffc1bf026140cfaa5f6e50febf75 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 28 Oct 2024 13:28:12 -0400 Subject: [PATCH 203/224] refactor: dedupe HyperlaneIsmFactory and IsmModule.create (#4732) ### Description - Uses HyperlaneIsmFactory in IsmModuleCreate for deduping redundant code ### Backward compatibility Yes ### Testing Unit tests --- .changeset/dirty-swans-drum.md | 6 + typescript/sdk/src/contracts/contracts.ts | 31 +- typescript/sdk/src/core/EvmCoreModule.ts | 15 +- .../sdk/src/deploy/EvmModuleDeployer.ts | 359 --------------- .../sdk/src/deploy/HyperlaneDeployer.ts | 5 +- typescript/sdk/src/hook/EvmHookModule.ts | 150 +++---- typescript/sdk/src/ism/EvmIsmModule.ts | 417 ++---------------- .../ism/HyperlaneIsmFactory.hardhat-test.ts | 1 - typescript/sdk/src/ism/HyperlaneIsmFactory.ts | 85 ++-- .../sdk/src/token/EvmERC20WarpModule.ts | 15 +- typescript/utils/src/index.ts | 11 +- typescript/utils/src/sets.ts | 10 + 12 files changed, 237 insertions(+), 868 deletions(-) create mode 100644 .changeset/dirty-swans-drum.md delete mode 100644 typescript/sdk/src/deploy/EvmModuleDeployer.ts diff --git a/.changeset/dirty-swans-drum.md b/.changeset/dirty-swans-drum.md new file mode 100644 index 000000000..963f91b39 --- /dev/null +++ b/.changeset/dirty-swans-drum.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/utils': patch +'@hyperlane-xyz/sdk': patch +--- + +Dedupe internals of hook and ISM module deploy code diff --git a/typescript/sdk/src/contracts/contracts.ts b/typescript/sdk/src/contracts/contracts.ts index 5f1913a55..aadeba085 100644 --- a/typescript/sdk/src/contracts/contracts.ts +++ b/typescript/sdk/src/contracts/contracts.ts @@ -1,10 +1,11 @@ import { Contract } from 'ethers'; -import { Ownable } from '@hyperlane-xyz/core'; +import { Ownable, Ownable__factory } from '@hyperlane-xyz/core'; import { Address, ProtocolType, ValueOf, + eqAddress, hexOrBase58ToHex, objFilter, objMap, @@ -12,8 +13,10 @@ import { promiseObjAll, } from '@hyperlane-xyz/utils'; +import { OwnableConfig } from '../deploy/types.js'; import { ChainMetadataManager } from '../metadata/ChainMetadataManager.js'; import { MultiProvider } from '../providers/MultiProvider.js'; +import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { ChainMap, Connection } from '../types.js'; import { @@ -257,3 +260,29 @@ export function appFromAddressesMapHelper( multiProvider, }; } + +export function transferOwnershipTransactions( + chainId: number, + contract: Address, + actual: OwnableConfig, + expected: OwnableConfig, + label?: string, +): AnnotatedEV5Transaction[] { + if (eqAddress(actual.owner, expected.owner)) { + return []; + } + + return [ + { + chainId, + annotation: `Transferring ownership of ${label ?? contract} from ${ + actual.owner + } to ${expected.owner}`, + to: contract, + data: Ownable__factory.createInterface().encodeFunctionData( + 'transferOwnership', + [expected.owner], + ), + }, + ]; +} diff --git a/typescript/sdk/src/core/EvmCoreModule.ts b/typescript/sdk/src/core/EvmCoreModule.ts index fd4e96018..1be81d98f 100644 --- a/typescript/sdk/src/core/EvmCoreModule.ts +++ b/typescript/sdk/src/core/EvmCoreModule.ts @@ -10,6 +10,7 @@ import { import { attachContractsMap, serializeContractsMap, + transferOwnershipTransactions, } from '../contracts/contracts.js'; import { HyperlaneAddresses, @@ -17,7 +18,6 @@ import { } from '../contracts/types.js'; import { DeployedCoreAddresses } from '../core/schemas.js'; import { CoreConfig } from '../core/types.js'; -import { EvmModuleDeployer } from '../deploy/EvmModuleDeployer.js'; import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js'; import { ProxyFactoryFactories, @@ -202,12 +202,13 @@ export class EvmCoreModule extends HyperlaneModule< actualConfig: CoreConfig, expectedConfig: CoreConfig, ): AnnotatedEV5Transaction[] { - return EvmModuleDeployer.createTransferOwnershipTx({ - actualOwner: actualConfig.owner, - expectedOwner: expectedConfig.owner, - deployedAddress: this.args.addresses.mailbox, - chainId: this.domainId, - }); + return transferOwnershipTransactions( + this.domainId, + this.args.addresses.mailbox, + actualConfig, + expectedConfig, + 'Mailbox', + ); } /** diff --git a/typescript/sdk/src/deploy/EvmModuleDeployer.ts b/typescript/sdk/src/deploy/EvmModuleDeployer.ts deleted file mode 100644 index 6b2a09eba..000000000 --- a/typescript/sdk/src/deploy/EvmModuleDeployer.ts +++ /dev/null @@ -1,359 +0,0 @@ -import { ethers } from 'ethers'; -import { Logger } from 'pino'; - -import { - Ownable__factory, - StaticAddressSetFactory, - StaticThresholdAddressSetFactory, - TransparentUpgradeableProxy__factory, -} from '@hyperlane-xyz/core'; -import { buildArtifact as coreBuildArtifact } from '@hyperlane-xyz/core/buildArtifact.js'; -import { - Address, - addBufferToGasLimit, - eqAddress, - rootLogger, -} from '@hyperlane-xyz/utils'; - -import { HyperlaneContracts, HyperlaneFactories } from '../contracts/types.js'; -import { MultiProvider } from '../providers/MultiProvider.js'; -import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; -import { ChainMap, ChainName } from '../types.js'; - -import { isProxy, proxyConstructorArgs } from './proxy.js'; -import { ContractVerifier } from './verify/ContractVerifier.js'; -import { - ContractVerificationInput, - ExplorerLicenseType, -} from './verify/types.js'; -import { getContractVerificationInput } from './verify/utils.js'; - -export class EvmModuleDeployer { - public verificationInputs: ChainMap = {}; - - constructor( - protected readonly multiProvider: MultiProvider, - protected readonly factories: Factories, - protected readonly logger = rootLogger.child({ - module: 'EvmModuleDeployer', - }), - protected readonly contractVerifier?: ContractVerifier, - ) { - this.contractVerifier ??= new ContractVerifier( - multiProvider, - {}, - coreBuildArtifact, - ExplorerLicenseType.MIT, - ); - } - - // Deploys a contract from a factory - public async deployContractFromFactory({ - chain, - factory, - contractName, - constructorArgs, - initializeArgs, - implementationAddress, - }: { - chain: ChainName; - factory: F; - contractName: string; - constructorArgs: Parameters; - initializeArgs?: Parameters>['initialize']>; - implementationAddress?: Address; - }): Promise> { - this.logger.info( - `Deploying ${contractName} on ${chain} with constructor args (${constructorArgs.join( - ', ', - )})...`, - ); - const contract = await this.multiProvider.handleDeploy( - chain, - factory, - constructorArgs, - ); - - if (initializeArgs) { - this.logger.debug(`Initialize ${contractName} on ${chain}`); - // Estimate gas for the initialize transaction - const estimatedGas = await contract.estimateGas.initialize( - ...initializeArgs, - ); - - // deploy with buffer on gas limit - const overrides = this.multiProvider.getTransactionOverrides(chain); - const initTx = await contract.initialize(...initializeArgs, { - gasLimit: addBufferToGasLimit(estimatedGas), - ...overrides, - }); - - await this.multiProvider.handleTx(chain, initTx); - } - - const verificationInput = getContractVerificationInput({ - name: contractName, - contract, - bytecode: factory.bytecode, - expectedimplementation: implementationAddress, - }); - this.addVerificationArtifacts({ chain, artifacts: [verificationInput] }); - - // try verifying contract - try { - await this.contractVerifier?.verifyContract(chain, verificationInput); - } catch (error) { - // log error but keep deploying, can also verify post-deployment if needed - this.logger.debug(`Error verifying contract: ${error}`); - } - - return contract; - } - - /** - * Deploys a contract with a specified name. - * - * This function is capable of deploying any contract type defined within the `Factories` type to a specified chain. - * - * @param {ChainName} chain - The name of the chain on which the contract is to be deployed. - * @param {K} contractKey - The key identifying the factory to use for deployment. - * @param {string} contractName - The name of the contract to deploy. This must match the contract source code. - * @param {Parameters} constructorArgs - Arguments for the contract's constructor. - * @param {Parameters>['initialize']>?} initializeArgs - Optional arguments for the contract's initialization function. - * @returns {Promise[K]>} A promise that resolves to the deployed contract instance. - */ - public async deployContractWithName({ - chain, - contractKey, - contractName, - constructorArgs, - initializeArgs, - }: { - chain: ChainName; - contractKey: K; - contractName: string; - constructorArgs: Parameters; - initializeArgs?: Parameters< - Awaited>['initialize'] - >; - }): Promise[K]> { - const contract = await this.deployContractFromFactory({ - chain, - factory: this.factories[contractKey], - contractName, - constructorArgs, - initializeArgs, - }); - return contract; - } - - // Deploys a contract with the same name as the contract key - public async deployContract({ - chain, - contractKey, - constructorArgs, - initializeArgs, - }: { - chain: ChainName; - contractKey: K; - constructorArgs: Parameters; - initializeArgs?: Parameters< - Awaited>['initialize'] - >; - }): Promise[K]> { - return this.deployContractWithName({ - chain, - contractKey, - contractName: contractKey.toString(), - constructorArgs, - initializeArgs, - }); - } - - // Deploys the Implementation and Proxy for a given contract - public async deployProxiedContract({ - chain, - contractKey, - contractName, - proxyAdmin, - constructorArgs, - initializeArgs, - }: { - chain: ChainName; - contractKey: K; - contractName: string; - proxyAdmin: string; - constructorArgs: Parameters; - initializeArgs?: Parameters[K]['initialize']>; - }): Promise[K]> { - // Try to initialize the implementation even though it may not be necessary - const implementation = await this.deployContractWithName({ - chain, - contractKey, - contractName, - constructorArgs, - initializeArgs, - }); - - // Initialize the proxy the same way - return this.deployProxy({ - chain, - implementation, - proxyAdmin, - initializeArgs, - }); - } - - // Deploys a proxy for a given implementation contract - protected async deployProxy({ - chain, - implementation, - proxyAdmin, - initializeArgs, - }: { - chain: ChainName; - implementation: C; - proxyAdmin: string; - initializeArgs?: Parameters; - }): Promise { - const isProxied = await isProxy( - this.multiProvider.getProvider(chain), - implementation.address, - ); - if (isProxied) { - // if the implementation is already a proxy, do not deploy a new proxy - return implementation; - } - - const constructorArgs = proxyConstructorArgs( - implementation, - proxyAdmin, - initializeArgs, - ); - const proxy = await this.deployContractFromFactory({ - chain, - factory: new TransparentUpgradeableProxy__factory(), - contractName: 'TransparentUpgradeableProxy', - constructorArgs, - implementationAddress: implementation.address, - }); - - return implementation.attach(proxy.address) as C; - } - - // Adds verification artifacts to the verificationInputs map - protected addVerificationArtifacts({ - chain, - artifacts, - }: { - chain: ChainName; - artifacts: ContractVerificationInput[]; - }): void { - this.verificationInputs[chain] = this.verificationInputs[chain] || []; - artifacts.forEach((artifact) => { - this.verificationInputs[chain].push(artifact); - }); - } - - // Static deploy function used by Hook and ISM modules. - public static async deployStaticAddressSet({ - chain, - factory, - values, - logger, - threshold = values.length, - multiProvider, - }: { - chain: ChainName; - factory: StaticThresholdAddressSetFactory | StaticAddressSetFactory; - values: Address[]; - logger: Logger; - threshold?: number; - multiProvider: MultiProvider; - }): Promise
{ - const sortedValues = [...values].sort(); - - const address = await factory['getAddress(address[],uint8)']( - sortedValues, - threshold, - ); - const code = await multiProvider.getProvider(chain).getCode(address); - if (code === '0x') { - logger.debug( - `Deploying new ${threshold} of ${sortedValues.length} address set to ${chain}`, - ); - const overrides = multiProvider.getTransactionOverrides(chain); - - // estimate gas - const estimatedGas = await factory.estimateGas['deploy(address[],uint8)']( - sortedValues, - threshold, - overrides, - ); - - // add gas buffer - const hash = await factory['deploy(address[],uint8)']( - sortedValues, - threshold, - { - gasLimit: addBufferToGasLimit(estimatedGas), - ...overrides, - }, - ); - - await multiProvider.handleTx(chain, hash); - } else { - logger.debug( - `Recovered ${threshold} of ${sortedValues.length} address set on ${chain}: ${address}`, - ); - } - - // TODO: figure out how to get the constructor arguments for manual deploy TXs - // const verificationInput = buildVerificationInput( - // NAME, - // ADDRESS, - // CONSTRUCTOR_ARGS, - // ); - // await this.deployer.verifyContract( - // this.chainName, - // verificationInput, - // logger, - // ); - - return address; - } - - /** - * Transfers ownership of a contract to a new owner. - * - * @param actualOwner - The current owner of the contract. - * @param expectedOwner - The expected new owner of the contract. - * @param deployedAddress - The address of the deployed contract. - * @param chainId - The chain ID of the network the contract is deployed on. - * @returns An array of annotated EV5 transactions that need to be executed to update the owner. - */ - public static createTransferOwnershipTx(params: { - actualOwner: Address; - expectedOwner: Address; - deployedAddress: Address; - chainId: number; - }): AnnotatedEV5Transaction[] { - const { actualOwner, expectedOwner, deployedAddress, chainId } = params; - const updateTransactions: AnnotatedEV5Transaction[] = []; - if (eqAddress(actualOwner, expectedOwner)) { - return []; - } - - updateTransactions.push({ - annotation: `Transferring ownership of ${deployedAddress} from current owner ${actualOwner} to new owner ${expectedOwner}`, - chainId, - to: deployedAddress, - data: Ownable__factory.createInterface().encodeFunctionData( - 'transferOwnership(address)', - [expectedOwner], - ), - }); - - return updateTransactions; - } -} diff --git a/typescript/sdk/src/deploy/HyperlaneDeployer.ts b/typescript/sdk/src/deploy/HyperlaneDeployer.ts index 8203c7919..c6cd2048c 100644 --- a/typescript/sdk/src/deploy/HyperlaneDeployer.ts +++ b/typescript/sdk/src/deploy/HyperlaneDeployer.ts @@ -74,6 +74,8 @@ export abstract class HyperlaneDeployer< public cachedAddresses: HyperlaneAddressesMap = {}; public deployedContracts: HyperlaneContractsMap = {}; + protected cachingEnabled = true; + protected logger: Logger; chainTimeoutMs: number; @@ -86,7 +88,6 @@ export abstract class HyperlaneDeployer< ) { this.logger = options?.logger ?? rootLogger.child({ module: 'deployer' }); this.chainTimeoutMs = options?.chainTimeoutMs ?? 15 * 60 * 1000; // 15 minute timeout per chain - this.options.ismFactory?.setDeployer(this); if (Object.keys(icaAddresses).length > 0) { this.options.icaApp = InterchainAccount.fromAddressesMap( icaAddresses, @@ -374,7 +375,7 @@ export abstract class HyperlaneDeployer< shouldRecover = true, implementationAddress?: Address, ): Promise> { - if (shouldRecover) { + if (this.cachingEnabled && shouldRecover) { const cachedContract = this.readCache(chain, factory, contractName); if (cachedContract) { if (this.recoverVerificationInputs) { diff --git a/typescript/sdk/src/hook/EvmHookModule.ts b/typescript/sdk/src/hook/EvmHookModule.ts index fb8e12842..a1b6d1412 100644 --- a/typescript/sdk/src/hook/EvmHookModule.ts +++ b/typescript/sdk/src/hook/EvmHookModule.ts @@ -40,16 +40,16 @@ import { HyperlaneModuleParams, } from '../core/AbstractHyperlaneModule.js'; import { CoreAddresses } from '../core/contracts.js'; -import { EvmModuleDeployer } from '../deploy/EvmModuleDeployer.js'; +import { HyperlaneDeployer } from '../deploy/HyperlaneDeployer.js'; import { ProxyFactoryFactories } from '../deploy/contracts.js'; import { ContractVerifier } from '../deploy/verify/ContractVerifier.js'; -import { IgpFactories, igpFactories } from '../gas/contracts.js'; import { IgpConfig } from '../gas/types.js'; import { EvmIsmModule } from '../ism/EvmIsmModule.js'; +import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js'; import { ArbL2ToL1IsmConfig, IsmType, OpStackIsmConfig } 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 { normalizeConfig } from '../utils/ism.js'; import { EvmHookReader } from './EvmHookReader.js'; @@ -75,6 +75,14 @@ type HookModuleAddresses = { proxyAdmin: Address; }; +class HookDeployer extends HyperlaneDeployer<{}, HookFactories> { + protected cachingEnabled = false; + + deployContracts(_chain: ChainName, _config: {}): Promise { + throw new Error('Method not implemented.'); + } +} + export class EvmHookModule extends HyperlaneModule< ProtocolType.Ethereum, HookConfig, @@ -82,7 +90,9 @@ export class EvmHookModule extends HyperlaneModule< > { protected readonly logger = rootLogger.child({ module: 'EvmHookModule' }); protected readonly reader: EvmHookReader; - protected readonly deployer: EvmModuleDeployer; + // "ISM" Factory has aggregation hook factories too + protected readonly hookFactory: HyperlaneIsmFactory; + protected readonly deployer: HookDeployer; // Adding these to reduce how often we need to grab from MultiProvider. public readonly chain: string; @@ -105,15 +115,11 @@ export class EvmHookModule extends HyperlaneModule< super(params); this.reader = new EvmHookReader(multiProvider, this.args.chain); - this.deployer = new EvmModuleDeployer( + this.hookFactory = HyperlaneIsmFactory.fromAddressesMap( + { [this.args.chain]: params.addresses }, multiProvider, - { - ...hookFactories, - ...igpFactories, - }, - this.logger, - contractVerifier, ); + this.deployer = new HookDeployer(multiProvider, hookFactories); this.chain = this.multiProvider.getChainName(this.args.chain); this.domainId = this.multiProvider.getDomainId(this.chain); @@ -625,11 +631,9 @@ export class EvmHookModule extends HyperlaneModule< switch (config.type) { case HookType.MERKLE_TREE: - return this.deployer.deployContract({ - chain: this.chain, - contractKey: HookType.MERKLE_TREE, - constructorArgs: [this.args.addresses.mailbox], - }); + return this.deployer.deployContract(this.chain, HookType.MERKLE_TREE, [ + this.args.addresses.mailbox, + ]); case HookType.INTERCHAIN_GAS_PAYMASTER: return this.deployIgpHook({ config }); case HookType.AGGREGATION: @@ -657,16 +661,13 @@ export class EvmHookModule extends HyperlaneModule< config: ProtocolFeeHookConfig; }): Promise { this.logger.debug('Deploying ProtocolFeeHook...'); - return this.deployer.deployContract({ - chain: this.chain, - contractKey: HookType.PROTOCOL_FEE, - constructorArgs: [ - config.maxProtocolFee, - config.protocolFee, - config.beneficiary, - config.owner, - ], - }); + const deployer = new HookDeployer(this.multiProvider, hookFactories); + return deployer.deployContract(this.chain, HookType.PROTOCOL_FEE, [ + config.maxProtocolFee, + config.protocolFee, + config.beneficiary, + config.owner, + ]); } protected async deployPausableHook({ @@ -675,11 +676,12 @@ export class EvmHookModule extends HyperlaneModule< config: PausableHookConfig; }): Promise { this.logger.debug('Deploying PausableHook...'); - const hook = await this.deployer.deployContract({ - chain: this.chain, - contractKey: HookType.PAUSABLE, - constructorArgs: [], - }); + const deployer = new HookDeployer(this.multiProvider, hookFactories); + const hook = await deployer.deployContract( + this.chain, + HookType.PAUSABLE, + [], + ); // transfer ownership await this.multiProvider.handleTx( @@ -715,13 +717,12 @@ export class EvmHookModule extends HyperlaneModule< this.args.addresses.staticAggregationHookFactory, signer, ); - const address = await EvmModuleDeployer.deployStaticAddressSet({ - chain: this.chain, + const address = await this.hookFactory.deployStaticAddressSet( + this.chain, factory, - values: aggregatedHooks, - logger: this.logger, - multiProvider: this.multiProvider, - }); + aggregatedHooks, + this.logger, + ); // return aggregation hook return StaticAggregationHook__factory.connect(address, signer); @@ -773,16 +774,12 @@ export class EvmHookModule extends HyperlaneModule< ); // deploy opstack hook - const hook = await this.deployer.deployContract({ - chain, - contractKey: HookType.OP_STACK, - constructorArgs: [ - mailbox, - this.multiProvider.getDomainId(config.destinationChain), - addressToBytes32(opstackIsm.address), - config.nativeBridge, - ], - }); + const hook = await this.deployer.deployContract(chain, HookType.OP_STACK, [ + mailbox, + this.multiProvider.getDomainId(config.destinationChain), + addressToBytes32(opstackIsm.address), + config.nativeBridge, + ]); // set authorized hook on opstack ism const authorizedHook = await opstackIsm.authorizedHook(); @@ -866,17 +863,17 @@ export class EvmHookModule extends HyperlaneModule< ); // deploy arbL1ToL1 hook - const hook = await this.deployer.deployContract({ + const hook = await this.deployer.deployContract( chain, - contractKey: HookType.ARB_L2_TO_L1, - constructorArgs: [ + HookType.ARB_L2_TO_L1, + [ mailbox, this.multiProvider.getDomainId(config.destinationChain), addressToBytes32(arbL2ToL1IsmAddress), config.arbSys, BigNumber.from(200_000), // 2x estimate of executeTransaction call overhead ], - }); + ); // set authorized hook on arbL2ToL1 ism const authorizedHook = await arbL2ToL1Ism.authorizedHook(); if (authorizedHook === addressToBytes32(hook.address)) { @@ -928,22 +925,18 @@ export class EvmHookModule extends HyperlaneModule< // deploy fallback hook const fallbackHook = await this.deploy({ config: config.fallback }); // deploy routing hook with fallback - routingHook = await this.deployer.deployContract({ - chain: this.chain, - contractKey: HookType.FALLBACK_ROUTING, - constructorArgs: [ - this.args.addresses.mailbox, - deployerAddress, - fallbackHook.address, - ], - }); + routingHook = await this.deployer.deployContract( + this.chain, + HookType.FALLBACK_ROUTING, + [this.args.addresses.mailbox, deployerAddress, fallbackHook.address], + ); } else { // deploy routing hook - routingHook = await this.deployer.deployContract({ - chain: this.chain, - contractKey: HookType.ROUTING, - constructorArgs: [this.args.addresses.mailbox, deployerAddress], - }); + routingHook = await this.deployer.deployContract( + this.chain, + HookType.ROUTING, + [this.args.addresses.mailbox, deployerAddress], + ); } // compute the hooks that need to be set @@ -1002,14 +995,14 @@ export class EvmHookModule extends HyperlaneModule< ); // Deploy the InterchainGasPaymaster - const igp = await this.deployer.deployProxiedContract({ - chain: this.chain, - contractKey: HookType.INTERCHAIN_GAS_PAYMASTER, - contractName: HookType.INTERCHAIN_GAS_PAYMASTER, - proxyAdmin: this.args.addresses.proxyAdmin, - constructorArgs: [], - initializeArgs: [deployerAddress, config.beneficiary], - }); + const igp = await this.deployer.deployProxiedContract( + this.chain, + HookType.INTERCHAIN_GAS_PAYMASTER, + HookType.INTERCHAIN_GAS_PAYMASTER, + this.args.addresses.proxyAdmin, + [], + [deployerAddress, config.beneficiary], + ); // Obtain the transactions to set the gas params for each remote const configureTxs = await this.updateIgpRemoteGasParams({ @@ -1038,11 +1031,12 @@ export class EvmHookModule extends HyperlaneModule< config: IgpConfig; }): Promise { // Deploy the StorageGasOracle, by default msg.sender is the owner - const gasOracle = await this.deployer.deployContract({ - chain: this.chain, - contractKey: 'storageGasOracle', - constructorArgs: [], - }); + const gasOracle = await this.deployer.deployContractFromFactory( + this.chain, + new StorageGasOracle__factory(), + 'storageGasOracle', + [], + ); // Obtain the transactions to set the gas params for each remote const configureTxs = await this.updateStorageGasOracle({ diff --git a/typescript/sdk/src/ism/EvmIsmModule.ts b/typescript/sdk/src/ism/EvmIsmModule.ts index 691ae1deb..bba38aa57 100644 --- a/typescript/sdk/src/ism/EvmIsmModule.ts +++ b/typescript/sdk/src/ism/EvmIsmModule.ts @@ -1,63 +1,38 @@ import { ethers } from 'ethers'; import { Logger } from 'pino'; -import { - ArbL2ToL1Ism__factory, - DefaultFallbackRoutingIsm__factory, - DomainRoutingIsm, - DomainRoutingIsmFactory__factory, - DomainRoutingIsm__factory, - IAggregationIsm, - IAggregationIsm__factory, - IInterchainSecurityModule__factory, - IMultisigIsm, - IMultisigIsm__factory, - IRoutingIsm, - OPStackIsm__factory, - Ownable__factory, - PausableIsm__factory, - TestIsm__factory, - TrustedRelayerIsm__factory, -} from '@hyperlane-xyz/core'; +import { DomainRoutingIsm__factory } from '@hyperlane-xyz/core'; import { Address, Domain, ProtocolType, - addBufferToGasLimit, assert, deepEquals, - eqAddress, - objFilter, + intersection, rootLogger, } from '@hyperlane-xyz/utils'; -import { attachAndConnectContracts } from '../contracts/contracts.js'; -import { HyperlaneAddresses, HyperlaneContracts } from '../contracts/types.js'; +import { transferOwnershipTransactions } from '../contracts/contracts.js'; +import { HyperlaneAddresses } from '../contracts/types.js'; import { HyperlaneModule, HyperlaneModuleParams, } from '../core/AbstractHyperlaneModule.js'; -import { EvmModuleDeployer } from '../deploy/EvmModuleDeployer.js'; -import { - ProxyFactoryFactories, - proxyFactoryFactories, -} from '../deploy/contracts.js'; +import { ProxyFactoryFactories } from '../deploy/contracts.js'; import { ContractVerifier } from '../deploy/verify/ContractVerifier.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { AnnotatedEV5Transaction } from '../providers/ProviderType.js'; import { ChainName, ChainNameOrId } from '../types.js'; import { normalizeConfig } from '../utils/ism.js'; -import { findMatchingLogEvents } from '../utils/logUtils.js'; import { EvmIsmReader } from './EvmIsmReader.js'; +import { HyperlaneIsmFactory } from './HyperlaneIsmFactory.js'; import { IsmConfigSchema } from './schemas.js'; import { - AggregationIsmConfig, DeployedIsm, IsmConfig, IsmType, MUTABLE_ISM_TYPE, - MultisigIsmConfig, RoutingIsmConfig, } from './types.js'; import { calculateDomainRoutingDelta } from './utils.js'; @@ -74,8 +49,8 @@ export class EvmIsmModule extends HyperlaneModule< > { protected readonly logger = rootLogger.child({ module: 'EvmIsmModule' }); protected readonly reader: EvmIsmReader; - protected readonly deployer: EvmModuleDeployer; - protected readonly factories: HyperlaneContracts; + protected readonly ismFactory: HyperlaneIsmFactory; + protected readonly mailbox: Address; // Adding these to reduce how often we need to grab from MultiProvider. public readonly chain: ChainName; @@ -95,33 +70,14 @@ export class EvmIsmModule extends HyperlaneModule< super(params); this.reader = new EvmIsmReader(multiProvider, params.chain); - this.deployer = new EvmModuleDeployer( - this.multiProvider, - {}, - this.logger, - contractVerifier, - ); - this.factories = attachAndConnectContracts( - { - staticMerkleRootMultisigIsmFactory: - params.addresses.staticMerkleRootMultisigIsmFactory, - staticMessageIdMultisigIsmFactory: - params.addresses.staticMessageIdMultisigIsmFactory, - staticAggregationIsmFactory: - params.addresses.staticAggregationIsmFactory, - staticAggregationHookFactory: - params.addresses.staticAggregationHookFactory, - domainRoutingIsmFactory: params.addresses.domainRoutingIsmFactory, - staticMerkleRootWeightedMultisigIsmFactory: - params.addresses.staticMerkleRootWeightedMultisigIsmFactory, - staticMessageIdWeightedMultisigIsmFactory: - params.addresses.staticMessageIdWeightedMultisigIsmFactory, - }, - proxyFactoryFactories, - multiProvider.getSigner(params.chain), + this.ismFactory = HyperlaneIsmFactory.fromAddressesMap( + { [params.chain]: params.addresses }, + multiProvider, ); + this.mailbox = params.addresses.mailbox; + this.chain = this.multiProvider.getChainName(this.args.chain); this.domainId = this.multiProvider.getDomainId(this.chain); } @@ -211,24 +167,14 @@ export class EvmIsmModule extends HyperlaneModule< } // Lastly, check if the resolved owner is different from the current owner - const provider = this.multiProvider.getProvider(this.chain); - const owner = await Ownable__factory.connect( - this.args.addresses.deployedIsm, - provider, - ).owner(); - - // Return an ownership transfer transaction if required - if (!eqAddress(targetConfig.owner, owner)) { - updateTxs.push({ - annotation: 'Transferring ownership of ownable ISM...', - chainId: this.domainId, - to: this.args.addresses.deployedIsm, - data: Ownable__factory.createInterface().encodeFunctionData( - 'transferOwnership(address)', - [targetConfig.owner], - ), - }); - } + updateTxs.push( + ...transferOwnershipTransactions( + this.domainId, + this.args.addresses.deployedIsm, + currentConfig, + targetConfig, + ), + ); return updateTxs; } @@ -278,30 +224,24 @@ export class EvmIsmModule extends HyperlaneModule< target: RoutingIsmConfig; logger: Logger; }): Promise { - const routingIsmInterface = DomainRoutingIsm__factory.createInterface(); - const updateTxs = []; - - // filter out domains which are not part of the multiprovider - current = { - ...current, - domains: this.filterRoutingIsmDomains({ - config: current, - }).availableDomains, - }; - target = { - ...target, - domains: this.filterRoutingIsmDomains({ - config: target, - }).availableDomains, - }; + const contract = DomainRoutingIsm__factory.connect( + this.args.addresses.deployedIsm, + this.multiProvider.getProvider(this.chain), + ); + + const updateTxs: AnnotatedEV5Transaction[] = []; + + const knownChains = new Set(this.multiProvider.getKnownChainNames()); const { domainsToEnroll, domainsToUnenroll } = calculateDomainRoutingDelta( current, target, ); + const knownEnrolls = intersection(knownChains, new Set(domainsToEnroll)); + // Enroll domains - for (const origin of domainsToEnroll) { + for (const origin of knownEnrolls) { logger.debug( `Reconfiguring preexisting routing ISM for origin ${origin}...`, ); @@ -310,27 +250,27 @@ export class EvmIsmModule extends HyperlaneModule< }); const domainId = this.multiProvider.getDomainId(origin); + const tx = await contract.populateTransaction.set(domainId, ism.address); updateTxs.push({ annotation: `Setting new ISM for origin ${origin}...`, + ...tx, chainId: this.domainId, - to: this.args.addresses.deployedIsm, - data: routingIsmInterface.encodeFunctionData('set(uint32,address)', [ - domainId, - ism.address, - ]), }); } + const knownUnenrolls = intersection( + knownChains, + new Set(domainsToUnenroll), + ); + // Unenroll domains - for (const origin of domainsToUnenroll) { + for (const origin of knownUnenrolls) { const domainId = this.multiProvider.getDomainId(origin); + const tx = await contract.populateTransaction.remove(domainId); updateTxs.push({ annotation: `Unenrolling originDomain ${domainId} from preexisting routing ISM at ${this.args.addresses.deployedIsm}...`, + ...tx, chainId: this.domainId, - to: this.args.addresses.deployedIsm, - data: routingIsmInterface.encodeFunctionData('remove(uint32)', [ - domainId, - ]), }); } @@ -344,275 +284,10 @@ export class EvmIsmModule extends HyperlaneModule< }): Promise { config = IsmConfigSchema.parse(config); - // If it's an address ISM, just return a base ISM - if (typeof config === 'string') { - // TODO: https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/3773 - // we can remove the ts-ignore once we have a proper type for address ISMs - // @ts-ignore - return IInterchainSecurityModule__factory.connect( - config, - this.multiProvider.getSignerOrProvider(this.args.chain), - ); - } - - const ismType = config.type; - const logger = rootLogger.child({ chainName: this.chain, ismType }); - - logger.debug(`Deploying ${ismType} to ${this.args.chain}`); - - switch (ismType) { - case IsmType.MESSAGE_ID_MULTISIG: - case IsmType.MERKLE_ROOT_MULTISIG: - return this.deployMultisigIsm({ - config, - logger, - }); - - case IsmType.ROUTING: - case IsmType.FALLBACK_ROUTING: - return this.deployRoutingIsm({ - config, - logger, - }); - - case IsmType.AGGREGATION: - return this.deployAggregationIsm({ - config, - logger, - }); - - case IsmType.OP_STACK: - return this.deployer.deployContractFromFactory({ - chain: this.chain, - factory: new OPStackIsm__factory(), - contractName: IsmType.OP_STACK, - constructorArgs: [config.nativeBridge], - }); - - case IsmType.ARB_L2_TO_L1: - return this.deployer.deployContractFromFactory({ - chain: this.chain, - factory: new ArbL2ToL1Ism__factory(), - contractName: IsmType.ARB_L2_TO_L1, - constructorArgs: [config.bridge], - }); - - case IsmType.PAUSABLE: - return this.deployer.deployContractFromFactory({ - chain: this.chain, - factory: new PausableIsm__factory(), - contractName: IsmType.PAUSABLE, - constructorArgs: [config.owner], - }); - - case IsmType.TRUSTED_RELAYER: - assert( - this.args.addresses.mailbox, - `Mailbox address is required for deploying ${ismType}`, - ); - return this.deployer.deployContractFromFactory({ - chain: this.chain, - factory: new TrustedRelayerIsm__factory(), - contractName: IsmType.TRUSTED_RELAYER, - constructorArgs: [this.args.addresses.mailbox, config.relayer], - }); - - case IsmType.TEST_ISM: - return this.deployer.deployContractFromFactory({ - chain: this.chain, - factory: new TestIsm__factory(), - contractName: IsmType.TEST_ISM, - constructorArgs: [], - }); - - default: - throw new Error(`Unsupported ISM type ${ismType}`); - } - } - - protected async deployMultisigIsm({ - config, - logger, - }: { - config: MultisigIsmConfig; - logger: Logger; - }): Promise { - const signer = this.multiProvider.getSigner(this.chain); - const factoryName = - config.type === IsmType.MERKLE_ROOT_MULTISIG - ? 'staticMerkleRootMultisigIsmFactory' - : 'staticMessageIdMultisigIsmFactory'; - - const address = await EvmModuleDeployer.deployStaticAddressSet({ - chain: this.chain, - factory: this.factories[factoryName], - values: config.validators, - logger, - threshold: config.threshold, - multiProvider: this.multiProvider, - }); - - return IMultisigIsm__factory.connect(address, signer); - } - - protected async deployRoutingIsm({ - config, - logger, - }: { - config: RoutingIsmConfig; - logger: Logger; - }): Promise { - // filter out domains which are not part of the multiprovider - const { availableDomains, availableDomainIds } = - this.filterRoutingIsmDomains({ - config, - }); - config = { - ...config, - domains: availableDomains, - }; - - // deploy the submodules first - const submoduleAddresses: Address[] = []; - for (const origin of Object.keys(config.domains)) { - const { address } = await this.deploy({ - config: config.domains[origin], - }); - submoduleAddresses.push(address); - } - - if (config.type === IsmType.FALLBACK_ROUTING) { - // deploy the fallback routing ISM - logger.debug('Deploying fallback routing ISM ...'); - const ism = await this.multiProvider.handleDeploy( - this.chain, - new DefaultFallbackRoutingIsm__factory(), - [this.args.addresses.mailbox], - ); - - // initialize the fallback routing ISM - logger.debug('Initializing fallback routing ISM ...'); - const tx = await ism['initialize(address,uint32[],address[])']( - config.owner, - availableDomainIds, - submoduleAddresses, - this.multiProvider.getTransactionOverrides(this.args.chain), - ); - - await this.multiProvider.handleTx(this.chain, tx); - // return the fallback routing ISM - return ism; - } - - // then deploy the domain routing ISM - logger.debug('Deploying domain routing ISM ...'); - return this.deployDomainRoutingIsm({ - owner: config.owner, - domainIds: availableDomainIds, - submoduleAddresses, - }); - } - - protected async deployDomainRoutingIsm({ - owner, - domainIds, - submoduleAddresses, - }: { - owner: string; - domainIds: number[]; - submoduleAddresses: string[]; - }): Promise { - const overrides = this.multiProvider.getTransactionOverrides( - this.args.chain, - ); - - const signer = this.multiProvider.getSigner(this.args.chain); - const domainRoutingIsmFactory = DomainRoutingIsmFactory__factory.connect( - this.args.addresses.domainRoutingIsmFactory, - signer, - ); - - // estimate gas - const estimatedGas = await domainRoutingIsmFactory.estimateGas.deploy( - owner, - domainIds, - submoduleAddresses, - overrides, - ); - - // deploying new domain routing ISM, add gas buffer - const tx = await domainRoutingIsmFactory.deploy( - owner, - domainIds, - submoduleAddresses, - { - gasLimit: addBufferToGasLimit(estimatedGas), - ...overrides, - }, - ); - - const receipt = await this.multiProvider.handleTx(this.args.chain, tx); - const dispatchLogs = findMatchingLogEvents( - receipt.logs, - domainRoutingIsmFactory.interface, - 'ModuleDeployed', - ); - - if (dispatchLogs.length === 0) { - throw new Error('No ModuleDeployed event found'); - } - - const moduleAddress = dispatchLogs[0].args['module']; - return DomainRoutingIsm__factory.connect(moduleAddress, signer); - } - - protected async deployAggregationIsm({ - config, - logger, - }: { - config: AggregationIsmConfig; - logger: Logger; - }): Promise { - const addresses: Address[] = []; - // Needs to be deployed sequentially because Ethers will throw `Error: replacement fee too low` - for (const module of config.modules) { - const submodule = await this.deploy({ config: module }); - addresses.push(submodule.address); - } - - const factoryName = 'staticAggregationIsmFactory'; - const address = await EvmModuleDeployer.deployStaticAddressSet({ - chain: this.chain, - factory: this.factories[factoryName], - values: addresses, - logger: logger, - threshold: config.threshold, - multiProvider: this.multiProvider, + return this.ismFactory.deploy({ + destination: this.chain, + config, + mailbox: this.mailbox, }); - - const signer = this.multiProvider.getSigner(this.args.chain); - return IAggregationIsm__factory.connect(address, signer); - } - - // filtering out domains which are not part of the multiprovider - private filterRoutingIsmDomains({ config }: { config: RoutingIsmConfig }) { - const availableDomainIds: number[] = []; - const availableDomains = objFilter( - config.domains, - (domain, _): _ is IsmConfig => { - const domainId = this.multiProvider.tryGetDomainId(domain); - if (domainId === null) { - this.logger.warn( - `Domain ${domain} doesn't have chain metadata provided, skipping ...`, - ); - return false; - } - - availableDomainIds.push(domainId); - return true; - }, - ); - - return { availableDomains, availableDomainIds }; } } diff --git a/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts b/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts index 5e7b004a0..894eaa278 100644 --- a/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts +++ b/typescript/sdk/src/ism/HyperlaneIsmFactory.hardhat-test.ts @@ -168,7 +168,6 @@ describe('HyperlaneIsmFactory', async () => { ismFactoryDeployer = new HyperlaneProxyFactoryDeployer(multiProvider); ismFactory = new HyperlaneIsmFactory(contractsMap, multiProvider); - ismFactory.setDeployer(new TestCoreDeployer(multiProvider, ismFactory)); exampleRoutingConfig = { type: IsmType.ROUTING, diff --git a/typescript/sdk/src/ism/HyperlaneIsmFactory.ts b/typescript/sdk/src/ism/HyperlaneIsmFactory.ts index c2f42b8db..645fee8aa 100644 --- a/typescript/sdk/src/ism/HyperlaneIsmFactory.ts +++ b/typescript/sdk/src/ism/HyperlaneIsmFactory.ts @@ -2,6 +2,7 @@ import { ethers } from 'ethers'; import { Logger } from 'pino'; import { + ArbL2ToL1Ism__factory, DefaultFallbackRoutingIsm, DefaultFallbackRoutingIsm__factory, DomainRoutingIsm, @@ -33,7 +34,10 @@ import { import { HyperlaneApp } from '../app/HyperlaneApp.js'; import { appFromAddressesMapHelper } from '../contracts/contracts.js'; -import { HyperlaneAddressesMap } from '../contracts/types.js'; +import { + HyperlaneAddressesMap, + HyperlaneContractsMap, +} from '../contracts/types.js'; import { HyperlaneDeployer } from '../deploy/HyperlaneDeployer.js'; import { ProxyFactoryFactories, @@ -55,15 +59,39 @@ import { } from './types.js'; import { routingModuleDelta } from './utils.js'; +const ismFactories = { + [IsmType.PAUSABLE]: new PausableIsm__factory(), + [IsmType.TRUSTED_RELAYER]: new TrustedRelayerIsm__factory(), + [IsmType.TEST_ISM]: new TestIsm__factory(), + [IsmType.OP_STACK]: new OPStackIsm__factory(), + [IsmType.ARB_L2_TO_L1]: new ArbL2ToL1Ism__factory(), +}; + +class IsmDeployer extends HyperlaneDeployer<{}, typeof ismFactories> { + protected readonly cachingEnabled = false; + + deployContracts(_chain: ChainName, _config: any): Promise { + throw new Error('Method not implemented.'); + } +} + export class HyperlaneIsmFactory extends HyperlaneApp { // The shape of this object is `ChainMap
`, // although `any` is use here because that type breaks a lot of signatures. // TODO: fix this in the next refactoring public deployedIsms: ChainMap = {}; + protected readonly deployer: IsmDeployer; - protected deployer?: HyperlaneDeployer; - setDeployer(deployer: HyperlaneDeployer): void { - this.deployer = deployer; + constructor( + contractsMap: HyperlaneContractsMap, + public readonly multiProvider: MultiProvider, + ) { + super( + contractsMap, + multiProvider, + rootLogger.child({ module: 'ismFactoryApp' }), + ); + this.deployer = new IsmDeployer(multiProvider, ismFactories); } static fromAddressesMap( @@ -75,11 +103,7 @@ export class HyperlaneIsmFactory extends HyperlaneApp { proxyFactoryFactories, multiProvider, ); - return new HyperlaneIsmFactory( - helper.contractsMap, - multiProvider, - rootLogger.child({ module: 'ismFactoryApp' }), - ); + return new HyperlaneIsmFactory(helper.contractsMap, multiProvider); } async deploy(params: { @@ -142,56 +166,39 @@ export class HyperlaneIsmFactory extends HyperlaneApp { }); break; case IsmType.OP_STACK: - assert( - this.deployer, - `HyperlaneDeployer must be set to deploy ${ismType}`, - ); - contract = await this.deployer.deployContractFromFactory( - destination, - new OPStackIsm__factory(), - IsmType.OP_STACK, - [config.nativeBridge], - ); + contract = await this.deployer.deployContract(destination, ismType, [ + config.nativeBridge, + ]); break; case IsmType.PAUSABLE: - assert( - this.deployer, - `HyperlaneDeployer must be set to deploy ${ismType}`, - ); - contract = await this.deployer.deployContractFromFactory( + contract = await this.deployer.deployContract( destination, - new PausableIsm__factory(), IsmType.PAUSABLE, [config.owner], ); - await this.deployer.transferOwnershipOfContracts(destination, config, { - [IsmType.PAUSABLE]: contract, - }); break; case IsmType.TRUSTED_RELAYER: - assert( - this.deployer, - `HyperlaneDeployer must be set to deploy ${ismType}`, - ); assert(mailbox, `Mailbox address is required for deploying ${ismType}`); - contract = await this.deployer.deployContractFromFactory( + contract = await this.deployer.deployContract( destination, - new TrustedRelayerIsm__factory(), IsmType.TRUSTED_RELAYER, [mailbox, config.relayer], ); break; case IsmType.TEST_ISM: - if (!this.deployer) { - throw new Error(`HyperlaneDeployer must be set to deploy ${ismType}`); - } - contract = await this.deployer.deployContractFromFactory( + contract = await this.deployer.deployContract( destination, - new TestIsm__factory(), IsmType.TEST_ISM, [], ); break; + case IsmType.ARB_L2_TO_L1: + contract = await this.deployer.deployContract( + destination, + IsmType.ARB_L2_TO_L1, + [config.bridge], + ); + break; default: throw new Error(`Unsupported ISM type ${ismType}`); } diff --git a/typescript/sdk/src/token/EvmERC20WarpModule.ts b/typescript/sdk/src/token/EvmERC20WarpModule.ts index 19ea85489..6dec4b093 100644 --- a/typescript/sdk/src/token/EvmERC20WarpModule.ts +++ b/typescript/sdk/src/token/EvmERC20WarpModule.ts @@ -15,11 +15,11 @@ import { rootLogger, } from '@hyperlane-xyz/utils'; +import { transferOwnershipTransactions } from '../contracts/contracts.js'; import { HyperlaneModule, HyperlaneModuleParams, } from '../core/AbstractHyperlaneModule.js'; -import { EvmModuleDeployer } from '../deploy/EvmModuleDeployer.js'; import { EvmIsmModule } from '../ism/EvmIsmModule.js'; import { DerivedIsmConfig } from '../ism/EvmIsmReader.js'; import { MultiProvider } from '../providers/MultiProvider.js'; @@ -215,12 +215,13 @@ export class EvmERC20WarpModule extends HyperlaneModule< actualConfig: TokenRouterConfig, expectedConfig: TokenRouterConfig, ): AnnotatedEV5Transaction[] { - return EvmModuleDeployer.createTransferOwnershipTx({ - actualOwner: actualConfig.owner, - expectedOwner: expectedConfig.owner, - deployedAddress: this.args.addresses.deployedTokenRoute, - chainId: this.domainId, - }); + return transferOwnershipTransactions( + this.multiProvider.getDomainId(this.args.chain), + this.args.addresses.deployedTokenRoute, + actualConfig, + expectedConfig, + `${expectedConfig.type} Warp Route`, + ); } /** diff --git a/typescript/utils/src/index.ts b/typescript/utils/src/index.ts index 0c82c6782..26921fa1c 100644 --- a/typescript/utils/src/index.ts +++ b/typescript/utils/src/index.ts @@ -103,10 +103,12 @@ export { parseLegacyMultisigIsmMetadata, } from './multisig.js'; export { + ObjectDiff, ValueOf, arrayToObject, deepCopy, deepEquals, + diffObjMerge, invertKeysAndValues, isObjEmpty, isObject, @@ -120,11 +122,14 @@ export { pick, promiseObjAll, stringifyObject, - diffObjMerge, - ObjectDiff, } from './objects.js'; export { Result, failure, success } from './result.js'; -export { difference, setEquality, symmetricDifference } from './sets.js'; +export { + difference, + intersection, + setEquality, + symmetricDifference, +} from './sets.js'; export { errorToString, fromHexString, diff --git a/typescript/utils/src/sets.ts b/typescript/utils/src/sets.ts index 18149ae37..587c00a62 100644 --- a/typescript/utils/src/sets.ts +++ b/typescript/utils/src/sets.ts @@ -22,3 +22,13 @@ export function symmetricDifference(a: Set, b: Set) { export function setEquality(a: Set, b: Set) { return symmetricDifference(a, b).size === 0; } + +export function intersection(a: Set, b: Set) { + const _intersection = new Set(); + a.forEach((elem) => { + if (b.has(elem)) { + _intersection.add(elem); + } + }); + return _intersection; +} From 39a9b20388ca5ede1805bac460eee2e33ddbb513 Mon Sep 17 00:00:00 2001 From: Tien Dao <15717476+tiendn@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:56:51 +0700 Subject: [PATCH 204/224] test: add more object utils test + remove undefined value when use with invertKeysAndValues fnc (#4764) ### Description Add filter `undefined/null` value when use with utils **invertKeysAndValues** function Add more test at `objects.test.ts` ### Drive-by changes ```diff return Object.fromEntries( Object.entries(data) + .filter(([_, value]) => value !== undefined && value !== null) // Filter out undefined and null values .map(([key, value]) => [value, key]), ); ``` ### Related issues None ### Backward compatibility Currently, nowhere call this **invertKeysAndValues** func ### Testing Yes, more tests. --------- Co-authored-by: J M Rossy --- .changeset/tidy-meals-add.md | 5 ++ typescript/utils/src/objects.test.ts | 130 +++++++++++++++++++++++++++ typescript/utils/src/objects.ts | 4 +- 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 .changeset/tidy-meals-add.md diff --git a/.changeset/tidy-meals-add.md b/.changeset/tidy-meals-add.md new file mode 100644 index 000000000..47b2fee5a --- /dev/null +++ b/.changeset/tidy-meals-add.md @@ -0,0 +1,5 @@ +--- +"@hyperlane-xyz/utils": patch +--- + +Filter undefined/null values in invertKeysAndValues function diff --git a/typescript/utils/src/objects.test.ts b/typescript/utils/src/objects.test.ts index beab06bc3..3318c682e 100644 --- a/typescript/utils/src/objects.test.ts +++ b/typescript/utils/src/objects.test.ts @@ -1,12 +1,24 @@ import { expect } from 'chai'; import { + arrayToObject, deepCopy, deepEquals, + deepFind, diffObjMerge, + invertKeysAndValues, + isObjEmpty, isObject, + objFilter, + objKeys, + objLength, + objMap, + objMapEntries, objMerge, objOmit, + pick, + promiseObjAll, + stringifyObject, } from './objects.js'; describe('Object utilities', () => { @@ -83,6 +95,124 @@ describe('Object utilities', () => { expect(isObject(42)).to.be.false; }); + it('objKeys', () => { + const obj = { a: 1, b: 2 }; + expect(objKeys(obj)).to.eql(['a', 'b']); + }); + + it('objLength', () => { + const obj = { a: 1, b: 2 }; + expect(objLength(obj)).to.equal(2); + }); + + it('isObjEmpty', () => { + expect(isObjEmpty({})).to.be.true; + expect(isObjEmpty({ a: 1 })).to.be.false; + }); + + it('objMapEntries', () => { + const obj = { a: 1, b: 2 }; + const result = objMapEntries(obj, (k, v) => v * 2); + expect(result).to.eql([ + ['a', 2], + ['b', 4], + ]); + }); + + it('objMap', () => { + const obj = { a: 1, b: 2 }; + const result = objMap(obj, (k, v) => v * 2); + expect(result).to.eql({ a: 2, b: 4 }); + }); + + it('objFilter', () => { + const obj = { a: 1, b: 2, c: 3 }; + const result = objFilter(obj, (k: string, v: number): v is number => v > 1); + expect(result).to.eql({ b: 2, c: 3 }); + }); + + it('deepFind should find nested object', () => { + const obj = { a: { b: { c: 3 } } }; + const result = deepFind( + obj, + (v: any): v is { c: number } => v && v.c === 3, + ); + expect(result).to.eql({ c: 3 }); + }); + + it('deepFind should return undefined if object is not found', () => { + const obj = { a: { b: { c: 3 } } }; + const result = deepFind( + obj, + (v: any): v is { c: number } => v && v.c === 4, + ); + expect(result).to.be.undefined; + }); + + it('promiseObjAll', async () => { + const obj = { a: Promise.resolve(1), b: Promise.resolve(2) }; + const result = await promiseObjAll(obj); + expect(result).to.eql({ a: 1, b: 2 }); + }); + + it('pick should return a subset of the object', () => { + const obj = { a: 1, b: 2, c: 3 }; + const result = pick(obj, ['a', 'c']); + expect(result).to.eql({ a: 1, c: 3 }); + }); + + it('pick should return an empty object if no keys are provided', () => { + const obj = { a: 1, b: 2, c: 3 }; + const result = pick(obj, []); + expect(result).to.eql({}); + }); + + it("pick should return an empty object if the object doesn't contain the keys", () => { + const obj = { c: 4, d: 5 }; + const result = pick(obj as any, ['a', 'b']); + expect(result).to.eql({}); + }); + + describe('invertKeysAndValues', () => { + it('invertKeysAndValues should invert the keys and values', () => { + const obj = { a: '1', b: '2' }; + const result = invertKeysAndValues(obj); + expect(result).to.eql({ '1': 'a', '2': 'b' }); + }); + + it('invertKeysAndValues should return an empty object if the object is empty', () => { + const obj = {}; + const result = invertKeysAndValues(obj); + expect(result).to.eql({}); + }); + + it('invertKeysAndValues should return an object if the object has duplicate values', () => { + const obj = { a: '1', b: '1' }; + const result = invertKeysAndValues(obj); + expect(result).to.eql({ '1': 'b' }); + }); + + it('invertKeysAndValues should return an object if the object has undefined/null values', () => { + const obj = { a: '1', b: '2', c: undefined, d: null, e: 0 }; + const result = invertKeysAndValues(obj); + expect(result).to.eql({ '1': 'a', '2': 'b', '0': 'e' }); + }); + }); + + it('arrayToObject', () => { + const keys = ['a', 'b']; + const result = arrayToObject(keys); + expect(result).to.eql({ a: true, b: true }); + }); + + it('stringifyObject', () => { + const obj = { a: 1, b: 2 }; + const jsonResult = stringifyObject(obj, 'json'); + expect(jsonResult).to.equal('{"a":1,"b":2}'); + const yamlResult = stringifyObject(obj, 'yaml'); + expect(yamlResult).to.include('a: 1\nb: 2'); + }); + describe('diffObjMerge', () => { it('should merge objects with equal values', () => { const actual = { a: 1, b: 2 }; diff --git a/typescript/utils/src/objects.ts b/typescript/utils/src/objects.ts index 1917cbff6..0c021587f 100644 --- a/typescript/utils/src/objects.ts +++ b/typescript/utils/src/objects.ts @@ -192,7 +192,9 @@ export function objOmit = any>( export function invertKeysAndValues(data: any) { return Object.fromEntries( - Object.entries(data).map(([key, value]) => [value, key]), + Object.entries(data) + .filter(([_, value]) => value !== undefined && value !== null) // Filter out undefined and null values + .map(([key, value]) => [value, key]), ); } From a028e1624380e4011c71078a4bb704604cda1b84 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:04:54 +0000 Subject: [PATCH 205/224] chore: migrate away from unmaintained rust toolchain installer (#4465) chore: migrate away from unmaintained rust toolchain installer - previous toolchain action was archived almost a year ago https://github.com/actions-rs/toolchain - new action has 1k+ stars and sensible defaults https://github.com/dtolnay/rust-toolchain - uses minimal profile by default - `stable` toolchain by default Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- .github/workflows/agent-release-artifacts.yml | 4 +--- .github/workflows/rust.yml | 9 ++------- .github/workflows/test.yml | 5 +---- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/.github/workflows/agent-release-artifacts.yml b/.github/workflows/agent-release-artifacts.yml index b2a190f7e..ee27483c8 100644 --- a/.github/workflows/agent-release-artifacts.yml +++ b/.github/workflows/agent-release-artifacts.yml @@ -58,10 +58,8 @@ jobs: linker = "aarch64-linux-gnu-gcc" EOF - name: setup rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - toolchain: stable - profile: minimal target: ${{ matrix.TARGET }} - name: setup target run: rustup target add ${{ matrix.TARGET }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 18b856bc4..c0431b4e9 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -35,10 +35,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal + - uses: dtolnay/rust-toolchain@stable - name: rust cache uses: Swatinem/rust-cache@v2 with: @@ -68,10 +65,8 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@stable with: - toolchain: stable - profile: minimal components: rustfmt, clippy target: wasm32-unknown-unknown - name: rust cache diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bfbb3c8f6..92d203446 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -187,10 +187,7 @@ jobs: uses: foundry-rs/foundry-toolchain@v1 - name: setup rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal + uses: dtolnay/rust-toolchain@stable - name: rust cache uses: Swatinem/rust-cache@v2 From 956ff752ab89ca56718240c2b332a7ae4d5b1259 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:27:18 +0000 Subject: [PATCH 206/224] feat: ergonomic IGP configuration in CLI (#4635) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Re-adding the ability to generate IGP hook configs using the CLI, but repurposing logic found in infra to make the configuration experience more ergonomic. Logic still behind the `--advanced` flag. > Enabling this allows IGP configuration in any place that supports hook config e.g. `core`/`warp`/`hook` init with `--advanced`. We will use metadata in registry to: 1. fetch price from Coingecko (prompt user if unable to find) 1. fetch current gas prices via the default RPCs 1. request user to enter an IGP margin in % 1. Calculate the `gasPrice` + `tokenExchangeRate` for you Note that it still sets `overhead` to some preexisting default. ```sh ? Select hook type interchainGasPaymaster Creating interchainGasPaymaster... ? Detected owner address as 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 from signer, is this correct? yes ? Use this same address for the beneficiary? yes ? Select network type Mainnet ? Select local chain for IGP hook bitlayer ? Select remote destination chains for IGP hook alephzero, ancient8 ? Enter overhead for alephzero (e.g., 75000) for IGP hook 75000 ? Enter overhead for ancient8 (e.g., 75000) for IGP hook 75000 Getting gas token prices for all chains from Coingecko... Gas price for alephzero is 40.0 Gas token price for alephzero is $0.393347 Gas price for ancient8 is 0.001000252 Gas token price for ancient8 is $2356.71 Gas price for bitlayer is 0.050000007 Gas token price for bitlayer is $60576 ? Enter IGP margin percentage (e.g. 10 for 10%) 100 Created interchainGasPaymaster! ``` ```sh Core config is valid, writing to file ./configs/core-config.yaml: owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" defaultIsm: type: trustedRelayerIsm relayer: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" defaultHook: type: aggregationHook hooks: - type: merkleTreeHook - owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" type: interchainGasPaymaster beneficiary: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" oracleKey: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" overhead: alephzero: 75000 ancient8: 75000 oracleConfig: alephzero: gasPrice: "40000000000" tokenExchangeRate: "129868" ancient8: gasPrice: "1000253" tokenExchangeRate: "778100236" requiredHook: owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" type: protocolFee beneficiary: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" maxProtocolFee: "1000000000000000000" protocolFee: "0" ✅ Successfully created new core deployment config. ``` ### Drive-by changes Moving reusable infra logic into the SDK, and refactoring CLI+Infra to reuse the underlying logic. For example: - fetching token prices from coingecko - fetching gas prices using a chain's RPC ### Related issues Most recently, https://github.com/hyperlane-xyz/hyperlane-registry/pull/236#issuecomment-2383956859. But there have been numerous occasions where it would be nice for users to be self-sufficient in configuring and deploying an IGP hook for their PI deployments/relayer. ### Backward compatibility yes ### Testing - creating igp config with `hyperlane core init --advanced` - making sure infra print-token-prices.ts still works - making sure infra print-gas-prices.ts still works --- .changeset/sixty-eggs-smoke.md | 5 + .changeset/thin-tips-explain.md | 5 + typescript/cli/src/config/hooks.ts | 231 ++++++++++++---- typescript/cli/src/utils/chains.ts | 12 +- .../infra/config/environments/mainnet3/igp.ts | 22 +- .../config/environments/test/gas-oracle.ts | 2 +- .../infra/config/environments/testnet4/igp.ts | 21 +- .../scripts/agents/update-agent-config.ts | 4 +- typescript/infra/scripts/print-gas-prices.ts | 14 +- typescript/infra/src/config/gas-oracle.ts | 115 +------- typescript/sdk/src/gas/utils.ts | 251 ++++++++++++++++++ typescript/sdk/src/index.ts | 10 + 12 files changed, 516 insertions(+), 176 deletions(-) create mode 100644 .changeset/sixty-eggs-smoke.md create mode 100644 .changeset/thin-tips-explain.md create mode 100644 typescript/sdk/src/gas/utils.ts diff --git a/.changeset/sixty-eggs-smoke.md b/.changeset/sixty-eggs-smoke.md new file mode 100644 index 000000000..24906d7c6 --- /dev/null +++ b/.changeset/sixty-eggs-smoke.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +Enable configuration of IGP hooks in the CLI diff --git a/.changeset/thin-tips-explain.md b/.changeset/thin-tips-explain.md new file mode 100644 index 000000000..330e57a8a --- /dev/null +++ b/.changeset/thin-tips-explain.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Introduce utils that can be reused by the CLI and Infra for fetching token prices from Coingecko and gas prices from EVM/Cosmos chains. diff --git a/typescript/cli/src/config/hooks.ts b/typescript/cli/src/config/hooks.ts index a075d6655..0bfd8cb1f 100644 --- a/typescript/cli/src/config/hooks.ts +++ b/typescript/cli/src/config/hooks.ts @@ -4,22 +4,33 @@ import { ethers } from 'ethers'; import { z } from 'zod'; import { + ChainGasOracleParams, ChainMap, + ChainMetadata, ChainName, HookConfig, HookConfigSchema, HookType, + IgpHookConfig, + MultiProtocolProvider, + getCoingeckoTokenPrices, + getGasPrice, + getLocalStorageGasOracleConfig, } from '@hyperlane-xyz/sdk'; import { Address, normalizeAddressEvm, + objFilter, objMap, toWei, } from '@hyperlane-xyz/utils'; import { CommandContext } from '../context/types.js'; import { errorRed, logBlue, logGreen, logRed } from '../logger.js'; -import { runMultiChainSelectionStep } from '../utils/chains.js'; +import { + runMultiChainSelectionStep, + runSingleChainSelectionStep, +} from '../utils/chains.js'; import { readYamlOrJson } from '../utils/files.js'; import { detectAndConfirmOrPrompt, inputWithInfo } from '../utils/input.js'; @@ -96,6 +107,11 @@ export async function createHookConfig({ name: HookType.PROTOCOL_FEE, description: 'Charge fees for each message dispatch from this chain', }, + { + value: HookType.INTERCHAIN_GAS_PAYMASTER, + name: HookType.INTERCHAIN_GAS_PAYMASTER, + description: 'Pay for gas on remote chains', + }, ], pageSize: 10, }); @@ -107,6 +123,8 @@ export async function createHookConfig({ return createMerkleTreeConfig(); case HookType.PROTOCOL_FEE: return createProtocolFeeConfig(context, advanced); + case HookType.INTERCHAIN_GAS_PAYMASTER: + return createIGPConfig(context, advanced); default: throw new Error(`Invalid hook type: ${hookType}`); } @@ -124,30 +142,13 @@ export const createProtocolFeeConfig = callWithConfigCreationLogs( context: CommandContext, advanced: boolean = false, ): Promise => { - const unnormalizedOwner = - !advanced && context.signer - ? await context.signer.getAddress() - : await detectAndConfirmOrPrompt( - async () => context.signer?.getAddress(), - 'For protocol fee hook, enter', - 'owner address', - 'signer', - ); - const owner = normalizeAddressEvm(unnormalizedOwner); - let beneficiary = owner; - - const isBeneficiarySameAsOwner = advanced - ? await confirm({ - message: `Use this same address (${owner}) for the beneficiary?`, - }) - : true; - - if (!isBeneficiarySameAsOwner) { - const unnormalizedBeneficiary = await input({ - message: 'Enter beneficiary address for protocol fee hook:', - }); - beneficiary = normalizeAddressEvm(unnormalizedBeneficiary); - } + // Get owner and beneficiary + const { owner, beneficiary } = await getOwnerAndBeneficiary( + 'Protocol Fee Hook', + context, + advanced, + ); + // TODO: input in gwei, wei, etc const maxProtocolFee = advanced ? toWei( @@ -182,51 +183,167 @@ export const createProtocolFeeConfig = callWithConfigCreationLogs( HookType.PROTOCOL_FEE, ); -// TODO: make this usable export const createIGPConfig = callWithConfigCreationLogs( - async (remotes: ChainName[]): Promise => { - const unnormalizedOwner = await input({ - message: 'Enter owner address for IGP hook', - }); - const owner = normalizeAddressEvm(unnormalizedOwner); - let beneficiary = owner; - let oracleKey = owner; + async ( + context: CommandContext, + advanced: boolean = false, + ): Promise => { + // Get owner and beneficiary + const { owner, beneficiary } = await getOwnerAndBeneficiary( + 'Interchain Gas Paymaster', + context, + advanced, + ); + + // Determine local and remote chains + const { localChain, remoteChains } = await selectIgpChains(context); + + // Get overhead, defaulting to 75000 + const overhead = await getIgpOverheads(remoteChains); + + // Only get prices for local and remote chains + const filteredMetadata = objFilter( + context.chainMetadata, + (_, metadata): metadata is ChainMetadata => + remoteChains.includes(metadata.name) || metadata.name === localChain, + ); + const prices = await getIgpTokenPrices(context, filteredMetadata); + + // Get exchange rate margin percentage, defaulting to 10 + const exchangeRateMarginPct = parseInt( + await input({ + message: `Enter IGP margin percentage (e.g. 10 for 10%)`, + default: '10', + }), + 10, + ); - const beneficiarySameAsOwner = await confirm({ - message: 'Use this same address for the beneficiary and gasOracleKey?', + // Calculate storage gas oracle config + const oracleConfig = getLocalStorageGasOracleConfig({ + local: localChain, + gasOracleParams: prices, + exchangeRateMarginPct, }); - if (!beneficiarySameAsOwner) { - const unnormalizedBeneficiary = await input({ - message: 'Enter beneficiary address for IGP hook', - }); - beneficiary = normalizeAddressEvm(unnormalizedBeneficiary); - const unnormalizedOracleKey = await input({ - message: 'Enter gasOracleKey address for IGP hook', - }); - oracleKey = normalizeAddressEvm(unnormalizedOracleKey); - } - const overheads: ChainMap = {}; - for (const chain of remotes) { - const overhead = parseInt( - await input({ - message: `Enter overhead for ${chain} (eg 75000) for IGP hook`, - }), - ); - overheads[chain] = overhead; - } return { type: HookType.INTERCHAIN_GAS_PAYMASTER, beneficiary, owner, - oracleKey, - overhead: overheads, - oracleConfig: {}, + oracleKey: owner, + overhead, + oracleConfig, }; }, HookType.INTERCHAIN_GAS_PAYMASTER, ); +async function getOwnerAndBeneficiary( + module: string, + context: CommandContext, + advanced: boolean, +) { + const unnormalizedOwner = + !advanced && context.signer + ? await context.signer.getAddress() + : await detectAndConfirmOrPrompt( + async () => context.signer?.getAddress(), + `For ${module}, enter`, + 'owner address', + 'signer', + ); + const owner = normalizeAddressEvm(unnormalizedOwner); + + let beneficiary = owner; + const beneficiarySameAsOwner = await confirm({ + message: `Use this same address (${owner}) for the beneficiary?`, + }); + if (!beneficiarySameAsOwner) { + const unnormalizedBeneficiary = await input({ + message: `Enter beneficiary address for ${module}`, + }); + beneficiary = normalizeAddressEvm(unnormalizedBeneficiary); + } + + return { owner, beneficiary }; +} + +async function selectIgpChains(context: CommandContext) { + const localChain = await runSingleChainSelectionStep( + context.chainMetadata, + 'Select local chain for IGP hook', + ); + const isTestnet = context.chainMetadata[localChain].isTestnet; + const remoteChains = await runMultiChainSelectionStep({ + chainMetadata: objFilter( + context.chainMetadata, + (_, metadata): metadata is ChainMetadata => metadata.name !== localChain, + ), + message: 'Select remote destination chains for IGP hook', + requireNumber: 1, + networkType: isTestnet ? 'testnet' : 'mainnet', + }); + + return { localChain, remoteChains }; +} + +async function getIgpOverheads(remoteChains: ChainName[]) { + const overhead: ChainMap = {}; + for (const chain of remoteChains) { + overhead[chain] = parseInt( + await input({ + message: `Enter overhead for ${chain} (e.g., 75000) for IGP hook`, + default: '75000', + }), + ); + } + return overhead; +} + +async function getIgpTokenPrices( + context: CommandContext, + filteredMetadata: ChainMap, +) { + const isTestnet = + context.chainMetadata[Object.keys(filteredMetadata)[0]].isTestnet; + const fetchedPrices = isTestnet + ? objMap(filteredMetadata, () => '10') + : await getCoingeckoTokenPrices(filteredMetadata); + + logBlue( + isTestnet + ? `Hardcoding all gas token prices to 10 USD for testnet...` + : `Getting gas token prices for all chains from Coingecko...`, + ); + + const mpp = new MultiProtocolProvider(context.chainMetadata); + const prices: ChainMap = {}; + + for (const chain of Object.keys(filteredMetadata)) { + const gasPrice = await getGasPrice(mpp, chain); + logBlue(`Gas price for ${chain} is ${gasPrice.amount}`); + + let tokenPrice = fetchedPrices[chain]; + if (!tokenPrice) { + tokenPrice = await input({ + message: `Enter the price of ${chain}'s token in USD`, + }); + } else { + logBlue(`Gas token price for ${chain} is $${tokenPrice}`); + } + + const decimals = context.chainMetadata[chain].nativeToken?.decimals; + if (!decimals) { + throw new Error(`No decimals found in metadata for ${chain}`); + } + prices[chain] = { + gasPrice, + nativeToken: { price: tokenPrice, decimals }, + }; + } + + return prices; +} + export const createAggregationConfig = callWithConfigCreationLogs( async ( context: CommandContext, diff --git a/typescript/cli/src/utils/chains.ts b/typescript/cli/src/utils/chains.ts index 09975aca3..f5fb2b341 100644 --- a/typescript/cli/src/utils/chains.ts +++ b/typescript/cli/src/utils/chains.ts @@ -58,6 +58,13 @@ type RunMultiChainSelectionStepOptions = { * @default false */ requiresConfirmation?: boolean; + + /** + * The network type to filter the chains by + * + * @default undefined + */ + networkType?: 'mainnet' | 'testnet'; }; export async function runMultiChainSelectionStep({ @@ -65,11 +72,12 @@ export async function runMultiChainSelectionStep({ message = 'Select chains', requireNumber = 0, requiresConfirmation = false, + networkType = undefined, }: RunMultiChainSelectionStepOptions) { - const networkType = await selectNetworkType(); + const selectedNetworkType = networkType ?? (await selectNetworkType()); const { choices, networkTypeSeparator } = getChainChoices( chainMetadata, - networkType, + selectedNetworkType, ); let currentChoiceSelection = new Set(); diff --git a/typescript/infra/config/environments/mainnet3/igp.ts b/typescript/infra/config/environments/mainnet3/igp.ts index 6b0d8fbbc..fa4ab8e91 100644 --- a/typescript/infra/config/environments/mainnet3/igp.ts +++ b/typescript/infra/config/environments/mainnet3/igp.ts @@ -1,12 +1,19 @@ -import { ChainMap, ChainName, HookType, IgpConfig } from '@hyperlane-xyz/sdk'; +import { + ChainMap, + ChainName, + HookType, + IgpConfig, + getTokenExchangeRateFromValues, +} from '@hyperlane-xyz/sdk'; import { exclude, objMap } from '@hyperlane-xyz/utils'; import { AllStorageGasOracleConfigs, + EXCHANGE_RATE_MARGIN_PCT, getAllStorageGasOracleConfigs, getOverhead, - getTokenExchangeRateFromValues, } from '../../../src/config/gas-oracle.js'; +import { mustGetChainNativeToken } from '../../../src/utils/utils.js'; import { ethereumChainNames } from './chains.js'; import gasPrices from './gasPrices.json'; @@ -29,7 +36,16 @@ const storageGasOracleConfig: AllStorageGasOracleConfigs = supportedChainNames, gasPrices, (local, remote) => - getTokenExchangeRateFromValues(local, remote, tokenPrices), + getTokenExchangeRateFromValues({ + local, + remote, + tokenPrices, + exchangeRateMarginPct: EXCHANGE_RATE_MARGIN_PCT, + decimals: { + local: mustGetChainNativeToken(local).decimals, + remote: mustGetChainNativeToken(remote).decimals, + }, + }), (local) => parseFloat(tokenPrices[local]), (local, remote) => getOverheadWithOverrides(local, remote), ); diff --git a/typescript/infra/config/environments/test/gas-oracle.ts b/typescript/infra/config/environments/test/gas-oracle.ts index cacf8f3a3..65c09d9cd 100644 --- a/typescript/infra/config/environments/test/gas-oracle.ts +++ b/typescript/infra/config/environments/test/gas-oracle.ts @@ -3,12 +3,12 @@ import { BigNumber, ethers } from 'ethers'; import { ChainMap, ChainName, + GasPriceConfig, TOKEN_EXCHANGE_RATE_DECIMALS, } from '@hyperlane-xyz/sdk'; import { AllStorageGasOracleConfigs, - GasPriceConfig, getAllStorageGasOracleConfigs, } from '../../../src/config/gas-oracle.js'; diff --git a/typescript/infra/config/environments/testnet4/igp.ts b/typescript/infra/config/environments/testnet4/igp.ts index 302d6aeb7..0cabe5b69 100644 --- a/typescript/infra/config/environments/testnet4/igp.ts +++ b/typescript/infra/config/environments/testnet4/igp.ts @@ -1,12 +1,18 @@ -import { ChainMap, HookType, IgpConfig } from '@hyperlane-xyz/sdk'; +import { + ChainMap, + HookType, + IgpConfig, + getTokenExchangeRateFromValues, +} from '@hyperlane-xyz/sdk'; import { Address, exclude, objMap } from '@hyperlane-xyz/utils'; import { AllStorageGasOracleConfigs, + EXCHANGE_RATE_MARGIN_PCT, getAllStorageGasOracleConfigs, getOverhead, - getTokenExchangeRateFromValues, } from '../../../src/config/gas-oracle.js'; +import { mustGetChainNativeToken } from '../../../src/utils/utils.js'; import { ethereumChainNames } from './chains.js'; import gasPrices from './gasPrices.json'; @@ -21,7 +27,16 @@ export const storageGasOracleConfig: AllStorageGasOracleConfigs = supportedChainNames, gasPrices, (local, remote) => - getTokenExchangeRateFromValues(local, remote, tokenPrices), + getTokenExchangeRateFromValues({ + local, + remote, + tokenPrices, + exchangeRateMarginPct: EXCHANGE_RATE_MARGIN_PCT, + decimals: { + local: mustGetChainNativeToken(local).decimals, + remote: mustGetChainNativeToken(remote).decimals, + }, + }), ); export const igp: ChainMap = objMap( diff --git a/typescript/infra/scripts/agents/update-agent-config.ts b/typescript/infra/scripts/agents/update-agent-config.ts index de01a2cff..7044bc436 100644 --- a/typescript/infra/scripts/agents/update-agent-config.ts +++ b/typescript/infra/scripts/agents/update-agent-config.ts @@ -12,6 +12,7 @@ import { HyperlaneDeploymentArtifacts, MultiProvider, buildAgentConfig, + getCosmosChainGasPrice, } from '@hyperlane-xyz/sdk'; import { ProtocolType, @@ -26,7 +27,6 @@ import { DeployEnvironment, envNameToAgentEnv, } from '../../src/config/environment.js'; -import { getCosmosChainGasPrice } from '../../src/config/gas-oracle.js'; import { chainIsProtocol, filterRemoteDomainMetadata, @@ -125,7 +125,7 @@ export async function writeAgentConfig( .map(async (chain) => [ chain, { - gasPrice: await getCosmosChainGasPrice(chain), + gasPrice: await getCosmosChainGasPrice(chain, multiProvider), }, ]), ), diff --git a/typescript/infra/scripts/print-gas-prices.ts b/typescript/infra/scripts/print-gas-prices.ts index bbe15c7b1..39eca69ee 100644 --- a/typescript/infra/scripts/print-gas-prices.ts +++ b/typescript/infra/scripts/print-gas-prices.ts @@ -1,7 +1,12 @@ import { Provider } from '@ethersproject/providers'; import { ethers } from 'ethers'; -import { ChainMap, MultiProtocolProvider } from '@hyperlane-xyz/sdk'; +import { + ChainMap, + GasPriceConfig, + MultiProtocolProvider, + getCosmosChainGasPrice, +} from '@hyperlane-xyz/sdk'; import { ProtocolType } from '@hyperlane-xyz/utils'; // Intentionally circumvent `mainnet3/index.ts` and `getEnvironmentConfig('mainnet3')` @@ -12,10 +17,6 @@ import { supportedChainNames as mainnet3SupportedChainNames } from '../config/en import { getRegistry as getTestnet4Registry } from '../config/environments/testnet4/chains.js'; import testnet4GasPrices from '../config/environments/testnet4/gasPrices.json' assert { type: 'json' }; import { supportedChainNames as testnet4SupportedChainNames } from '../config/environments/testnet4/supportedChainNames.js'; -import { - GasPriceConfig, - getCosmosChainGasPrice, -} from '../src/config/gas-oracle.js'; import { getArgs } from './agent-utils.js'; @@ -69,8 +70,7 @@ async function getGasPrice( }; } case ProtocolType.Cosmos: { - const { amount } = await getCosmosChainGasPrice(chain); - + const { amount } = await getCosmosChainGasPrice(chain, mpp); return { amount, decimals: 1, diff --git a/typescript/infra/src/config/gas-oracle.ts b/typescript/infra/src/config/gas-oracle.ts index ac3516d10..c040ff45b 100644 --- a/typescript/infra/src/config/gas-oracle.ts +++ b/typescript/infra/src/config/gas-oracle.ts @@ -2,56 +2,37 @@ import chalk from 'chalk'; import { BigNumber, ethers } from 'ethers'; import { - AgentCosmosGasPrice, ChainMap, ChainName, - StorageGasOracleConfig as DestinationOracleConfig, - TOKEN_EXCHANGE_RATE_DECIMALS, + GasPriceConfig, + StorageGasOracleConfig, TOKEN_EXCHANGE_RATE_SCALE, defaultMultisigConfigs, - getCosmosRegistryChain, multisigIsmVerificationCost, } from '@hyperlane-xyz/sdk'; -import { ProtocolType, convertDecimals } from '@hyperlane-xyz/utils'; -import { getChain } from '../../config/registry.js'; -import { - isEthereumProtocolChain, - mustGetChainNativeToken, -} from '../utils/utils.js'; - -// Gas data to configure on a single local chain. Includes DestinationOracleConfig -// for each remote chain. -export type StorageGasOracleConfig = ChainMap; - -// StorageGasOracleConfigs for each local chain -export type AllStorageGasOracleConfigs = ChainMap; +import { isEthereumProtocolChain } from '../utils/utils.js'; -// A configuration for a gas price. -// Some chains, e.g. Neutron, have gas prices that are -// not integers and and are still quoted in the "wei" version -// of the token. Therefore it's possible for the amount to be a -// float (e.g. "0.0053") and for decimals to be 1. This is why -// we intentionally don't deal with BigNumber here. -export interface GasPriceConfig { - amount: string; - decimals: number; -} +// gas oracle configs for each chain, which includes +// a map for each chain's remote chains +export type AllStorageGasOracleConfigs = ChainMap< + ChainMap +>; // Overcharge by 50% to account for market making risk -const EXCHANGE_RATE_MARGIN_PCT = 50; +export const EXCHANGE_RATE_MARGIN_PCT = 50; -// Gets the StorageGasOracleConfig for a particular local chain. +// Gets the StorageGasOracleConfig for each remote chain for a particular local chain. // Accommodates small non-integer gas prices by scaling up the gas price // and scaling down the exchange rate by the same factor. -function getLocalStorageGasOracleConfig( +function getLocalStorageGasOracleConfigOverride( local: ChainName, remotes: ChainName[], gasPrices: ChainMap, getTokenExchangeRate: (local: ChainName, remote: ChainName) => BigNumber, getTokenUsdPrice?: (chain: ChainName) => number, getOverhead?: (local: ChainName, remote: ChainName) => number, -): StorageGasOracleConfig { +): ChainMap { return remotes.reduce((agg, remote) => { let exchangeRate = getTokenExchangeRate(local, remote); if (!gasPrices[remote]) { @@ -203,7 +184,7 @@ export function getOverhead( : FOREIGN_DEFAULT_OVERHEAD; // non-ethereum overhead } -// Gets the StorageGasOracleConfig for each local chain +// Gets the map of remote gas oracle configs for each local chain export function getAllStorageGasOracleConfigs( chainNames: ChainName[], gasPrices: ChainMap, @@ -215,7 +196,7 @@ export function getAllStorageGasOracleConfigs( const remotes = chainNames.filter((chain) => local !== chain); return { ...agg, - [local]: getLocalStorageGasOracleConfig( + [local]: getLocalStorageGasOracleConfigOverride( local, remotes, gasPrices, @@ -226,71 +207,3 @@ export function getAllStorageGasOracleConfigs( }; }, {}) as AllStorageGasOracleConfigs; } - -// Gets the exchange rate of the remote quoted in local tokens -export function getTokenExchangeRateFromValues( - local: ChainName, - remote: ChainName, - tokenPrices: ChainMap, -): BigNumber { - // Workaround for chicken-egg dependency problem. - // We need to provide some default value here to satisfy the config on initial load, - // whilst knowing that it will get overwritten when a script actually gets run. - // We set default token price to 1 to mitigate underflow/overflow errors that occurred - // on some pairings if the exchange rate itself was set to 1. - const defaultValue = '1'; - const localValue = ethers.utils.parseUnits( - tokenPrices[local] ?? defaultValue, - TOKEN_EXCHANGE_RATE_DECIMALS, - ); - const remoteValue = ethers.utils.parseUnits( - tokenPrices[remote] ?? defaultValue, - TOKEN_EXCHANGE_RATE_DECIMALS, - ); - - // This does not yet account for decimals! - let exchangeRate = remoteValue.mul(TOKEN_EXCHANGE_RATE_SCALE).div(localValue); - // Apply the premium - exchangeRate = exchangeRate.mul(100 + EXCHANGE_RATE_MARGIN_PCT).div(100); - - return BigNumber.from( - convertDecimals( - mustGetChainNativeToken(remote).decimals, - mustGetChainNativeToken(local).decimals, - exchangeRate.toString(), - ), - ); -} - -// Gets the gas price for a Cosmos chain -export async function getCosmosChainGasPrice( - chain: ChainName, -): Promise { - const metadata = getChain(chain); - if (!metadata) { - throw new Error(`No metadata found for Cosmos chain ${chain}`); - } - if (metadata.protocol !== ProtocolType.Cosmos) { - throw new Error(`Chain ${chain} is not a Cosmos chain`); - } - - const cosmosRegistryChain = await getCosmosRegistryChain(chain); - - const nativeToken = mustGetChainNativeToken(chain); - - const fee = cosmosRegistryChain.fees?.fee_tokens.find( - (fee: { denom: string }) => { - return ( - fee.denom === nativeToken.denom || fee.denom === `u${nativeToken.denom}` - ); - }, - ); - if (!fee || fee.average_gas_price === undefined) { - throw new Error(`No gas price found for Cosmos chain ${chain}`); - } - - return { - denom: fee.denom, - amount: fee.average_gas_price.toString(), - }; -} diff --git a/typescript/sdk/src/gas/utils.ts b/typescript/sdk/src/gas/utils.ts new file mode 100644 index 000000000..3a658d9b6 --- /dev/null +++ b/typescript/sdk/src/gas/utils.ts @@ -0,0 +1,251 @@ +import { Provider } from '@ethersproject/providers'; +import { BigNumber, ethers } from 'ethers'; + +import { ProtocolType, convertDecimals, objMap } from '@hyperlane-xyz/utils'; + +import { + TOKEN_EXCHANGE_RATE_DECIMALS, + TOKEN_EXCHANGE_RATE_SCALE, +} from '../consts/igp.js'; +import { ChainMetadataManager } from '../metadata/ChainMetadataManager.js'; +import { AgentCosmosGasPrice } from '../metadata/agentConfig.js'; +import { ChainMetadata } from '../metadata/chainMetadataTypes.js'; +import { MultiProtocolProvider } from '../providers/MultiProtocolProvider.js'; +import { ChainMap, ChainName } from '../types.js'; +import { getCosmosRegistryChain } from '../utils/cosmos.js'; + +import { StorageGasOracleConfig } from './oracle/types.js'; + +export interface GasPriceConfig { + amount: string; + decimals: number; +} + +export interface NativeTokenPriceConfig { + price: string; + decimals: number; +} + +export interface ChainGasOracleParams { + gasPrice: GasPriceConfig; + nativeToken: NativeTokenPriceConfig; +} + +export async function getGasPrice( + mpp: MultiProtocolProvider, + chain: string, +): Promise { + const protocolType = mpp.getProtocol(chain); + switch (protocolType) { + case ProtocolType.Ethereum: { + const provider = mpp.getProvider(chain); + const gasPrice = await (provider.provider as Provider).getGasPrice(); + return { + amount: ethers.utils.formatUnits(gasPrice, 'gwei'), + decimals: 9, + }; + } + case ProtocolType.Cosmos: { + const { amount } = await getCosmosChainGasPrice(chain, mpp); + return { + amount, + decimals: 1, + }; + } + case ProtocolType.Sealevel: + // TODO get a reasonable value + return { + amount: '0.001', + decimals: 9, + }; + default: + throw new Error(`Unsupported protocol type: ${protocolType}`); + } +} + +// Gets the gas price for a Cosmos chain +export async function getCosmosChainGasPrice( + chain: ChainName, + chainMetadataManager: ChainMetadataManager, +): Promise { + const metadata = chainMetadataManager.getChainMetadata(chain); + if (!metadata) { + throw new Error(`No metadata found for Cosmos chain ${chain}`); + } + if (metadata.protocol !== ProtocolType.Cosmos) { + throw new Error(`Chain ${chain} is not a Cosmos chain`); + } + + const cosmosRegistryChain = await getCosmosRegistryChain(chain); + const nativeToken = metadata.nativeToken; + if (!nativeToken) { + throw new Error(`No native token found for Cosmos chain ${chain}`); + } + if (!nativeToken.denom) { + throw new Error(`No denom found for native token on Cosmos chain ${chain}`); + } + + const fee = cosmosRegistryChain.fees?.fee_tokens.find( + (fee: { denom: string }) => { + return ( + fee.denom === nativeToken.denom || fee.denom === `u${nativeToken.denom}` + ); + }, + ); + if (!fee || fee.average_gas_price === undefined) { + throw new Error(`No gas price found for Cosmos chain ${chain}`); + } + + return { + denom: fee.denom, + amount: fee.average_gas_price.toString(), + }; +} + +// Gets the exchange rate of the remote quoted in local tokens +export function getTokenExchangeRateFromValues({ + local, + remote, + tokenPrices, + exchangeRateMarginPct, + decimals, +}: { + local: ChainName; + remote: ChainName; + tokenPrices: ChainMap; + exchangeRateMarginPct: number; + decimals: { local: number; remote: number }; +}): BigNumber { + // Workaround for chicken-egg dependency problem. + // We need to provide some default value here to satisfy the config on initial load, + // whilst knowing that it will get overwritten when a script actually gets run. + const defaultValue = '1'; + const localValue = ethers.utils.parseUnits( + tokenPrices[local] ?? defaultValue, + TOKEN_EXCHANGE_RATE_DECIMALS, + ); + const remoteValue = ethers.utils.parseUnits( + tokenPrices[remote] ?? defaultValue, + TOKEN_EXCHANGE_RATE_DECIMALS, + ); + + // This does not yet account for decimals! + let exchangeRate = remoteValue.mul(TOKEN_EXCHANGE_RATE_SCALE).div(localValue); + // Apply the premium + exchangeRate = exchangeRate.mul(100 + exchangeRateMarginPct).div(100); + + return BigNumber.from( + convertDecimals(decimals.remote, decimals.local, exchangeRate.toString()), + ); +} + +// Gets the StorageGasOracleConfig for each remote chain for a particular local chain. +// Accommodates small non-integer gas prices by scaling up the gas price +// and scaling down the exchange rate by the same factor. +export function getLocalStorageGasOracleConfig({ + local, + gasOracleParams, + exchangeRateMarginPct, +}: { + local: ChainName; + gasOracleParams: ChainMap; + exchangeRateMarginPct: number; +}): ChainMap { + const remotes = Object.keys(gasOracleParams).filter( + (remote) => remote !== local, + ); + const tokenPrices: ChainMap = objMap( + gasOracleParams, + (chain) => gasOracleParams[chain].nativeToken.price, + ); + const localDecimals = gasOracleParams[local].nativeToken.decimals; + return remotes.reduce((agg, remote) => { + const remoteDecimals = gasOracleParams[remote].nativeToken.decimals; + let exchangeRate = getTokenExchangeRateFromValues({ + local, + remote, + tokenPrices, + exchangeRateMarginPct, + decimals: { local: localDecimals, remote: remoteDecimals }, + }); + + // First parse as a number, so we have floating point precision. + // Recall it's possible to have gas prices that are not integers, even + // after converting to the "wei" version of the token. + let gasPrice = + parseFloat(gasOracleParams[remote].gasPrice.amount) * + Math.pow(10, gasOracleParams[remote].gasPrice.decimals); + if (isNaN(gasPrice)) { + throw new Error( + `Invalid gas price for chain ${remote}: ${gasOracleParams[remote].gasPrice.amount}`, + ); + } + + // We have very little precision and ultimately need an integer value for + // the gas price that will be set on-chain. We scale up the gas price and + // scale down the exchange rate by the same factor. + if (gasPrice < 10 && gasPrice % 1 !== 0) { + // Scale up the gas price by 1e4 + const gasPriceScalingFactor = 1e4; + + // Check that there's no significant underflow when applying + // this to the exchange rate: + const adjustedExchangeRate = exchangeRate.div(gasPriceScalingFactor); + const recoveredExchangeRate = adjustedExchangeRate.mul( + gasPriceScalingFactor, + ); + if (recoveredExchangeRate.mul(100).div(exchangeRate).lt(99)) { + throw new Error('Too much underflow when downscaling exchange rate'); + } + + // Apply the scaling factor + exchangeRate = adjustedExchangeRate; + gasPrice *= gasPriceScalingFactor; + } + + // Our integer gas price. + const gasPriceBn = BigNumber.from(Math.ceil(gasPrice)); + + return { + ...agg, + [remote]: { + tokenExchangeRate: exchangeRate.toString(), + gasPrice: gasPriceBn.toString(), + }, + }; + }, {} as ChainMap); +} + +const COINGECKO_PRICE_API = 'https://api.coingecko.com/api/v3/simple/price'; + +export async function getCoingeckoTokenPrices( + chainMetadata: ChainMap, + currency = 'usd', +): Promise> { + const ids = objMap( + chainMetadata, + (_, metadata) => metadata.gasCurrencyCoinGeckoId ?? metadata.name, + ); + + const resp = await fetch( + `${COINGECKO_PRICE_API}?ids=${Object.entries(ids).join( + ',', + )}&vs_currencies=${currency}`, + ); + + const idPrices = await resp.json(); + + const prices = objMap(ids, (chain, id) => { + const idData = idPrices[id]; + if (!idData) { + return undefined; + } + const price = idData[currency]; + if (!price) { + return undefined; + } + return price.toString(); + }); + + return prices; +} diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index e9bd31bb4..5ab4630b9 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -539,3 +539,13 @@ export { export { EvmIsmModule } from './ism/EvmIsmModule.js'; export { AnnotatedEV5Transaction } from './providers/ProviderType.js'; export { EvmERC20WarpModule } from './token/EvmERC20WarpModule.js'; +export { + GasPriceConfig, + NativeTokenPriceConfig, + ChainGasOracleParams, + getCoingeckoTokenPrices, + getCosmosChainGasPrice, + getGasPrice, + getLocalStorageGasOracleConfig, + getTokenExchangeRateFromValues, +} from './gas/utils.js'; From f9919c447e02e460595a16ddf3f01518c7b4df21 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 28 Oct 2024 14:38:15 -0400 Subject: [PATCH 207/224] feat: add lumia warp route to infra (#4705) ### Description - Add lumia warp route to infra config --- .../getEthereumBscLumiaLUMIAWarpConfig.ts | 41 +++++++++++++++++++ .../environments/mainnet3/warp/warpIds.ts | 1 + typescript/infra/config/warp.ts | 2 + 3 files changed, 44 insertions(+) create mode 100644 typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumBscLumiaLUMIAWarpConfig.ts diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumBscLumiaLUMIAWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumBscLumiaLUMIAWarpConfig.ts new file mode 100644 index 000000000..d063f9a8f --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getEthereumBscLumiaLUMIAWarpConfig.ts @@ -0,0 +1,41 @@ +import { + ChainMap, + RouterConfig, + TokenRouterConfig, + TokenType, +} from '@hyperlane-xyz/sdk'; +import { objMap } from '@hyperlane-xyz/utils'; + +// Lumia Team +const owner = '0x8bBA07Ddc72455b55530C17e6f6223EF6E156863'; + +export const getEthereumBscLUMIAWarpConfig = async ( + routerConfig: ChainMap, +): Promise> => { + const ethereum = { + type: TokenType.collateral, + token: '0xD9343a049D5DBd89CD19DC6BcA8c48fB3a0a42a7', + }; + + const bsc = { + type: TokenType.synthetic, + }; + + const lumia = { + type: TokenType.native, + }; + + const configMap = { + ethereum, + bsc, + lumia, + }; + + const merged = objMap(configMap, (chain, config) => ({ + ...routerConfig[chain], + ...config, + owner, + })); + + return merged as ChainMap; +}; diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index a90601c35..35adc72c6 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -17,6 +17,7 @@ export enum WarpRouteIds { EthereumVictionUSDC = 'USDC/ethereum-viction', EthereumVictionUSDT = 'USDT/ethereum-viction', EthereumZircuitPZETH = 'PZETH/ethereum-zircuit', + EthereumBscLumiaLUMIA = 'LUMIA/bsc-ethereum-lumia', InevmInjectiveINJ = 'INJ/inevm-injective', MantapacificNeutronTIA = 'TIA/mantapacific-neutron', } diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 84086342e..4e1246ec5 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -14,6 +14,7 @@ import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/ import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js'; import { getEclipseStrideTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.js'; import { getEclipseStrideStTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.js'; +import { getEthereumBscLUMIAWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumBscLumiaLUMIAWarpConfig.js'; import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js'; import { getEthereumInevmUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDTWarpConfig.js'; import { getEthereumSeiFastUSDWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumSeiFastUSDWarpConfig.js'; @@ -51,6 +52,7 @@ export const warpConfigGetterMap: Record< [WarpRouteIds.EthereumVictionUSDC]: getEthereumVictionUSDCWarpConfig, [WarpRouteIds.EthereumVictionUSDT]: getEthereumVictionUSDTWarpConfig, [WarpRouteIds.EthereumZircuitPZETH]: getRenzoPZETHWarpConfig, + [WarpRouteIds.EthereumBscLumiaLUMIA]: getEthereumBscLUMIAWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, [WarpRouteIds.EclipseStrideTIA]: getEclipseStrideTiaWarpConfig, [WarpRouteIds.EclipseStrideSTTIA]: getEclipseStrideStTiaWarpConfig, From 56328e6e1301c64dc5f483179a173bf5026e8a81 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Mon, 28 Oct 2024 17:07:09 -0400 Subject: [PATCH 208/224] fix: use `ism.route(message)` for supporting self relay of ICA ISM (#4772) ### Description ICA ISM does not implement `module(uint32)` but rather `route(message)`. This modifies ISM derivation with message context to use this function. ### Related issues ### Backward compatibility Yes ### Testing Manual --- .changeset/sweet-houses-type.md | 5 +++++ typescript/sdk/src/ism/EvmIsmReader.ts | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .changeset/sweet-houses-type.md diff --git a/.changeset/sweet-houses-type.md b/.changeset/sweet-houses-type.md new file mode 100644 index 000000000..27fa3feeb --- /dev/null +++ b/.changeset/sweet-houses-type.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': patch +--- + +Fix ICA ISM self relay diff --git a/typescript/sdk/src/ism/EvmIsmReader.ts b/typescript/sdk/src/ism/EvmIsmReader.ts index 47e58d2b7..06493cb45 100644 --- a/typescript/sdk/src/ism/EvmIsmReader.ts +++ b/typescript/sdk/src/ism/EvmIsmReader.ts @@ -148,7 +148,9 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader { ); return; } - const module = await ism.module(domainId); + const module = this.messageContext + ? await ism.route(this.messageContext.message) + : await ism.module(domainId); domains[chainName] = await this.deriveIsmConfig(module); }); From cd3bc5cd37083e121957f9bf9928d51a0f64d2bc Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:51:00 +0000 Subject: [PATCH 209/224] chore: disable arcadiatestnet until redeployment (#4775) ### Description chore: disable arcadiatestnet until redeployment - testnet had to be reset ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --------- Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com> --- typescript/infra/config/environments/testnet4/agent.ts | 6 +++--- .../environments/testnet4/aw-validators/hyperlane.json | 3 --- typescript/infra/config/environments/testnet4/funding.ts | 2 +- .../config/environments/testnet4/supportedChainNames.ts | 3 ++- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index 18b4b7690..17db9d2ff 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -43,7 +43,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< [Role.Validator]: { alfajores: true, arbitrumsepolia: true, - arcadiatestnet: true, + // arcadiatestnet: true, basesepolia: true, berabartio: true, bsctestnet: true, @@ -73,7 +73,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< [Role.Relayer]: { alfajores: true, arbitrumsepolia: true, - arcadiatestnet: true, + // arcadiatestnet: true, basesepolia: true, berabartio: true, bsctestnet: true, @@ -103,7 +103,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< [Role.Scraper]: { alfajores: true, arbitrumsepolia: true, - arcadiatestnet: true, + // arcadiatestnet: true, basesepolia: true, berabartio: true, bsctestnet: true, diff --git a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json index ce4a9509f..2bc9d9762 100644 --- a/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/testnet4/aw-validators/hyperlane.json @@ -9,9 +9,6 @@ "arbitrumsepolia": { "validators": ["0x09fabfbca0b8bf042e2a1161ee5010d147b0f603"] }, - "arcadiatestnet": { - "validators": ["0x7ce5973d3f22971546efb86f5a0417c1248e92f5"] - }, "basesepolia": { "validators": ["0x82e3b437a2944e3ff00258c93e72cd1ba5e0e921"] }, diff --git a/typescript/infra/config/environments/testnet4/funding.ts b/typescript/infra/config/environments/testnet4/funding.ts index 938dd880f..e022357a9 100644 --- a/typescript/infra/config/environments/testnet4/funding.ts +++ b/typescript/infra/config/environments/testnet4/funding.ts @@ -28,7 +28,7 @@ export const keyFunderConfig: KeyFunderConfig< desiredBalancePerChain: { alfajores: '5', arbitrumsepolia: '0.1', - arcadiatestnet: '0.1', + // arcadiatestnet: '0.1', basesepolia: '0.1', berabartio: '0.1', bsctestnet: '5', diff --git a/typescript/infra/config/environments/testnet4/supportedChainNames.ts b/typescript/infra/config/environments/testnet4/supportedChainNames.ts index 3643ff89a..7bd9c5b56 100644 --- a/typescript/infra/config/environments/testnet4/supportedChainNames.ts +++ b/typescript/infra/config/environments/testnet4/supportedChainNames.ts @@ -2,7 +2,8 @@ export const testnet4SupportedChainNames = [ 'alfajores', 'arbitrumsepolia', - 'arcadiatestnet', + // Disabling arcadiatestnet on Oct 29, 2024: chain reset and needs to be redeployed + // 'arcadiatestnet', 'basesepolia', 'berabartio', 'bsctestnet', From 0640f837ce5df887b45a5f476be0c8f4585fa250 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Tue, 29 Oct 2024 16:22:36 +0530 Subject: [PATCH 210/224] fix(contracts): InterchainAccountRouter minor audit remediation (#4581) ### Description - disabled the ICARouter's ability to change hook given that the user doesn't expect the hook to change after they deploy their ICA account. Hook is not part of the derivation like ism on the destination chain and hence, cannot be configured custom by the user. ### Drive-by changes - MailboxClient events for hook and ism setting - ProtocolFee events for setting beneficiary and owner ### Related issues - partly fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/14 ### Backward compatibility No ### Testing Unit tests --- .changeset/silent-berries-attend.md | 5 ++ solidity/contracts/client/MailboxClient.sol | 21 ++++- solidity/contracts/hooks/ProtocolFee.sol | 5 ++ .../middleware/InterchainAccountRouter.sol | 34 ++++++-- .../contracts/test/TestPostDispatchHook.sol | 9 +- solidity/test/InterchainAccountRouter.t.sol | 86 ++++++++++++++++++- solidity/test/hooks/ProtocolFee.t.sol | 10 +++ 7 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 .changeset/silent-berries-attend.md diff --git a/.changeset/silent-berries-attend.md b/.changeset/silent-berries-attend.md new file mode 100644 index 000000000..2b6b43e5f --- /dev/null +++ b/.changeset/silent-berries-attend.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': minor +--- + +disabled the ICARouter's ability to change hook given that the user doesn't expect the hook to change after they deploy their ICA account. Hook is not part of the derivation like ism on the destination chain and hence, cannot be configured custom by the user. diff --git a/solidity/contracts/client/MailboxClient.sol b/solidity/contracts/client/MailboxClient.sol index 41ad7f055..9c986a0cc 100644 --- a/solidity/contracts/client/MailboxClient.sol +++ b/solidity/contracts/client/MailboxClient.sol @@ -1,6 +1,18 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + // ============ Internal Imports ============ import {IMailbox} from "../interfaces/IMailbox.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; @@ -15,6 +27,9 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own abstract contract MailboxClient is OwnableUpgradeable, PackageVersioned { using Message for bytes; + event HookSet(address _hook); + event IsmSet(address _ism); + IMailbox public immutable mailbox; uint32 public immutable localDomain; @@ -63,8 +78,11 @@ abstract contract MailboxClient is OwnableUpgradeable, PackageVersioned { * @notice Sets the address of the application's custom hook. * @param _hook The address of the hook contract. */ - function setHook(address _hook) public onlyContractOrNull(_hook) onlyOwner { + function setHook( + address _hook + ) public virtual onlyContractOrNull(_hook) onlyOwner { hook = IPostDispatchHook(_hook); + emit HookSet(_hook); } /** @@ -75,6 +93,7 @@ abstract contract MailboxClient is OwnableUpgradeable, PackageVersioned { address _module ) public onlyContractOrNull(_module) onlyOwner { interchainSecurityModule = IInterchainSecurityModule(_module); + emit IsmSet(_module); } // ======== Initializer ========= diff --git a/solidity/contracts/hooks/ProtocolFee.sol b/solidity/contracts/hooks/ProtocolFee.sol index 4e1f47048..b530b0d83 100644 --- a/solidity/contracts/hooks/ProtocolFee.sol +++ b/solidity/contracts/hooks/ProtocolFee.sol @@ -32,6 +32,9 @@ contract ProtocolFee is AbstractPostDispatchHook, Ownable { using Address for address payable; using Message for bytes; + event ProtocolFeeSet(uint256 protocolFee); + event BeneficiarySet(address beneficiary); + // ============ Constants ============ /// @notice The maximum protocol fee that can be set. @@ -126,6 +129,7 @@ contract ProtocolFee is AbstractPostDispatchHook, Ownable { "ProtocolFee: exceeds max protocol fee" ); protocolFee = _protocolFee; + emit ProtocolFeeSet(_protocolFee); } /** @@ -135,5 +139,6 @@ contract ProtocolFee is AbstractPostDispatchHook, Ownable { function _setBeneficiary(address _beneficiary) internal { require(_beneficiary != address(0), "ProtocolFee: invalid beneficiary"); beneficiary = _beneficiary; + emit BeneficiarySet(_beneficiary); } } diff --git a/solidity/contracts/middleware/InterchainAccountRouter.sol b/solidity/contracts/middleware/InterchainAccountRouter.sol index 3980ac29b..aa583f341 100644 --- a/solidity/contracts/middleware/InterchainAccountRouter.sol +++ b/solidity/contracts/middleware/InterchainAccountRouter.sol @@ -22,6 +22,7 @@ import {TypeCasts} from "../libs/TypeCasts.sol"; import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol"; import {EnumerableMapExtended} from "../libs/EnumerableMapExtended.sol"; import {Router} from "../client/Router.sol"; +import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; // ============ External Imports ============ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; @@ -160,6 +161,12 @@ contract InterchainAccountRouter is Router { } } + function setHook( + address _hook + ) public override onlyContractOrNull(_hook) onlyOwner { + hook = IPostDispatchHook(_hook); + } + // ============ External Functions ============ /** * @notice Dispatches a single remote call to be made by an owner's @@ -600,7 +607,14 @@ contract InterchainAccountRouter is Router { ) private returns (bytes32) { require(_router != bytes32(0), "no router specified for destination"); emit RemoteCallDispatched(_destination, msg.sender, _router, _ism); - return mailbox.dispatch{value: msg.value}(_destination, _router, _body); + return + mailbox.dispatch{value: msg.value}( + _destination, + _router, + _body, + new bytes(0), + hook + ); } /** @@ -625,7 +639,8 @@ contract InterchainAccountRouter is Router { _destination, _router, _body, - _hookMetadata + _hookMetadata, + hook ); } @@ -665,7 +680,13 @@ contract InterchainAccountRouter is Router { function quoteGasPayment( uint32 _destination ) external view returns (uint256 _gasPayment) { - return _quoteDispatch(_destination, ""); + return + _Router_quoteDispatch( + _destination, + new bytes(0), + new bytes(0), + address(hook) + ); } /** @@ -679,13 +700,12 @@ contract InterchainAccountRouter is Router { bytes calldata _messageBody, uint256 gasLimit ) external view returns (uint256 _gasPayment) { - bytes32 _router = _mustHaveRemoteRouter(_destination); return - mailbox.quoteDispatch( + _Router_quoteDispatch( _destination, - _router, _messageBody, - StandardHookMetadata.overrideGasLimit(gasLimit) + StandardHookMetadata.overrideGasLimit(gasLimit), + address(hook) ); } } diff --git a/solidity/contracts/test/TestPostDispatchHook.sol b/solidity/contracts/test/TestPostDispatchHook.sol index 34763b89c..84c84f379 100644 --- a/solidity/contracts/test/TestPostDispatchHook.sol +++ b/solidity/contracts/test/TestPostDispatchHook.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; + import {Message} from "../libs/Message.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; @@ -35,15 +36,15 @@ contract TestPostDispatchHook is AbstractPostDispatchHook { // ============ Internal functions ============ function _postDispatch( - bytes calldata /*metadata*/, - bytes calldata message + bytes calldata, + /*metadata*/ bytes calldata message ) internal override { messageDispatched[message.id()] = true; } function _quoteDispatch( - bytes calldata /*metadata*/, - bytes calldata /*message*/ + bytes calldata, + /*metadata*/ bytes calldata /*message*/ ) internal view override returns (uint256) { return fee; } diff --git a/solidity/test/InterchainAccountRouter.t.sol b/solidity/test/InterchainAccountRouter.t.sol index d091bfe26..65d804caa 100644 --- a/solidity/test/InterchainAccountRouter.t.sol +++ b/solidity/test/InterchainAccountRouter.t.sol @@ -13,6 +13,8 @@ import {TestInterchainGasPaymaster} from "../contracts/test/TestInterchainGasPay import {IPostDispatchHook} from "../contracts/interfaces/hooks/IPostDispatchHook.sol"; import {CallLib, OwnableMulticall, InterchainAccountRouter} from "../contracts/middleware/InterchainAccountRouter.sol"; import {InterchainAccountIsm} from "../contracts/isms/routing/InterchainAccountIsm.sol"; +import {AbstractPostDispatchHook} from "../contracts/hooks/libs/AbstractPostDispatchHook.sol"; +import {TestPostDispatchHook} from "../contracts/test/TestPostDispatchHook.sol"; contract Callable { mapping(address => bytes32) public data; @@ -108,10 +110,11 @@ contract InterchainAccountRouterTestBase is Test { address owner = address(this); originIcaRouter = deployProxiedIcaRouter( environment.mailboxes(origin), - environment.igps(destination), + environment.igps(origin), icaIsm, owner ); + destinationIcaRouter = deployProxiedIcaRouter( environment.mailboxes(destination), environment.igps(destination), @@ -392,6 +395,25 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { ); } + function test_quoteDispatch_differentHook() public { + // arrange + TestPostDispatchHook testHook = new TestPostDispatchHook(); + originIcaRouter = deployProxiedIcaRouter( + environment.mailboxes(origin), + testHook, + icaIsm, + address(this) + ); + originIcaRouter.enrollRemoteRouterAndIsm( + destination, + routerOverride, + ismOverride + ); + + // assert + assertEq(originIcaRouter.quoteGasPayment(destination), 0); + } + function testFuzz_singleCallRemoteWithDefault( bytes32 data, uint256 value @@ -444,6 +466,35 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { assertIgpPayment(balanceBefore, balanceAfter, igp.getDefaultGasUsage()); } + function testFuzz_callRemoteWithDefault_differentHook( + bytes32 data, + uint256 value + ) public { + // arrange + TestPostDispatchHook testHook = new TestPostDispatchHook(); + originIcaRouter = deployProxiedIcaRouter( + environment.mailboxes(origin), + testHook, + icaIsm, + address(this) + ); + originIcaRouter.enrollRemoteRouterAndIsm( + destination, + routerOverride, + ismOverride + ); + + // assert + vm.expectCall( + address(testHook), + 0, + abi.encodePacked(AbstractPostDispatchHook.postDispatch.selector) + ); + + // act + originIcaRouter.callRemote(destination, getCalls(data, value)); + } + function testFuzz_overrideAndCallRemote( bytes32 data, uint256 value @@ -558,6 +609,7 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { uint256 balanceAfter = address(this).balance; assertRemoteCallReceived(data, value); assertIgpPayment(balanceBefore, balanceAfter, igp.getDefaultGasUsage()); + assertEq(address(originIcaRouter.hook()), address(0)); } function testFuzz_callRemoteWithOverrides_metadata( @@ -591,6 +643,38 @@ contract InterchainAccountRouterTest is InterchainAccountRouterTestBase { assertIgpPayment(balanceBefore, balanceAfter, gasLimit); } + function testFuzz_callRemoteWithOverrides_withHook( + bytes32 data, + uint256 value + ) public { + TestPostDispatchHook testHook = new TestPostDispatchHook(); + + originIcaRouter = deployProxiedIcaRouter( + environment.mailboxes(origin), + testHook, + icaIsm, + address(this) + ); + originIcaRouter.enrollRemoteRouterAndIsm( + destination, + routerOverride, + ismOverride + ); + + vm.expectCall( + address(testHook), + 0, + abi.encodePacked(AbstractPostDispatchHook.postDispatch.selector) + ); + originIcaRouter.callRemoteWithOverrides( + destination, + routerOverride, + ismOverride, + getCalls(data, value), + new bytes(0) + ); + } + function testFuzz_callRemoteWithFailingIsmOverride( bytes32 data, uint256 value diff --git a/solidity/test/hooks/ProtocolFee.t.sol b/solidity/test/hooks/ProtocolFee.t.sol index df0d3471c..bfd90f687 100644 --- a/solidity/test/hooks/ProtocolFee.t.sol +++ b/solidity/test/hooks/ProtocolFee.t.sol @@ -42,6 +42,9 @@ contract ProtocolFeeTest is Test { function testSetProtocolFee(uint256 fee) public { fee = bound(fee, 0, fees.MAX_PROTOCOL_FEE()); + + vm.expectEmit(true, true, true, true); + emit ProtocolFee.ProtocolFeeSet(fee); fees.setProtocolFee(fee); assertEq(fees.protocolFee(), fee); } @@ -69,6 +72,13 @@ contract ProtocolFeeTest is Test { assertEq(fees.protocolFee(), FEE); } + function testSetBeneficiary(address beneficiary) public { + vm.expectEmit(true, true, true, true); + emit ProtocolFee.BeneficiarySet(beneficiary); + fees.setBeneficiary(beneficiary); + assertEq(fees.beneficiary(), beneficiary); + } + function testSetBeneficiary_revertWhen_notOwner() public { vm.prank(charlie); From d9505ab585637c8e7d2e31ee234fa968156f4c70 Mon Sep 17 00:00:00 2001 From: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Date: Tue, 29 Oct 2024 11:21:43 +0000 Subject: [PATCH 211/224] feat: oct 25 deployment batch (#4766) ### Description - feat: oct 25 deployment batch - apechain, arbitrumnova, b3, fantom, gravity, harmony, kaia, morph, orderly, snaxchain - deployed as normal - zeronetwork, zksync - deployed from special zksync branch containing txfusion's changes + latest `main` pulled in - https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4761 ### Drive-by changes - igp updates ### Related issues n/a ### Backward compatibility yes ### Testing manual using local CLI from this branch, no tx fusion changes required for hyperlane send or self-relay to work --- .changeset/fresh-pigs-work.md | 5 + .registryrc | 2 +- rust/main/config/mainnet_config.json | 785 +++++++++++++++- .../config/environments/mainnet3/agent.ts | 42 +- .../mainnet3/aw-validators/hyperlane.json | 36 + .../mainnet3/core/verification.json | 888 ++++++++++++++++++ .../config/environments/mainnet3/funding.ts | 14 +- .../environments/mainnet3/gasPrices.json | 100 +- .../mainnet3/ism/verification.json | 860 +++++++++++++++++ .../middleware/accounts/verification.json | 210 +++++ .../mainnet3/supportedChainNames.ts | 12 + .../environments/mainnet3/tokenPrices.json | 152 +-- .../environments/mainnet3/validators.ts | 122 +++ typescript/infra/scripts/deploy.ts | 4 + typescript/sdk/src/consts/multisigIsm.ts | 60 ++ typescript/sdk/src/core/HyperlaneCore.ts | 8 +- 16 files changed, 3196 insertions(+), 104 deletions(-) create mode 100644 .changeset/fresh-pigs-work.md diff --git a/.changeset/fresh-pigs-work.md b/.changeset/fresh-pigs-work.md new file mode 100644 index 000000000..a43a7e339 --- /dev/null +++ b/.changeset/fresh-pigs-work.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Deploy to apechain, arbitrumnova, b3, fantom, gravity, harmony, kaia, morph, orderly, snaxchain, zeronetwork, zksync. Update default metadata in `HyperlaneCore` to `0x00001` to ensure empty metadata does not break on zksync. diff --git a/.registryrc b/.registryrc index 265b47093..e1877ed1f 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -18666269e99ad8d2ba45579c4be783478e50e936 +302be4817c063629cec70c0b02322b250df71122 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index fee83dfbd..b0404fee4 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -3081,7 +3081,7 @@ "proxyAdmin": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", "rpcUrls": [ { - "http": "https://raas-backend.alchemy.com/rpc/worldchain-mainnet/rollup" + "http": "https://worldchain-mainnet.g.alchemy.com/public" } ], "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", @@ -4843,6 +4843,789 @@ "from": 9152000, "chunk": 5 } + }, + "apechain": { + "blockExplorers": [ + { + "apiUrl": "https://apechain.calderaexplorer.xyz/api", + "family": "blockscout", + "name": "ApeChain Explorer", + "url": "https://apechain.calderaexplorer.xyz" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 0.2, + "reorgPeriod": 5 + }, + "chainId": 33139, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "ApeChain", + "domainId": 33139, + "gasCurrencyCoinGeckoId": "apecoin", + "index": { + "from": 1759561 + }, + "name": "apechain", + "nativeToken": { + "decimals": 18, + "name": "ApeCoin", + "symbol": "APE" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.apechain.com/http" + } + ], + "technicalStack": "arbitrumnitro", + "aggregationHook": "0x9C16FBa8b0c8a356E0f4398f524ae73Fd5a677B6", + "domainRoutingIsm": "0xDEed16fe4b1c9b2a93483EDFf34C77A9b57D31Ff", + "domainRoutingIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "fallbackRoutingHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "interchainAccountIsm": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "interchainAccountRouter": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47", + "interchainGasPaymaster": "0x18B0688990720103dB63559a3563f7E8d0f63EDb", + "interchainSecurityModule": "0x9FF3f38DED52D74EF4b666A7A09BcB5F38d6D272", + "mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", + "merkleTreeHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "pausableHook": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "pausableIsm": "0x5090dF2FBDa7127c7aDa41f60B79F5c55D380Dd8", + "protocolFee": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", + "proxyAdmin": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "staticAggregationHookFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticAggregationIsm": "0x9FF3f38DED52D74EF4b666A7A09BcB5F38d6D272", + "staticAggregationIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticMerkleRootMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticMessageIdMultisigIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMessageIdWeightedMultisigIsmFactory": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "storageGasOracle": "0xF1854214392864c628A16930E73B699f7a51b3EE", + "testRecipient": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96" + }, + "arbitrumnova": { + "blockExplorers": [ + { + "apiUrl": "https://api-nova.arbiscan.io/api", + "family": "etherscan", + "name": "Arbiscan Nova", + "url": "https://nova.arbiscan.io/" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 5 + }, + "chainId": 42170, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Arbitrum Nova", + "domainId": 42170, + "gasCurrencyCoinGeckoId": "ethereum", + "index": { + "from": 78794208 + }, + "name": "arbitrumnova", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://nova.arbitrum.io/rpc" + } + ], + "technicalStack": "arbitrumnitro", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53" + }, + "b3": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.b3.fun/api", + "family": "blockscout", + "name": "B3 Explorer", + "url": "https://explorer.b3.fun" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 5 + }, + "chainId": 8333, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "B3", + "domainId": 8333, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "b3", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet-rpc.b3.fun" + } + ], + "technicalStack": "opstack", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "index": { + "from": 7504261 + } + }, + "fantom": { + "blockExplorers": [ + { + "apiUrl": "https://api.ftmscan.com/api", + "family": "etherscan", + "name": "FTMScan", + "url": "https://ftmscan.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 5 + }, + "chainId": 250, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Fantom Opera", + "domainId": 250, + "gasCurrencyCoinGeckoId": "fantom", + "name": "fantom", + "nativeToken": { + "decimals": 18, + "name": "Fantom", + "symbol": "FTM" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpcapi.fantom.network" + }, + { + "http": "https://fantom-rpc.publicnode.com" + }, + { + "http": "https://fantom-pokt.nodies.app" + }, + { + "http": "https://rpc.fantom.network" + }, + { + "http": "https://rpc2.fantom.network" + }, + { + "http": "https://rpc3.fantom.network" + } + ], + "technicalStack": "other", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "index": { + "from": 95635171 + } + }, + "gravity": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.gravity.xyz/api", + "family": "blockscout", + "name": "Gravity Alpha Explorer", + "url": "https://explorer.gravity.xyz" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 5 + }, + "chainId": 1625, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Gravity Alpha Mainnet", + "domainId": 1625, + "gasCurrencyCoinGeckoId": "g-token", + "index": { + "from": 13374779 + }, + "name": "gravity", + "nativeToken": { + "decimals": 18, + "name": "Gravity", + "symbol": "G" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.gravity.xyz" + } + ], + "technicalStack": "arbitrumnitro", + "aggregationHook": "0x836E1b748cac2FAc6264Baf2bF83cd9a79b723C6", + "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730", + "domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "fallbackRoutingHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "interchainAccountIsm": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "interchainAccountRouter": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563", + "interchainGasPaymaster": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a", + "interchainSecurityModule": "0xfa19BfEcB4fed2e0268ee5008a11cD946DcC13c3", + "mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "merkleTreeHook": "0x5090dF2FBDa7127c7aDa41f60B79F5c55D380Dd8", + "pausableHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "pausableIsm": "0x7621e04860F0bDe63311db9D5D8b589AD3458A1f", + "protocolFee": "0x8C3e1794018a589c9E9226b8543105fCb6cC88C4", + "proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticAggregationIsm": "0xfa19BfEcB4fed2e0268ee5008a11cD946DcC13c3", + "staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "storageGasOracle": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "testRecipient": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", + "displayNameShort": "Gravity" + }, + "harmony": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.harmony.one/api", + "family": "blockscout", + "name": "Harmony Explorer", + "url": "https://explorer.harmony.one" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 5 + }, + "chainId": 1666600000, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Harmony One", + "domainId": 1666600000, + "gasCurrencyCoinGeckoId": "harmony", + "name": "harmony", + "nativeToken": { + "decimals": 18, + "name": "ONE", + "symbol": "ONE" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://api.harmony.one" + }, + { + "http": "https://api.s0.t.hmny.io" + }, + { + "http": "https://1rpc.io/one" + }, + { + "http": "https://rpc.ankr.com/harmony" + } + ], + "technicalStack": "other", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "index": { + "chunk": 999, + "from": 64597391 + } + }, + "kaia": { + "blockExplorers": [ + { + "apiUrl": "https://api-cypress.klaytnscope.com/api", + "family": "etherscan", + "name": "Kaiascope", + "url": "https://kaiascope.com" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 5 + }, + "chainId": 8217, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Kaia", + "domainId": 8217, + "gasCurrencyCoinGeckoId": "kaia", + "name": "kaia", + "nativeToken": { + "decimals": 18, + "name": "Kaia", + "symbol": "KLAY" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://public-en.node.kaia.io" + } + ], + "technicalStack": "other", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "index": { + "from": 167871545 + } + }, + "morph": { + "blockExplorers": [ + { + "apiUrl": "https://explorer-api.morphl2.io/api", + "family": "blockscout", + "name": "Morph Explorer", + "url": "https://explorer.morphl2.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 4, + "reorgPeriod": 5 + }, + "chainId": 2818, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Morph", + "domainId": 2818, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "morph", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.morphl2.io" + } + ], + "technicalStack": "other", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "index": { + "from": 94151 + } + }, + "orderly": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.orderly.network/api", + "family": "blockscout", + "name": "Orderly L2 Explorer", + "url": "https://explorer.orderly.network" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 5 + }, + "chainId": 291, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Orderly L2", + "domainId": 291, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "orderly", + "nativeToken": { + "decimals": 18, + "name": "Ethereum", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://rpc.orderly.network" + }, + { + "http": "https://l2-orderly-mainnet-0.t.conduit.xyz" + } + ], + "technicalStack": "opstack", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "index": { + "from": 16635646 + } + }, + "snaxchain": { + "blockExplorers": [ + { + "apiUrl": "https://explorer.snaxchain.io/api", + "family": "blockscout", + "name": "Snaxchain Mainnet Explorer", + "url": "https://explorer.snaxchain.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 5 + }, + "chainId": 2192, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "SnaxChain", + "domainId": 2192, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "snaxchain", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet.snaxchain.io" + } + ], + "technicalStack": "opstack", + "aggregationHook": "0xcFD1c5b1357539566edC273aDaae19CA5e359c42", + "domainRoutingIsm": "0x494415e823236A05c608D6b777bC80082cED6A2E", + "domainRoutingIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "fallbackRoutingHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "pausableIsm": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "protocolFee": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "proxyAdmin": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "staticAggregationHookFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "staticAggregationIsm": "0x92772a801db50044a9D5078CC35CD63CEcD7B424", + "staticAggregationIsmFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "staticMerkleRootMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "staticMerkleRootWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "staticMessageIdMultisigIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "staticMessageIdWeightedMultisigIsmFactory": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "storageGasOracle": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "testRecipient": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "timelockController": "0x0000000000000000000000000000000000000000", + "validatorAnnounce": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "index": { + "from": 3158644 + } + }, + "zeronetwork": { + "blockExplorers": [ + { + "apiUrl": "https://zero-network-api.calderaexplorer.xyz/api", + "family": "etherscan", + "name": "Zero Network Explorer", + "url": "https://zerion-explorer.vercel.app" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 0 + }, + "chainId": 543210, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "Zero Network", + "domainId": 543210, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "zeronetwork", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://zero-network.calderachain.xyz" + } + ], + "technicalStack": "zksync", + "domainRoutingIsm": "0x307A9dBD1df2329c3c597aF6853de60660baFFb5", + "domainRoutingIsmFactory": "0x0000000000000000000000000000000000000000", + "fallbackDomainRoutingHook": "0x671836d35BB15E21ECc92c4936F0e3131efe12B4", + "fallbackRoutingHook": "0x671836d35BB15E21ECc92c4936F0e3131efe12B4", + "interchainGasPaymaster": "0x318FbdB17d4e743aBF3183658a4730777101B75C", + "interchainSecurityModule": "0x307A9dBD1df2329c3c597aF6853de60660baFFb5", + "mailbox": "0xd7b351D2dE3495eA259DD10ab4b9300A378Afbf3", + "merkleTreeHook": "0x55379421409961Ef129738c24261379ef8A547Df", + "proxyAdmin": "0x72e2A678442Edc65f14476A0E4c94312C0469f4A", + "staticAggregationHookFactory": "0x0000000000000000000000000000000000000000", + "staticAggregationIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMerkleRootMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMessageIdMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMessageIdWeightedMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "storageGasOracle": "0xe85d65f04D1562f8571d57326d6798e4584aa254", + "testRecipient": "0xC18bE7ac43334F501fd9622877160b085215dECC", + "validatorAnnounce": "0xB2F0e411B46AbE3248dAFB5e89aDB5b8404F45DF", + "index": { + "from": 475 + } + }, + "zksync": { + "blockExplorers": [ + { + "apiUrl": "https://block-explorer-api.mainnet.zksync.io/api", + "family": "etherscan", + "name": "zkSync Explorer", + "url": "https://explorer.zksync.io" + } + ], + "blocks": { + "confirmations": 1, + "estimateBlockTime": 1, + "reorgPeriod": 0 + }, + "chainId": 324, + "deployer": { + "name": "Abacus Works", + "url": "https://www.hyperlane.xyz" + }, + "displayName": "zkSync", + "domainId": 324, + "gasCurrencyCoinGeckoId": "ethereum", + "name": "zksync", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://mainnet.era.zksync.io" + } + ], + "technicalStack": "zksync", + "domainRoutingIsm": "0xec650696FDAE2355A928520AD7d6491c6072cf7f", + "domainRoutingIsmFactory": "0x0000000000000000000000000000000000000000", + "fallbackDomainRoutingHook": "0xe4e98Cc5D0318aBFD2adA8A3C6817b727063F500", + "fallbackRoutingHook": "0xe4e98Cc5D0318aBFD2adA8A3C6817b727063F500", + "interchainGasPaymaster": "0xf44AdA86a1f765A938d404699B8070Dd47bD2431", + "interchainSecurityModule": "0xec650696FDAE2355A928520AD7d6491c6072cf7f", + "mailbox": "0x6bD0A2214797Bc81e0b006F7B74d6221BcD8cb6E", + "merkleTreeHook": "0x823500D69D77A52212DC93f8836E9c08581487eE", + "proxyAdmin": "0xD01274DC164D32F8595bE707F221375E68cE300C", + "staticAggregationHookFactory": "0x0000000000000000000000000000000000000000", + "staticAggregationIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMerkleRootMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMerkleRootWeightedMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMessageIdMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "staticMessageIdWeightedMultisigIsmFactory": "0x0000000000000000000000000000000000000000", + "storageGasOracle": "0x37f4afe769087738f0577A77ffA24abef6fCBF99", + "testRecipient": "0xD55078c54b0cEAa87Ba5c3fAeAC89861c69F636d", + "validatorAnnounce": "0x576aF402c97bFE452Dcc203B6c3f6F4EBC92A0f5", + "index": { + "from": 47325797 + } } }, "defaultRpcConsensusType": "fallback" diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 68ac9ccb9..aa79f5e43 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -58,10 +58,13 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< [Role.Validator]: { ancient8: true, alephzeroevm: true, + apechain: true, arbitrum: true, + arbitrumnova: true, astar: true, astarzkevm: true, avalanche: true, + b3: true, base: true, bitlayer: true, blast: true, @@ -78,14 +81,18 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< endurance: true, ethereum: true, everclear: true, + fantom: true, flare: true, flow: true, fraxtal: true, fusemainnet: true, gnosis: true, + gravity: true, + harmony: true, immutablezkevm: true, inevm: true, injective: true, + kaia: true, kroma: true, linea: true, lisk: true, @@ -100,9 +107,11 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< mode: true, molten: true, moonbeam: true, + morph: true, neutron: true, oortmainnet: true, optimism: true, + orderly: true, osmosis: true, polygon: true, polygonzkevm: true, @@ -116,6 +125,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< scroll: true, sei: true, shibarium: true, + snaxchain: true, solanamainnet: true, stride: false, superposition: true, @@ -125,17 +135,22 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< worldchain: true, xai: true, xlayer: true, + zeronetwork: true, zetachain: true, zircuit: true, + zksync: true, zoramainnet: true, }, [Role.Relayer]: { alephzeroevm: true, ancient8: true, + apechain: true, arbitrum: true, + arbitrumnova: true, astar: true, astarzkevm: true, avalanche: true, + b3: true, base: true, bitlayer: true, blast: true, @@ -152,14 +167,18 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< endurance: true, ethereum: true, everclear: true, + fantom: true, flare: true, flow: true, fraxtal: true, fusemainnet: true, gnosis: true, + gravity: true, + harmony: true, immutablezkevm: true, inevm: true, injective: true, + kaia: true, kroma: true, linea: true, lisk: true, @@ -174,10 +193,12 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< mode: true, molten: true, moonbeam: true, + morph: true, // At the moment, we only relay between Neutron and Manta Pacific on the neutron context. neutron: false, oortmainnet: true, optimism: true, + orderly: true, osmosis: true, polygon: true, polygonzkevm: true, @@ -191,6 +212,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< scroll: true, sei: true, shibarium: true, + snaxchain: true, solanamainnet: true, stride: true, superposition: true, @@ -200,17 +222,22 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< worldchain: true, xai: true, xlayer: true, + zeronetwork: true, zetachain: true, zircuit: true, + zksync: true, zoramainnet: true, }, [Role.Scraper]: { ancient8: true, alephzeroevm: true, + apechain: true, arbitrum: true, + arbitrumnova: true, astar: true, astarzkevm: true, avalanche: true, + b3: true, base: true, bitlayer: true, blast: true, @@ -228,14 +255,18 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< endurance: true, ethereum: true, everclear: true, + fantom: true, flare: true, flow: true, fraxtal: true, fusemainnet: true, gnosis: true, + gravity: true, + harmony: true, immutablezkevm: true, inevm: true, injective: true, + kaia: true, kroma: true, linea: true, lisk: true, @@ -250,9 +281,11 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< mode: true, molten: true, moonbeam: true, + morph: true, neutron: true, oortmainnet: true, optimism: true, + orderly: true, osmosis: true, polygon: true, polygonzkevm: true, @@ -266,6 +299,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< scroll: true, sei: true, shibarium: true, + snaxchain: true, // Cannot scrape Sealevel chains solanamainnet: false, stride: true, @@ -277,8 +311,10 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< worldchain: true, xai: true, xlayer: true, + zeronetwork: true, zetachain: true, zircuit: true, + zksync: true, zoramainnet: true, }, }; @@ -429,7 +465,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'a64af8b-20241024-120818', + tag: '45399a3-20241025-210128', }, gasPaymentEnforcement: gasPaymentEnforcement, metricAppContexts, @@ -438,7 +474,7 @@ const hyperlane: RootAgentConfig = { validators: { docker: { repo, - tag: 'a64af8b-20241024-120818', + tag: '45399a3-20241025-210128', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -448,7 +484,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: 'a64af8b-20241024-120818', + tag: '45399a3-20241025-210128', }, resources: scraperResources, }, diff --git a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json index a63b630da..67119a8ee 100644 --- a/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json +++ b/typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json @@ -5,6 +5,9 @@ "alephzeroevm": { "validators": ["0xcae8fab142adc4e434bb7409e40dd932cc3851aa"] }, + "apechain": { + "validators": ["0x773d7fe6ffb1ba4de814c28044ff9a2d83a48221"] + }, "arbitrum": { "validators": [ "0x4d966438fe9e2b1e7124c87bbb90cb4f0f6c59a1", @@ -12,6 +15,9 @@ "0x3369e12edd52570806f126eb50be269ba5e65843" ] }, + "arbitrumnova": { + "validators": ["0xd2a5e9123308d187383c87053811a2c21bd8af1f"] + }, "astar": { "validators": ["0x4d1b2cade01ee3493f44304653d8e352c66ec3e7"] }, @@ -25,6 +31,9 @@ "0x6c754f1e9cd8287088b46a7c807303d55d728b49" ] }, + "b3": { + "validators": ["0xd77b516730a836fc41934e7d5864e72c165b934e"] + }, "base": { "validators": [ "0xb9453d675e0fa3c178a17b4ce1ad5b1a279b3af9", @@ -89,6 +98,9 @@ "everclear": { "validators": ["0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837"] }, + "fantom": { + "validators": ["0xa779572028e634e16f26af5dfd4fa685f619457d"] + }, "flare": { "validators": ["0xb65e52be342dba3ab2c088ceeb4290c744809134"] }, @@ -108,6 +120,12 @@ "0xb93a72cee19402553c9dd7fed2461aebd04e2454" ] }, + "gravity": { + "validators": ["0x23d549bf757a02a6f6068e9363196ecd958c974e"] + }, + "harmony": { + "validators": ["0xd677803a67651974b1c264171b5d7ca8838db8d5"] + }, "immutablezkevm": { "validators": ["0xa787c2952a4d22f776ee6e87e828e6f75de24330"] }, @@ -121,6 +139,9 @@ "injective": { "validators": ["0xbfb8911b72cfb138c7ce517c57d9c691535dc517"] }, + "kaia": { + "validators": ["0x9de0b3abb221d19719882fa4d61f769fdc2be9a4"] + }, "kroma": { "validators": ["0x71b83c21342787d758199e4b8634d3a15f02dc6e"] }, @@ -171,6 +192,9 @@ "0xcc4a78aa162482bea43313cd836ba7b560b44fc4" ] }, + "morph": { + "validators": ["0x4884535f393151ec419add872100d352f71af380"] + }, "neutron": { "validators": [ "0xa9b8c1f4998f781f958c63cfcd1708d02f004ff0", @@ -188,6 +212,9 @@ "0x779a17e035018396724a6dec8a59bda1b5adf738" ] }, + "orderly": { + "validators": ["0xec3dc91f9fa2ad35edf5842aa764d5573b778bb6"] + }, "osmosis": { "validators": ["0xea483af11c19fa41b16c31d1534c2a486a92bcac"] }, @@ -239,6 +266,9 @@ "shibarium": { "validators": ["0xfa33391ee38597cbeef72ccde8c9e13e01e78521"] }, + "snaxchain": { + "validators": ["0x2c25829ae32a772d2a49f6c4b34f8b01fd03ef9e"] + }, "solanamainnet": { "validators": ["0x28464752829b3ea59a497fca0bdff575c534c3ff"] }, @@ -263,12 +293,18 @@ "xlayer": { "validators": ["0xa2ae7c594703e988f23d97220717c513db638ea3"] }, + "zeronetwork": { + "validators": ["0x1bd9e3f8a90ea1a13b0f2838a1858046368aad87"] + }, "zetachain": { "validators": ["0xa3bca0b80317dbf9c7dce16a16ac89f4ff2b23ef"] }, "zircuit": { "validators": ["0x169ec400cc758fef3df6a0d6c51fbc6cdd1015bb"] }, + "zksync": { + "validators": ["0xadd1d39ce7a687e32255ac457cf99a6d8c5b5d1a"] + }, "zoramainnet": { "validators": ["0x35130945b625bb69b28aee902a3b9a76fa67125f"] } diff --git a/typescript/infra/config/environments/mainnet3/core/verification.json b/typescript/infra/config/environments/mainnet3/core/verification.json index 371e68403..029f75ad6 100644 --- a/typescript/infra/config/environments/mainnet3/core/verification.json +++ b/typescript/infra/config/environments/mainnet3/core/verification.json @@ -4395,5 +4395,893 @@ "constructorArguments": "000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90", "isProxy": false } + ], + "zksync": [ + { + "name": "ProxyAdmin", + "address": "0xD01274DC164D32F8595bE707F221375E68cE300C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x1B4E7fd3052Fc6d84DAB69eEf6a156C7D7909a78", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000144", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x6bD0A2214797Bc81e0b006F7B74d6221BcD8cb6E", + "constructorArguments": "0000000000000000000000001b4e7fd3052fc6d84dab69eef6a156c7d7909a78000000000000000000000000d01274dc164d32f8595be707f221375e68ce300c00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x1B4E7fd3052Fc6d84DAB69eEf6a156C7D7909a78" + }, + { + "name": "DomainRoutingIsm", + "address": "0xec650696FDAE2355A928520AD7d6491c6072cf7f", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x823500D69D77A52212DC93f8836E9c08581487eE", + "constructorArguments": "0000000000000000000000006bd0a2214797bc81e0b006f7b74d6221bcd8cb6e", + "isProxy": false + }, + { + "name": "FallbackDomainRoutingHook", + "address": "0xe4e98Cc5D0318aBFD2adA8A3C6817b727063F500", + "constructorArguments": "0000000000000000000000006bd0a2214797bc81e0b006f7b74d6221bcd8cb6e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000823500d69d77a52212dc93f8836e9c08581487ee", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x37f4afe769087738f0577A77ffA24abef6fCBF99", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0x95d20666eDf61b39f2706a7fc95E50C2758F800b", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xf44AdA86a1f765A938d404699B8070Dd47bD2431", + "constructorArguments": "00000000000000000000000095d20666edf61b39f2706a7fc95e50c2758f800b000000000000000000000000d01274dc164d32f8595be707f221375e68ce300c00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x95d20666eDf61b39f2706a7fc95E50C2758F800b" + }, + { + "name": "ValidatorAnnounce", + "address": "0x576aF402c97bFE452Dcc203B6c3f6F4EBC92A0f5", + "constructorArguments": "0000000000000000000000006bd0a2214797bc81e0b006f7b74d6221bcd8cb6e", + "isProxy": false + } + ], + "zeronetwork": [ + { + "name": "ProxyAdmin", + "address": "0x72e2A678442Edc65f14476A0E4c94312C0469f4A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a4c1e089dCaba813c10b641d8296a972ffAd939", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000849ea", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xd7b351D2dE3495eA259DD10ab4b9300A378Afbf3", + "constructorArguments": "0000000000000000000000003a4c1e089dcaba813c10b641d8296a972ffad93900000000000000000000000072e2a678442edc65f14476a0e4c94312c0469f4a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a4c1e089dCaba813c10b641d8296a972ffAd939" + }, + { + "name": "DomainRoutingIsm", + "address": "0x307A9dBD1df2329c3c597aF6853de60660baFFb5", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x55379421409961Ef129738c24261379ef8A547Df", + "constructorArguments": "000000000000000000000000d7b351d2de3495ea259dd10ab4b9300a378afbf3", + "isProxy": false + }, + { + "name": "FallbackDomainRoutingHook", + "address": "0x671836d35BB15E21ECc92c4936F0e3131efe12B4", + "constructorArguments": "000000000000000000000000d7b351d2de3495ea259dd10ab4b9300a378afbf3000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000055379421409961ef129738c24261379ef8a547df", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xe85d65f04D1562f8571d57326d6798e4584aa254", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xDA6193892B324fdEc49209E7cB37E5eE84Cb2459", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x318FbdB17d4e743aBF3183658a4730777101B75C", + "constructorArguments": "000000000000000000000000da6193892b324fdec49209e7cb37e5ee84cb245900000000000000000000000072e2a678442edc65f14476a0e4c94312c0469f4a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xDA6193892B324fdEc49209E7cB37E5eE84Cb2459" + }, + { + "name": "ValidatorAnnounce", + "address": "0xB2F0e411B46AbE3248dAFB5e89aDB5b8404F45DF", + "constructorArguments": "000000000000000000000000d7b351d2de3495ea259dd10ab4b9300a378afbf3", + "isProxy": false + } + ], + "gravity": [ + { + "name": "ProxyAdmin", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000659", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D" + }, + { + "name": "PausableIsm", + "address": "0x7621e04860F0bDe63311db9D5D8b589AD3458A1f", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x5090dF2FBDa7127c7aDa41f60B79F5c55D380Dd8", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000005090df2fbda7127c7ada41f60b79f5c55d380dd8", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xF1854214392864c628A16930E73B699f7a51b3EE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a", + "constructorArguments": "000000000000000000000000f1854214392864c628a16930e73b699f7a51b3ee0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xF1854214392864c628A16930E73B699f7a51b3EE" + }, + { + "name": "ProtocolFee", + "address": "0x8C3e1794018a589c9E9226b8543105fCb6cC88C4", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + } + ], + "arbitrumnova": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000a4ba", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "apechain": [ + { + "name": "ProxyAdmin", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000008173", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa70000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7" + }, + { + "name": "PausableIsm", + "address": "0x5090dF2FBDa7127c7aDa41f60B79F5c55D380Dd8", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000886bb0f329781b98f98fdeb1ce7a8957f2d43b9f", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0xF1854214392864c628A16930E73B699f7a51b3EE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x18B0688990720103dB63559a3563f7E8d0f63EDb", + "constructorArguments": "000000000000000000000000f3dff6747e7fc74b431c943961054b7bf6309d8a0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a" + }, + { + "name": "ProtocolFee", + "address": "0x61374178e45F65fF9D6252d017Cd580FC60B7654", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + } + ], + "harmony": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000063564c40", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "kaia": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000002019", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "b3": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "000000000000000000000000000000000000000000000000000000000000208d", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "orderly": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000123", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "snaxchain": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000890", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "morph": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000b02", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } + ], + "fantom": [ + { + "name": "ProxyAdmin", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000000fa", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E" + }, + { + "name": "PausableIsm", + "address": "0x696df5e79C4f1bd5F8D587Ba8946361d9B029d4B", + "constructorArguments": "000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "MerkleTreeHook", + "address": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000006963480b05eb58f4d624b014ab92e9ad4d21df6d", + "isProxy": false + }, + { + "name": "PausableHook", + "address": "0xD0dca420feFda68537695A8D887080eeF4030AF7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x2F619Ac5122689180AeBB930ADccdae215d538a9", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x145566181A18E23bB6a8A3eC6D87765542A7F754", + "constructorArguments": "000000000000000000000000ee08043cf22c80b27bf24d19999231df4a3fc256000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xEe08043cf22c80b27BF24d19999231dF4a3fC256" + }, + { + "name": "ProtocolFee", + "address": "0x13E83ac41e696856B6996263501fB3225AD5E6F5", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/mainnet3/funding.ts b/typescript/infra/config/environments/mainnet3/funding.ts index 89e34339a..1c348376a 100644 --- a/typescript/infra/config/environments/mainnet3/funding.ts +++ b/typescript/infra/config/environments/mainnet3/funding.ts @@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig< > = { docker: { repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', - tag: '25ae727-20241025-165028', + tag: '2cde782-20241029-100534', }, // We're currently using the same deployer/key funder key as mainnet2. // To minimize nonce clobbering we offset the key funder cron @@ -28,10 +28,13 @@ export const keyFunderConfig: KeyFunderConfig< desiredBalancePerChain: { ancient8: '0.5', alephzeroevm: '100', + apechain: '50', arbitrum: '0.5', + arbitrumnova: '0.05', astar: '100', astarzkevm: '0.05', avalanche: '5', + b3: '0.05', base: '0.5', bitlayer: '0.002', blast: '0.2', @@ -47,13 +50,17 @@ export const keyFunderConfig: KeyFunderConfig< endurance: '20', ethereum: '0.5', everclear: '0.05', + fantom: '100', flare: '500', flow: '5', fraxtal: '0.2', fusemainnet: '20', gnosis: '5', + gravity: '500', + harmony: '500', immutablezkevm: '25', inevm: '3', + kaia: '250', kroma: '0.05', linea: '0.2', lisk: '0.05', @@ -68,8 +75,10 @@ export const keyFunderConfig: KeyFunderConfig< mode: '0.2', molten: '3', moonbeam: '5', + morph: '0.05', oortmainnet: '2000', optimism: '0.5', + orderly: '0.05', polygon: '20', polygonzkevm: '0.5', polynomial: '0.05', @@ -82,6 +91,7 @@ export const keyFunderConfig: KeyFunderConfig< scroll: '0.5', sei: '50', shibarium: '50', + snaxchain: '0.05', // ignore non-evm chains stride: '0', superposition: '0.05', @@ -91,8 +101,10 @@ export const keyFunderConfig: KeyFunderConfig< worldchain: '0.2', xai: '20', xlayer: '0.5', + zeronetwork: '0.05', zetachain: '20', zircuit: '0.02', + zksync: '0.05', zoramainnet: '0.2', // ignore non-evm chains injective: '0', diff --git a/typescript/infra/config/environments/mainnet3/gasPrices.json b/typescript/infra/config/environments/mainnet3/gasPrices.json index 7f61122c8..4652bedc1 100644 --- a/typescript/infra/config/environments/mainnet3/gasPrices.json +++ b/typescript/infra/config/environments/mainnet3/gasPrices.json @@ -7,8 +7,16 @@ "amount": "40.0", "decimals": 9 }, + "apechain": { + "amount": "25.42069", + "decimals": 9 + }, "arbitrum": { - "amount": "0.017537", + "amount": "0.032084", + "decimals": 9 + }, + "arbitrumnova": { + "amount": "0.01", "decimals": 9 }, "astar": { @@ -16,15 +24,19 @@ "decimals": 9 }, "astarzkevm": { - "amount": "0.399", + "amount": "0.0696", "decimals": 9 }, "avalanche": { "amount": "25.0", "decimals": 9 }, + "b3": { + "amount": "0.001000252", + "decimals": 9 + }, "base": { - "amount": "0.015396226", + "amount": "0.025135767", "decimals": 9 }, "bitlayer": { @@ -32,7 +44,7 @@ "decimals": 9 }, "blast": { - "amount": "0.005712307", + "amount": "0.004639802", "decimals": 9 }, "bob": { @@ -76,19 +88,23 @@ "decimals": 1 }, "endurance": { - "amount": "3.0756015", + "amount": "1.500000007", "decimals": 9 }, "ethereum": { - "amount": "14.852716956", + "amount": "9.379005838", "decimals": 9 }, "everclear": { "amount": "0.1", "decimals": 9 }, + "fantom": { + "amount": "9.871668079", + "decimals": 9 + }, "flare": { - "amount": "49.455765643", + "amount": "26.179282546", "decimals": 9 }, "flow": { @@ -104,11 +120,19 @@ "decimals": 9 }, "gnosis": { - "amount": "1.500000007", + "amount": "1.430000001", + "decimals": 9 + }, + "gravity": { + "amount": "1800.0", + "decimals": 9 + }, + "harmony": { + "amount": "100.0", "decimals": 9 }, "immutablezkevm": { - "amount": "10.1", + "amount": "11.000000049", "decimals": 9 }, "inevm": { @@ -119,12 +143,16 @@ "amount": "700000000", "decimals": 1 }, + "kaia": { + "amount": "27.5", + "decimals": 9 + }, "kroma": { "amount": "0.001000252", "decimals": 9 }, "linea": { - "amount": "0.243", + "amount": "0.312253183", "decimals": 9 }, "lisk": { @@ -132,7 +160,7 @@ "decimals": 9 }, "lukso": { - "amount": "0.82770224", + "amount": "0.557453646", "decimals": 9 }, "lumia": { @@ -140,7 +168,7 @@ "decimals": 9 }, "mantapacific": { - "amount": "0.00129795", + "amount": "0.001001418", "decimals": 9 }, "mantle": { @@ -156,7 +184,7 @@ "decimals": 9 }, "metis": { - "amount": "1.278943587", + "amount": "1.077971462", "decimals": 9 }, "mint": { @@ -164,7 +192,7 @@ "decimals": 9 }, "mode": { - "amount": "0.001000313", + "amount": "0.001000265", "decimals": 9 }, "molten": { @@ -175,6 +203,10 @@ "amount": "125.0", "decimals": 9 }, + "morph": { + "amount": "0.0041472", + "decimals": 9 + }, "neutron": { "amount": "0.0053", "decimals": 1 @@ -184,7 +216,11 @@ "decimals": 9 }, "optimism": { - "amount": "0.02163419", + "amount": "0.001001064", + "decimals": 9 + }, + "orderly": { + "amount": "0.00100025", "decimals": 9 }, "osmosis": { @@ -192,11 +228,11 @@ "decimals": 1 }, "polygon": { - "amount": "61.134765243", + "amount": "100", "decimals": 9 }, "polygonzkevm": { - "amount": "0.726", + "amount": "0.5", "decimals": 9 }, "polynomial": { @@ -208,11 +244,11 @@ "decimals": 9 }, "rari": { - "amount": "0.03", + "amount": "0.15", "decimals": 9 }, "real": { - "amount": "0.022", + "amount": "0.03", "decimals": 9 }, "redstone": { @@ -228,7 +264,7 @@ "decimals": 9 }, "scroll": { - "amount": "0.048755492", + "amount": "0.041113999", "decimals": 9 }, "sei": { @@ -236,7 +272,11 @@ "decimals": 9 }, "shibarium": { - "amount": "39.319461243", + "amount": "61.627947201", + "decimals": 9 + }, + "snaxchain": { + "amount": "0.001000252", "decimals": 9 }, "solanamainnet": { @@ -252,7 +292,7 @@ "decimals": 9 }, "taiko": { - "amount": "0.050000001", + "amount": "0.11100569", "decimals": 9 }, "tangle": { @@ -264,15 +304,19 @@ "decimals": 9 }, "worldchain": { - "amount": "0.001000251", + "amount": "0.001000298", "decimals": 9 }, "xai": { - "amount": "0.1", + "amount": "0.10081", "decimals": 9 }, "xlayer": { - "amount": "14.54921875", + "amount": "5.882081", + "decimals": 9 + }, + "zeronetwork": { + "amount": "0.04525", "decimals": 9 }, "zetachain": { @@ -283,8 +327,12 @@ "amount": "0.001000253", "decimals": 9 }, + "zksync": { + "amount": "0.04525", + "decimals": 9 + }, "zoramainnet": { - "amount": "0.001000274", + "amount": "0.001000255", "decimals": 9 } } diff --git a/typescript/infra/config/environments/mainnet3/ism/verification.json b/typescript/infra/config/environments/mainnet3/ism/verification.json index 965505539..b291cf0e3 100644 --- a/typescript/infra/config/environments/mainnet3/ism/verification.json +++ b/typescript/infra/config/environments/mainnet3/ism/verification.json @@ -5798,5 +5798,865 @@ "constructorArguments": "", "isProxy": true } + ], + "gravity": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + } + ], + "apechain": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0xDFF18Bf286c9cDd0fC653a28616460Cf7443F8EF", + "constructorArguments": "", + "isProxy": true + } + ], + "arbitrumnova": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "harmony": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "kaia": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "b3": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "fantom": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "morph": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "orderly": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } + ], + "snaxchain": [ + { + "name": "StaticMerkleRootMultisigIsmFactory", + "address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdMultisigIsmFactory", + "address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationIsmFactory", + "address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticAggregationHookFactory", + "address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "DomainRoutingIsmFactory", + "address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMerkleRootWeightedMultisigIsmFactory", + "address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootWeightedMultisigIsm", + "address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "StaticMessageIdWeightedMultisigIsmFactory", + "address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdWeightedMultisigIsm", + "address": "0x7f51A658837A315134A97ff8B586d71B726B7e61", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json index 62bda474a..773a6e781 100644 --- a/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json @@ -1599,5 +1599,215 @@ "isProxy": true, "expectedimplementation": "0x3E12271EbD523d0886D0D51A4FF8D8e046CF2E1D" } + ], + "gravity": [ + { + "name": "InterchainAccountIsm", + "address": "0x783EC5e105234a570eB90f314284E5dBe53bdd90", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563", + "constructorArguments": "000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000783ec5e105234a570eb90f314284e5dbe53bdd90000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed" + } + ], + "apechain": [ + { + "name": "InterchainAccountIsm", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563", + "constructorArguments": "0000000000000000000000007f50c5776722630a0024fae05fde8b47571d7b39", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47", + "constructorArguments": "000000000000000000000000c5d6acaafbccec6d7fd7d92f4509befce641c5630000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563" + } + ], + "arbitrumnova": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "harmony": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "kaia": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "b3": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "orderly": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "snaxchain": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "fantom": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } + ], + "morph": [ + { + "name": "InterchainAccountIsm", + "address": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "InterchainAccountRouter", + "address": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1", + "constructorArguments": "0000000000000000000000003a867fcffec2b790970eebdc9023e75b0a172aa7", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451", + "constructorArguments": "0000000000000000000000006119b76720ccfeb3d256ec1b91218eeffd6756e1000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb9e40d811cea562cc8a322b029ef2bdcc3ef6ed000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000", + "isProxy": true, + "expectedimplementation": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1" + } ] } diff --git a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts index 3e5957241..39957bea0 100644 --- a/typescript/infra/config/environments/mainnet3/supportedChainNames.ts +++ b/typescript/infra/config/environments/mainnet3/supportedChainNames.ts @@ -3,10 +3,13 @@ export const mainnet3SupportedChainNames = [ 'ancient8', 'alephzeroevm', + 'apechain', 'arbitrum', + 'arbitrumnova', 'astar', 'astarzkevm', 'avalanche', + 'b3', 'base', 'bitlayer', 'blast', @@ -23,14 +26,18 @@ export const mainnet3SupportedChainNames = [ 'endurance', 'ethereum', 'everclear', + 'fantom', 'flare', 'flow', 'fraxtal', 'fusemainnet', 'gnosis', + 'gravity', + 'harmony', 'immutablezkevm', 'inevm', 'injective', + 'kaia', 'kroma', 'linea', 'lisk', @@ -45,9 +52,11 @@ export const mainnet3SupportedChainNames = [ 'mode', 'molten', 'moonbeam', + 'morph', 'neutron', 'oortmainnet', 'optimism', + 'orderly', 'osmosis', 'polygon', 'polygonzkevm', @@ -61,6 +70,7 @@ export const mainnet3SupportedChainNames = [ 'scroll', 'sei', 'shibarium', + 'snaxchain', 'solanamainnet', 'stride', 'superposition', @@ -70,8 +80,10 @@ export const mainnet3SupportedChainNames = [ 'worldchain', 'xai', 'xlayer', + 'zeronetwork', 'zetachain', 'zircuit', + 'zksync', 'zoramainnet', ] as const; diff --git a/typescript/infra/config/environments/mainnet3/tokenPrices.json b/typescript/infra/config/environments/mainnet3/tokenPrices.json index 86c2ed731..abe764bb7 100644 --- a/typescript/infra/config/environments/mainnet3/tokenPrices.json +++ b/typescript/infra/config/environments/mainnet3/tokenPrices.json @@ -1,74 +1,86 @@ { - "ancient8": "2629.74", - "alephzeroevm": "0.381786", - "arbitrum": "2629.74", - "astar": "0.061114", - "astarzkevm": "2629.74", - "avalanche": "27.96", - "base": "2629.74", - "bitlayer": "67813", - "blast": "2629.74", - "bob": "2629.74", - "bsc": "597.89", - "celo": "0.817141", - "cheesechain": "0.00556724", - "chiliz": "0.079288", - "coredao": "0.98348", - "cyber": "2629.74", - "degenchain": "0.00882961", - "dogechain": "0.126177", - "eclipsemainnet": "2629.74", - "endurance": "2.16", - "ethereum": "2629.74", - "everclear": "2629.74", - "flare": "0.01493582", - "flow": "0.558323", - "fraxtal": "2629.35", - "fusemainnet": "0.02901498", - "gnosis": "0.997404", - "immutablezkevm": "1.54", - "inevm": "21.05", - "injective": "21.05", - "kroma": "2629.74", - "linea": "2629.74", - "lisk": "2629.74", - "lukso": "1.47", - "lumia": "0.969511", - "mantapacific": "2629.74", - "mantle": "0.636484", - "merlin": "67781", - "metall2": "2629.74", - "metis": "45.78", - "mint": "2629.74", - "mode": "2629.74", - "molten": "0.436605", - "moonbeam": "0.169406", - "neutron": "0.408859", - "oortmainnet": "0.114304", - "optimism": "2629.74", - "osmosis": "0.558566", - "polygon": "0.371646", - "polygonzkevm": "2629.74", - "polynomial": "2629.74", - "proofofplay": "2629.74", - "rari": "2629.74", + "ancient8": "2509.23", + "alephzeroevm": "0.374106", + "apechain": "1.17", + "arbitrum": "2509.23", + "arbitrumnova": "2509.23", + "astar": "0.056948", + "astarzkevm": "2509.23", + "avalanche": "25.94", + "b3": "2509.23", + "base": "2509.23", + "bitlayer": "67372", + "blast": "2509.23", + "bob": "2509.23", + "bsc": "587.93", + "celo": "0.687006", + "cheesechain": "0.00295261", + "chiliz": "0.065082", + "coredao": "0.9041", + "cyber": "2509.23", + "degenchain": "0.00694026", + "dogechain": "0.135405", + "eclipsemainnet": "2509.23", + "endurance": "2.14", + "ethereum": "2509.23", + "everclear": "2509.23", + "fantom": "0.668043", + "flare": "0.01413977", + "flow": "0.537723", + "fraxtal": "2506.4", + "fusemainnet": "0.02708378", + "gnosis": "1", + "gravity": "0.03113181", + "harmony": "0.012995", + "immutablezkevm": "1.42", + "inevm": "19.75", + "injective": "19.75", + "kaia": "1", + "kroma": "2509.23", + "linea": "2509.23", + "lisk": "2509.23", + "lukso": "1.38", + "lumia": "1.14", + "mantapacific": "2509.23", + "mantle": "0.591459", + "merlin": "67402", + "metall2": "2509.23", + "metis": "41.48", + "mint": "2509.23", + "mode": "2509.23", + "molten": "0.202455", + "moonbeam": "0.163232", + "morph": "2509.23", + "neutron": "0.383777", + "oortmainnet": "0.109681", + "optimism": "2509.23", + "orderly": "2509.23", + "osmosis": "0.483881", + "polygon": "0.340093", + "polygonzkevm": "2509.23", + "polynomial": "2509.23", + "proofofplay": "2509.23", + "rari": "2509.23", "real": "1", - "redstone": "2629.74", - "rootstock": "67219", - "sanko": "70.7", - "scroll": "2629.74", - "sei": "0.447635", - "shibarium": "0.410927", - "solanamainnet": "155.35", - "stride": "0.840153", - "superposition": "2629.74", - "taiko": "2629.74", + "redstone": "2509.23", + "rootstock": "67025", + "sanko": "47.83", + "scroll": "2509.23", + "sei": "0.393025", + "shibarium": "0.383601", + "snaxchain": "2509.23", + "solanamainnet": "168.99", + "stride": "0.731952", + "superposition": "2509.23", + "taiko": "2509.23", "tangle": "1", - "viction": "0.369839", - "worldchain": "2629.74", - "xai": "0.216438", - "xlayer": "41.56", - "zetachain": "0.617959", - "zircuit": "2629.74", - "zoramainnet": "2629.74" + "viction": "0.348004", + "worldchain": "2509.23", + "xai": "0.20891", + "xlayer": "39.32", + "zeronetwork": "2509.23", + "zetachain": "0.661744", + "zircuit": "2509.23", + "zksync": "2509.23", + "zoramainnet": "2509.23" } diff --git a/typescript/infra/config/environments/mainnet3/validators.ts b/typescript/infra/config/environments/mainnet3/validators.ts index 0c0904744..c3747ac2a 100644 --- a/typescript/infra/config/environments/mainnet3/validators.ts +++ b/typescript/infra/config/environments/mainnet3/validators.ts @@ -998,5 +998,127 @@ export const validatorChainConfig = ( 'flow', ), }, + + zeronetwork: { + interval: 5, + reorgPeriod: getReorgPeriod('zeronetwork'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x1bd9e3f8a90ea1a13b0f2838a1858046368aad87'], + }, + 'zeronetwork', + ), + }, + zksync: { + interval: 5, + reorgPeriod: getReorgPeriod('zksync'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xadd1d39ce7a687e32255ac457cf99a6d8c5b5d1a'], + }, + 'zksync', + ), + }, + + apechain: { + interval: 5, + reorgPeriod: getReorgPeriod('apechain'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x773d7fe6ffb1ba4de814c28044ff9a2d83a48221'], + }, + 'apechain', + ), + }, + arbitrumnova: { + interval: 5, + reorgPeriod: getReorgPeriod('arbitrumnova'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xd2a5e9123308d187383c87053811a2c21bd8af1f'], + }, + 'arbitrumnova', + ), + }, + b3: { + interval: 5, + reorgPeriod: getReorgPeriod('b3'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xd77b516730a836fc41934e7d5864e72c165b934e'], + }, + 'b3', + ), + }, + fantom: { + interval: 5, + reorgPeriod: getReorgPeriod('fantom'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xa779572028e634e16f26af5dfd4fa685f619457d'], + }, + 'fantom', + ), + }, + gravity: { + interval: 5, + reorgPeriod: getReorgPeriod('gravity'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x23d549bf757a02a6f6068e9363196ecd958c974e'], + }, + 'gravity', + ), + }, + harmony: { + interval: 5, + reorgPeriod: getReorgPeriod('harmony'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xd677803a67651974b1c264171b5d7ca8838db8d5'], + }, + 'harmony', + ), + }, + kaia: { + interval: 5, + reorgPeriod: getReorgPeriod('kaia'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x9de0b3abb221d19719882fa4d61f769fdc2be9a4'], + }, + 'kaia', + ), + }, + morph: { + interval: 5, + reorgPeriod: getReorgPeriod('morph'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x4884535f393151ec419add872100d352f71af380'], + }, + 'morph', + ), + }, + orderly: { + interval: 5, + reorgPeriod: getReorgPeriod('orderly'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0xec3dc91f9fa2ad35edf5842aa764d5573b778bb6'], + }, + 'orderly', + ), + }, + snaxchain: { + interval: 5, + reorgPeriod: getReorgPeriod('snaxchain'), + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x2c25829ae32a772d2a49f6c4b34f8b01fd03ef9e'], + }, + 'snaxchain', + ), + }, }; }; diff --git a/typescript/infra/scripts/deploy.ts b/typescript/infra/scripts/deploy.ts index 111d85dbf..2c8d3ff90 100644 --- a/typescript/infra/scripts/deploy.ts +++ b/typescript/infra/scripts/deploy.ts @@ -71,6 +71,10 @@ async function main() { ).argv; const envConfig = getEnvironmentConfig(environment); + // TODO: remove once zksync PR is merged into main + delete envConfig.core.zksync; + delete envConfig.core.zeronetwork; + let multiProvider = await envConfig.getMultiProvider( context, Role.Deployer, diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index 5184a4b9e..27478ed9e 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -30,6 +30,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + apechain: { + threshold: 1, + validators: ['0x773d7fe6ffb1ba4de814c28044ff9a2d83a48221'], + }, + arbitrum: { threshold: 3, validators: [ @@ -41,6 +46,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + arbitrumnova: { + threshold: 1, + validators: ['0xd2a5e9123308d187383c87053811a2c21bd8af1f'], + }, + arbitrumsepolia: { threshold: 1, validators: ['0x09fabfbca0b8bf042e2a1161ee5010d147b0f603'], @@ -78,6 +88,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + b3: { + threshold: 1, + validators: ['0xd77b516730a836fc41934e7d5864e72c165b934e'], + }, + base: { threshold: 3, validators: [ @@ -284,6 +299,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + fantom: { + threshold: 1, + validators: ['0xa779572028e634e16f26af5dfd4fa685f619457d'], + }, + flare: { threshold: 2, validators: [ @@ -344,6 +364,16 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + gravity: { + threshold: 1, + validators: ['0x23d549bf757a02a6f6068e9363196ecd958c974e'], + }, + + harmony: { + threshold: 1, + validators: ['0xd677803a67651974b1c264171b5d7ca8838db8d5'], + }, + holesky: { threshold: 1, validators: ['0x7ab28ad88bb45867137ea823af88e2cb02359c03'], // TODO @@ -381,6 +411,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + kaia: { + threshold: 1, + validators: ['0x9de0b3abb221d19719882fa4d61f769fdc2be9a4'], + }, + kroma: { threshold: 2, validators: [ @@ -513,6 +548,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + morph: { + threshold: 1, + validators: ['0x4884535f393151ec419add872100d352f71af380'], + }, + neutron: { threshold: 4, validators: [ @@ -556,6 +596,11 @@ export const defaultMultisigConfigs: ChainMap = { validators: ['0x03efe4d0632ee15685d7e8f46dea0a874304aa29'], }, + orderly: { + threshold: 1, + validators: ['0xec3dc91f9fa2ad35edf5842aa764d5573b778bb6'], + }, + osmosis: { threshold: 1, validators: ['0xea483af11c19fa41b16c31d1534c2a486a92bcac'], @@ -700,6 +745,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + snaxchain: { + threshold: 1, + validators: ['0x2c25829ae32a772d2a49f6c4b34f8b01fd03ef9e'], + }, + solanadevnet: { threshold: 2, validators: [ @@ -830,6 +880,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + zeronetwork: { + threshold: 1, + validators: ['0x1bd9e3f8a90ea1a13b0f2838a1858046368aad87'], + }, + zetachain: { threshold: 3, validators: [ @@ -850,6 +905,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + zksync: { + threshold: 1, + validators: ['0xadd1d39ce7a687e32255ac457cf99a6d8c5b5d1a'], + }, + zoramainnet: { threshold: 3, validators: [ diff --git a/typescript/sdk/src/core/HyperlaneCore.ts b/typescript/sdk/src/core/HyperlaneCore.ts index 93f232a44..8b1425d10 100644 --- a/typescript/sdk/src/core/HyperlaneCore.ts +++ b/typescript/sdk/src/core/HyperlaneCore.ts @@ -42,6 +42,10 @@ import { CoreFactories, coreFactories } from './contracts.js'; import { DispatchEvent } from './events.js'; import { DispatchedMessage } from './types.js'; +// If no metadata is provided, ensure we provide a default of 0x0001. +// We set to 0x0001 instead of 0x0 to ensure it does not break on zksync. +const DEFAULT_METADATA = '0x0001'; + export class HyperlaneCore extends HyperlaneApp { static fromAddressesMap( addressesMap: HyperlaneAddressesMap, @@ -94,7 +98,7 @@ export class HyperlaneCore extends HyperlaneApp { destinationId, recipient, body, - metadata || '0x', + metadata || DEFAULT_METADATA, hook || ethers.constants.AddressZero, ); }; @@ -159,7 +163,7 @@ export class HyperlaneCore extends HyperlaneApp { destinationDomain, recipientBytes32, body, - metadata || '0x', + metadata || DEFAULT_METADATA, hook || ethers.constants.AddressZero, ] as const; From 8ff194dc47ae38d80ea0919a92072d0803cabf24 Mon Sep 17 00:00:00 2001 From: Mantas-M <120508669+Mantas-M@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:34:33 +0000 Subject: [PATCH 212/224] feat: Cosmos RPC client supporting fallback rpcs (#4752) ### Description Added fallback functionality to the Cosmos RPC client ### Drive-by changes N/A ### Related issues - Fixes #3425 ### Backward compatibility Yes ### Testing Unit tests already in place, no additional added, as the generic CosmosFallbackProvider which is used is already tested --- .../src/providers/cosmos/provider.rs | 28 ++++++++-- .../src/providers/grpc/tests.rs | 2 +- .../src/providers/rpc/client.rs | 37 +++++++++---- .../src/providers/rpc/provider.rs | 55 +++++++++++++------ .../hyperlane-cosmos/src/trait_builder.rs | 14 ++--- .../main/chains/hyperlane-cosmos/src/types.rs | 3 +- .../src/settings/parser/connection_parser.rs | 2 +- 7 files changed, 96 insertions(+), 45 deletions(-) diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs index e718df610..2ab0388be 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider.rs @@ -6,6 +6,7 @@ use cosmrs::crypto::PublicKey; use cosmrs::proto::traits::Message; use cosmrs::tx::{MessageExt, SequenceNumber, SignerInfo, SignerPublicKey}; use cosmrs::{proto, AccountId, Any, Coin, Tx}; +use hyperlane_core::rpc_clients::FallbackProvider; use itertools::{any, cloned, Itertools}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; @@ -25,6 +26,7 @@ use hyperlane_core::{ use crate::grpc::{WasmGrpcProvider, WasmProvider}; use crate::providers::cosmos::provider::parse::PacketData; use crate::providers::rpc::CosmosRpcClient; +use crate::rpc_clients::CosmosFallbackProvider; use crate::{ ConnectionConf, CosmosAccountId, CosmosAddress, CosmosAmount, HyperlaneCosmosError, Signer, }; @@ -43,7 +45,7 @@ pub struct CosmosProvider { domain: HyperlaneDomain, connection_conf: ConnectionConf, grpc_provider: WasmGrpcProvider, - rpc_client: CosmosRpcClient, + rpc_client: CosmosFallbackProvider, } impl CosmosProvider { @@ -62,13 +64,21 @@ impl CosmosProvider { locator, signer, )?; - let rpc_client = CosmosRpcClient::new(&conf)?; + + let providers = conf + .get_rpc_urls() + .iter() + .map(CosmosRpcClient::new) + .collect::, _>>()?; + let provider = CosmosFallbackProvider::new( + FallbackProvider::builder().add_providers(providers).build(), + ); Ok(Self { domain, connection_conf: conf, grpc_provider, - rpc_client, + rpc_client: provider, }) } @@ -362,7 +372,10 @@ impl HyperlaneChain for CosmosProvider { #[async_trait] impl HyperlaneProvider for CosmosProvider { async fn get_block_by_height(&self, height: u64) -> ChainResult { - let response = self.rpc_client.get_block(height as u32).await?; + let response = self + .rpc_client + .call(|provider| Box::pin(async move { provider.get_block(height as u32).await })) + .await?; let block = response.block; let block_height = block.header.height.value(); @@ -392,7 +405,12 @@ impl HyperlaneProvider for CosmosProvider { let tendermint_hash = Hash::from_bytes(Algorithm::Sha256, hash.as_bytes()) .expect("transaction hash should be of correct size"); - let response = self.rpc_client.get_tx_by_hash(tendermint_hash).await?; + let response = self + .rpc_client + .call(|provider| { + Box::pin(async move { provider.get_tx_by_hash(tendermint_hash).await }) + }) + .await?; let received_hash = H256::from_slice(response.hash.as_bytes()); diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs index 2f5ca4abf..392ab713d 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/grpc/tests.rs @@ -54,7 +54,7 @@ fn provider(address: &str) -> WasmGrpcProvider { domain.clone(), ConnectionConf::new( vec![Url::parse("http://grpc-kralum.neutron-1.neutron.org:80").unwrap()], - "https://rpc-kralum.neutron-1.neutron.org".to_owned(), + vec![Url::parse("https://rpc-kralum.neutron-1.neutron.org").unwrap()], "neutron-1".to_owned(), "neutron".to_owned(), "untrn".to_owned(), diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs index f3c3930b1..102c04fac 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/client.rs @@ -1,10 +1,13 @@ use cosmrs::proto::tendermint::blocksync::BlockResponse; +use hyperlane_core::rpc_clients::BlockNumberGetter; use tendermint::Hash; use tendermint_rpc::client::CompatMode; use tendermint_rpc::endpoint::{block, block_by_hash, block_results, tx}; -use tendermint_rpc::{Client, HttpClient}; +use tendermint_rpc::{Client, HttpClient, HttpClientUrl, Url as TendermintUrl}; -use hyperlane_core::ChainResult; +use hyperlane_core::{ChainCommunicationError, ChainResult}; +use tonic::async_trait; +use url::Url; use crate::{ConnectionConf, HyperlaneCosmosError}; @@ -16,16 +19,17 @@ pub struct CosmosRpcClient { impl CosmosRpcClient { /// Create new `CosmosRpcClient` - pub fn new(conf: &ConnectionConf) -> ChainResult { - let client = HttpClient::builder( - conf.get_rpc_url() - .parse() - .map_err(Into::::into)?, - ) - // Consider supporting different compatibility modes. - .compat_mode(CompatMode::latest()) - .build() - .map_err(Into::::into)?; + pub fn new(url: &Url) -> ChainResult { + let tendermint_url = tendermint_rpc::Url::try_from(url.to_owned()) + .map_err(Into::::into)?; + let url = tendermint_rpc::HttpClientUrl::try_from(tendermint_url) + .map_err(Into::::into)?; + + let client = HttpClient::builder(url) + // Consider supporting different compatibility modes. + .compat_mode(CompatMode::latest()) + .build() + .map_err(Into::::into)?; Ok(Self { client }) } @@ -75,3 +79,12 @@ impl CosmosRpcClient { .map_err(Into::::into)?) } } + +#[async_trait] +impl BlockNumberGetter for CosmosRpcClient { + async fn get_block_number(&self) -> Result { + self.get_latest_block() + .await + .map(|block| block.block.header.height.value()) + } +} diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs index 20b6ac714..599a75116 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/rpc/provider.rs @@ -4,13 +4,14 @@ use async_trait::async_trait; use cosmrs::cosmwasm::MsgExecuteContract; use cosmrs::rpc::client::Client; use futures::StreamExt; +use hyperlane_core::rpc_clients::{BlockNumberGetter, FallbackProvider}; use sha256::digest; use tendermint::abci::{Event, EventAttribute}; use tendermint::hash::Algorithm; use tendermint::Hash; use tendermint_rpc::client::CompatMode; use tendermint_rpc::endpoint::block::Response as BlockResponse; -use tendermint_rpc::endpoint::block_results::Response as BlockResultsResponse; +use tendermint_rpc::endpoint::block_results::{self, Response as BlockResultsResponse}; use tendermint_rpc::endpoint::tx; use tendermint_rpc::HttpClient; use time::OffsetDateTime; @@ -21,6 +22,7 @@ use hyperlane_core::{ }; use crate::rpc::CosmosRpcClient; +use crate::rpc_clients::CosmosFallbackProvider; use crate::{ConnectionConf, CosmosAddress, CosmosProvider, HyperlaneCosmosError}; #[async_trait] @@ -79,7 +81,7 @@ pub struct CosmosWasmRpcProvider { contract_address: CosmosAddress, target_event_kind: String, reorg_period: u32, - rpc_client: CosmosRpcClient, + rpc_client: CosmosFallbackProvider, } impl CosmosWasmRpcProvider { @@ -92,7 +94,15 @@ impl CosmosWasmRpcProvider { event_type: String, reorg_period: u32, ) -> ChainResult { - let rpc_client = CosmosRpcClient::new(&conf)?; + let providers = conf + .get_rpc_urls() + .iter() + .map(CosmosRpcClient::new) + .collect::, _>>()?; + let mut builder = FallbackProvider::builder(); + builder = builder.add_providers(providers); + let fallback_provider = builder.build(); + let provider = CosmosFallbackProvider::new(fallback_provider); Ok(Self { domain: locator.domain.clone(), @@ -103,9 +113,15 @@ impl CosmosWasmRpcProvider { )?, target_event_kind: format!("{}-{}", Self::WASM_TYPE, event_type), reorg_period, - rpc_client, + rpc_client: provider, }) } + + async fn get_block(&self, height: u32) -> ChainResult { + self.rpc_client + .call(|provider| Box::pin(async move { provider.get_block(height).await })) + .await + } } impl CosmosWasmRpcProvider { @@ -222,7 +238,10 @@ impl WasmRpcProvider for CosmosWasmRpcProvider { #[instrument(err, skip(self))] #[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue async fn get_finalized_block_number(&self) -> ChainResult { - let latest_block = self.rpc_client.get_latest_block().await?; + let latest_block = self + .rpc_client + .call(|provider| Box::pin(async move { provider.get_latest_block().await })) + .await?; let latest_height: u32 = latest_block .block .header @@ -244,15 +263,16 @@ impl WasmRpcProvider for CosmosWasmRpcProvider { where T: Send + Sync + PartialEq + Debug + 'static, { - debug!(?block_number, cursor_label, domain=?self.domain, "Getting logs in block"); - // The two calls below could be made in parallel, but on cosmos rate limiting is a bigger problem // than indexing latency, so we do them sequentially. - let block = self.rpc_client.get_block(block_number).await?; - + let block = self.get_block(block_number).await?; debug!(?block_number, block_hash = ?block.block_id.hash, cursor_label, domain=?self.domain, "Getting logs in block with hash"); - - let block_results = self.rpc_client.get_block_results(block_number).await?; + let block_results = self + .rpc_client + .call(|provider| { + Box::pin(async move { provider.get_block_results(block_number).await }) + }) + .await?; Ok(self.handle_txs(block, block_results, parser, cursor_label)) } @@ -268,17 +288,16 @@ impl WasmRpcProvider for CosmosWasmRpcProvider { where T: Send + Sync + PartialEq + Debug + 'static, { - debug!(?hash, cursor_label, domain=?self.domain, "Getting logs in transaction"); - - let tx = self.rpc_client.get_tx_by_hash(hash).await?; - + let tx = self + .rpc_client + .call(|provider| Box::pin(async move { provider.get_tx_by_hash(hash).await })) + .await?; let block_number = tx.height.value() as u32; - let block = self.rpc_client.get_block(block_number).await?; + let block = self.get_block(block_number).await?; + let block_hash = H256::from_slice(block.block_id.hash.as_bytes()); debug!(?block_number, block_hash = ?block.block_id.hash, cursor_label, domain=?self.domain, "Getting logs in transaction: block info"); - let block_hash = H256::from_slice(block.block_id.hash.as_bytes()); - Ok(self.handle_tx(tx, block_hash, parser).collect()) } } diff --git a/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs b/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs index c48c3611d..c96d73c47 100644 --- a/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs +++ b/rust/main/chains/hyperlane-cosmos/src/trait_builder.rs @@ -8,10 +8,10 @@ use hyperlane_core::{config::OperationBatchConfig, ChainCommunicationError, Fixe /// Cosmos connection configuration #[derive(Debug, Clone)] pub struct ConnectionConf { - /// The GRPC url to connect to + /// The GRPC urls to connect to grpc_urls: Vec, /// The RPC url to connect to - rpc_url: String, + rpc_urls: Vec, /// The chain ID chain_id: String, /// The human readable address prefix for the chains using bech32. @@ -95,9 +95,9 @@ impl ConnectionConf { self.grpc_urls.clone() } - /// Get the RPC url - pub fn get_rpc_url(&self) -> String { - self.rpc_url.clone() + /// Get the RPC urls + pub fn get_rpc_urls(&self) -> Vec { + self.rpc_urls.clone() } /// Get the chain ID @@ -134,7 +134,7 @@ impl ConnectionConf { #[allow(clippy::too_many_arguments)] pub fn new( grpc_urls: Vec, - rpc_url: String, + rpc_urls: Vec, chain_id: String, bech32_prefix: String, canonical_asset: String, @@ -145,7 +145,7 @@ impl ConnectionConf { ) -> Self { Self { grpc_urls, - rpc_url, + rpc_urls, chain_id, bech32_prefix, canonical_asset, diff --git a/rust/main/chains/hyperlane-cosmos/src/types.rs b/rust/main/chains/hyperlane-cosmos/src/types.rs index aa5a95465..bba61fb01 100644 --- a/rust/main/chains/hyperlane-cosmos/src/types.rs +++ b/rust/main/chains/hyperlane-cosmos/src/types.rs @@ -1,5 +1,6 @@ -use cosmrs::proto::cosmos::base::abci::v1beta1::TxResponse; +use cosmrs::proto::{cosmos::base::abci::v1beta1::TxResponse, tendermint::Error}; use hyperlane_core::{ChainResult, ModuleType, TxOutcome, H256, U256}; +use url::Url; pub struct IsmType(pub hyperlane_cosmwasm_interface::ism::IsmType); diff --git a/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs b/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs index 4a435444d..67edcfbc5 100644 --- a/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs +++ b/rust/main/hyperlane-base/src/settings/parser/connection_parser.rs @@ -162,7 +162,7 @@ pub fn build_cosmos_connection_conf( } else { Some(ChainConnectionConf::Cosmos(h_cosmos::ConnectionConf::new( grpcs, - rpcs.first().unwrap().to_string(), + rpcs.to_owned(), chain_id.unwrap().to_string(), prefix.unwrap().to_string(), canonical_asset.unwrap(), From f438d442a5ad06bd76c0d5d8f23d65c7f1437db4 Mon Sep 17 00:00:00 2001 From: Jason Guo <33064781+Xaroz@users.noreply.github.com> Date: Tue, 29 Oct 2024 11:36:01 -0400 Subject: [PATCH 213/224] feat: widget update for de-duplication (#4771) ### Description Update widgets with new components from the hyperlane explorer and warp UI. These will be used to replace the current components from both mentioned repo ### Drive-by changes None ### Backward compatibility Not exactly, Spinner and WideChevron were renamed to SpinnerIcon and WideChevronIcon, these must be updated accordingly ### Testing Manual and Visual Testing with storybook --- .changeset/plenty-pens-peel.md | 11 ++ typescript/widgets/src/animations/Fade.tsx | 28 +++++ .../widgets/src/chains/ChainDetailsMenu.tsx | 4 +- .../widgets/src/components/DatetimeField.tsx | 36 +++++++ .../widgets/src/components/SelectField.tsx | 45 ++++++++ typescript/widgets/src/icons/Arrow.tsx | 10 +- typescript/widgets/src/icons/Discord.tsx | 25 +++++ typescript/widgets/src/icons/Docs.tsx | 18 ++++ typescript/widgets/src/icons/Github.tsx | 18 ++++ typescript/widgets/src/icons/History.tsx | 18 ++++ typescript/widgets/src/icons/LinkedIn.tsx | 16 +++ typescript/widgets/src/icons/Medium.tsx | 24 +++++ typescript/widgets/src/icons/Spinner.tsx | 2 +- typescript/widgets/src/icons/Twitter.tsx | 18 ++++ typescript/widgets/src/icons/Wallet.tsx | 18 ++++ typescript/widgets/src/icons/Web.tsx | 68 ++++++++++++ typescript/widgets/src/icons/WideChevron.tsx | 2 +- typescript/widgets/src/index.ts | 21 +++- .../widgets/src/messages/MessageTimeline.tsx | 11 +- .../widgets/src/stories/Fade.stories.tsx | 21 ++++ .../widgets/src/stories/IconList.stories.tsx | 102 ++++++++++++++++++ .../src/stories/WideChevron.stories.tsx | 12 +-- 22 files changed, 508 insertions(+), 20 deletions(-) create mode 100644 .changeset/plenty-pens-peel.md create mode 100644 typescript/widgets/src/animations/Fade.tsx create mode 100644 typescript/widgets/src/components/DatetimeField.tsx create mode 100644 typescript/widgets/src/components/SelectField.tsx create mode 100644 typescript/widgets/src/icons/Discord.tsx create mode 100644 typescript/widgets/src/icons/Docs.tsx create mode 100644 typescript/widgets/src/icons/Github.tsx create mode 100644 typescript/widgets/src/icons/History.tsx create mode 100644 typescript/widgets/src/icons/LinkedIn.tsx create mode 100644 typescript/widgets/src/icons/Medium.tsx create mode 100644 typescript/widgets/src/icons/Twitter.tsx create mode 100644 typescript/widgets/src/icons/Wallet.tsx create mode 100644 typescript/widgets/src/icons/Web.tsx create mode 100644 typescript/widgets/src/stories/Fade.stories.tsx create mode 100644 typescript/widgets/src/stories/IconList.stories.tsx diff --git a/.changeset/plenty-pens-peel.md b/.changeset/plenty-pens-peel.md new file mode 100644 index 000000000..9b69b8003 --- /dev/null +++ b/.changeset/plenty-pens-peel.md @@ -0,0 +1,11 @@ +--- +'@hyperlane-xyz/widgets': minor +--- + +Update widgets with components from explorer and warp ui + +- Add icons: Discord, Docs, Github, History, LinkedIn, Medium, Twitter, Wallet and Web +- Add animation component: Fade component +- Add components: DatetimeField and SelectField +- New stories: IconList and Fade +- Add "Icon" suffix for icons that did not have it diff --git a/typescript/widgets/src/animations/Fade.tsx b/typescript/widgets/src/animations/Fade.tsx new file mode 100644 index 000000000..5e98e53cf --- /dev/null +++ b/typescript/widgets/src/animations/Fade.tsx @@ -0,0 +1,28 @@ +import React, { PropsWithChildren, useEffect, useState } from 'react'; + +export function Fade(props: PropsWithChildren<{ show: boolean }>) { + const { show, children } = props; + const [render, setRender] = useState(show); + + useEffect(() => { + if (show) setRender(true); + }, [show]); + + const onAnimationEnd = () => { + if (!show) setRender(false); + }; + + return render ? ( +
+ {children} +
+ ) : null; +} diff --git a/typescript/widgets/src/chains/ChainDetailsMenu.tsx b/typescript/widgets/src/chains/ChainDetailsMenu.tsx index 15478fbba..7c175d0d8 100644 --- a/typescript/widgets/src/chains/ChainDetailsMenu.tsx +++ b/typescript/widgets/src/chains/ChainDetailsMenu.tsx @@ -30,7 +30,7 @@ import { CheckmarkIcon } from '../icons/Checkmark.js'; import { ChevronIcon } from '../icons/Chevron.js'; import { Circle } from '../icons/Circle.js'; import { PlusCircleIcon } from '../icons/PlusCircle.js'; -import { Spinner } from '../icons/Spinner.js'; +import { SpinnerIcon } from '../icons/Spinner.js'; import { XIcon } from '../icons/X.js'; import { useConnectionHealthTest } from '../utils/useChainConnectionTest.js'; @@ -450,7 +450,7 @@ function ConnectionRow({ return (
{isNullish(isHealthy) && type == ChainConnectionType.RPC && ( - + )} {isNullish(isHealthy) && type == ChainConnectionType.Explorer && ( diff --git a/typescript/widgets/src/components/DatetimeField.tsx b/typescript/widgets/src/components/DatetimeField.tsx new file mode 100644 index 000000000..cc0406038 --- /dev/null +++ b/typescript/widgets/src/components/DatetimeField.tsx @@ -0,0 +1,36 @@ +import React, { ChangeEvent } from 'react'; + +interface Props { + className?: string; + timestamp: number | null; + onChange: (t: number | null) => void; + name?: string; +} + +export function DatetimeField({ className, timestamp, onChange, name }: Props) { + const handleChange = (e: ChangeEvent) => { + if (!e.target['validity'].valid) { + onChange(null); + } else { + const datetime = e.target['value'] + ':00Z'; + const newTimestamp = new Date(datetime).getTime(); + onChange(newTimestamp); + } + }; + + return ( + + ); +} + +function toShortIsoString(timestamp: number | null) { + if (!timestamp) return ''; + // Trim milliseconds and timezone to match input field format + return new Date(timestamp).toISOString().split('.')[0]; +} diff --git a/typescript/widgets/src/components/SelectField.tsx b/typescript/widgets/src/components/SelectField.tsx new file mode 100644 index 000000000..11ed0e1d0 --- /dev/null +++ b/typescript/widgets/src/components/SelectField.tsx @@ -0,0 +1,45 @@ +import React, { ChangeEvent } from 'react'; + +export type SelectOption = { + display: string; + value: string; +}; + +type Props = React.DetailedHTMLProps< + React.SelectHTMLAttributes, + HTMLSelectElement +> & { + options: Array; + value: string; + onValueSelect: (value: string) => void; + classes?: string; +}; + +export function SelectField({ + options, + value, + onValueSelect, + classes, + ...passThruProps +}: Props) { + const onChangeSelect = (event: ChangeEvent) => { + onValueSelect(event?.target?.value || ''); + }; + + return ( + + ); +} diff --git a/typescript/widgets/src/icons/Arrow.tsx b/typescript/widgets/src/icons/Arrow.tsx index 3d066af9c..d4061a6f6 100644 --- a/typescript/widgets/src/icons/Arrow.tsx +++ b/typescript/widgets/src/icons/Arrow.tsx @@ -1,12 +1,14 @@ -import React, { SVGProps, memo } from 'react'; +import React, { memo } from 'react'; import { ColorPalette } from '../color.js'; -type Props = SVGProps & { +import { DefaultIconProps } from './types.js'; + +type Props = DefaultIconProps & { direction: 'n' | 'e' | 's' | 'w'; }; -function _ArrowIcon({ fill, className, direction, ...rest }: Props) { +function _ArrowIcon({ color, className, direction, ...rest }: Props) { let directionClass; switch (direction) { case 'n': @@ -36,7 +38,7 @@ function _ArrowIcon({ fill, className, direction, ...rest }: Props) { ); diff --git a/typescript/widgets/src/icons/Discord.tsx b/typescript/widgets/src/icons/Discord.tsx new file mode 100644 index 000000000..28a3d93f1 --- /dev/null +++ b/typescript/widgets/src/icons/Discord.tsx @@ -0,0 +1,25 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _Discord({ color, ...rest }: DefaultIconProps) { + return ( + + + + + + + + + + + ); +} + +export const DiscordIcon = memo(_Discord); diff --git a/typescript/widgets/src/icons/Docs.tsx b/typescript/widgets/src/icons/Docs.tsx new file mode 100644 index 000000000..656c79c0e --- /dev/null +++ b/typescript/widgets/src/icons/Docs.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _DocsIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const DocsIcon = memo(_DocsIcon); diff --git a/typescript/widgets/src/icons/Github.tsx b/typescript/widgets/src/icons/Github.tsx new file mode 100644 index 000000000..5d41670fb --- /dev/null +++ b/typescript/widgets/src/icons/Github.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _Github({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const GithubIcon = memo(_Github); diff --git a/typescript/widgets/src/icons/History.tsx b/typescript/widgets/src/icons/History.tsx new file mode 100644 index 000000000..f6e185296 --- /dev/null +++ b/typescript/widgets/src/icons/History.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _HistoryIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const HistoryIcon = memo(_HistoryIcon); diff --git a/typescript/widgets/src/icons/LinkedIn.tsx b/typescript/widgets/src/icons/LinkedIn.tsx new file mode 100644 index 000000000..88e042c6d --- /dev/null +++ b/typescript/widgets/src/icons/LinkedIn.tsx @@ -0,0 +1,16 @@ +import React, { memo } from 'react'; + +import { DefaultIconProps } from './types.js'; + +function _Linkedin({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const LinkedInIcon = memo(_Linkedin); diff --git a/typescript/widgets/src/icons/Medium.tsx b/typescript/widgets/src/icons/Medium.tsx new file mode 100644 index 000000000..cba9c92d3 --- /dev/null +++ b/typescript/widgets/src/icons/Medium.tsx @@ -0,0 +1,24 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _Medium({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const MediumIcon = memo(_Medium); diff --git a/typescript/widgets/src/icons/Spinner.tsx b/typescript/widgets/src/icons/Spinner.tsx index 8cb1e8c45..71501341f 100644 --- a/typescript/widgets/src/icons/Spinner.tsx +++ b/typescript/widgets/src/icons/Spinner.tsx @@ -30,4 +30,4 @@ function _Spinner({ color, className, ...rest }: DefaultIconProps) { ); } -export const Spinner = memo(_Spinner); +export const SpinnerIcon = memo(_Spinner); diff --git a/typescript/widgets/src/icons/Twitter.tsx b/typescript/widgets/src/icons/Twitter.tsx new file mode 100644 index 000000000..feffaa495 --- /dev/null +++ b/typescript/widgets/src/icons/Twitter.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _Twitter({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const TwitterIcon = memo(_Twitter); diff --git a/typescript/widgets/src/icons/Wallet.tsx b/typescript/widgets/src/icons/Wallet.tsx new file mode 100644 index 000000000..7216791cc --- /dev/null +++ b/typescript/widgets/src/icons/Wallet.tsx @@ -0,0 +1,18 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _WalletIcon({ color, ...rest }: DefaultIconProps) { + return ( + + + + ); +} + +export const WalletIcon = memo(_WalletIcon); diff --git a/typescript/widgets/src/icons/Web.tsx b/typescript/widgets/src/icons/Web.tsx new file mode 100644 index 000000000..8915ed026 --- /dev/null +++ b/typescript/widgets/src/icons/Web.tsx @@ -0,0 +1,68 @@ +import React, { memo } from 'react'; + +import { ColorPalette } from '../color.js'; + +import { DefaultIconProps } from './types.js'; + +function _Web({ color = ColorPalette.Black, ...rest }: DefaultIconProps) { + return ( + + + + + + + + + + + + + + + + ); +} + +export const WebIcon = memo(_Web); diff --git a/typescript/widgets/src/icons/WideChevron.tsx b/typescript/widgets/src/icons/WideChevron.tsx index 83ecb8323..21d15238b 100644 --- a/typescript/widgets/src/icons/WideChevron.tsx +++ b/typescript/widgets/src/icons/WideChevron.tsx @@ -69,4 +69,4 @@ function _WideChevron({ } } -export const WideChevron = memo(_WideChevron); +export const WideChevronIcon = memo(_WideChevron); diff --git a/typescript/widgets/src/index.ts b/typescript/widgets/src/index.ts index 0a25bc9a5..2bb43315c 100644 --- a/typescript/widgets/src/index.ts +++ b/typescript/widgets/src/index.ts @@ -1,3 +1,4 @@ +export { Fade } from './animations/Fade.js'; export { ChainDetailsMenu, type ChainDetailsMenuProps, @@ -8,13 +9,16 @@ export { type ChainSearchMenuProps, } from './chains/ChainSearchMenu.js'; export { ColorPalette, seedToBgColor } from './color.js'; +export { Button } from './components/Button.js'; export { CopyButton } from './components/CopyButton.js'; +export { DatetimeField } from './components/DatetimeField.js'; export { IconButton } from './components/IconButton.js'; export { LinkButton } from './components/LinkButton.js'; export { SegmentedControl } from './components/SegmentedControl.js'; +export { SelectField, type SelectOption } from './components/SelectField.js'; export { TextInput } from './components/TextInput.js'; export { Tooltip } from './components/Tooltip.js'; -export * from './consts.js'; +export { HYPERLANE_EXPLORER_API_URL } from './consts.js'; export { AirplaneIcon } from './icons/Airplane.js'; export { ArrowIcon } from './icons/Arrow.js'; export { BoxArrowIcon } from './icons/BoxArrow.js'; @@ -22,20 +26,31 @@ export { CheckmarkIcon } from './icons/Checkmark.js'; export { ChevronIcon } from './icons/Chevron.js'; export { Circle } from './icons/Circle.js'; export { CopyIcon } from './icons/Copy.js'; +export { DiscordIcon } from './icons/Discord.js'; +export { DocsIcon } from './icons/Docs.js'; export { EnvelopeIcon } from './icons/Envelope.js'; export { FilterIcon } from './icons/Filter.js'; export { FunnelIcon } from './icons/Funnel.js'; export { GearIcon } from './icons/Gear.js'; +export { GithubIcon } from './icons/Github.js'; +export { HistoryIcon } from './icons/History.js'; +export { LinkedInIcon } from './icons/LinkedIn.js'; export { LockIcon } from './icons/Lock.js'; +export { MediumIcon } from './icons/Medium.js'; +export { PencilIcon } from './icons/Pencil.js'; export { PlusIcon } from './icons/Plus.js'; export { PlusCircleIcon } from './icons/PlusCircle.js'; export { QuestionMarkIcon } from './icons/QuestionMark.js'; export { SearchIcon } from './icons/Search.js'; export { ShieldIcon } from './icons/Shield.js'; -export { Spinner } from './icons/Spinner.js'; +export { SpinnerIcon } from './icons/Spinner.js'; +export { TwitterIcon } from './icons/Twitter.js'; export { UpDownArrowsIcon } from './icons/UpDownArrows.js'; -export { WideChevron } from './icons/WideChevron.js'; +export { WalletIcon } from './icons/Wallet.js'; +export { WebIcon } from './icons/Web.js'; +export { WideChevronIcon } from './icons/WideChevron.js'; export { XIcon } from './icons/X.js'; +export { type DefaultIconProps } from './icons/types.js'; export { DropdownMenu, type DropdownMenuProps } from './layout/DropdownMenu.js'; export { Modal, useModal, type ModalProps } from './layout/Modal.js'; export { Popover, type PopoverProps } from './layout/Popover.js'; diff --git a/typescript/widgets/src/messages/MessageTimeline.tsx b/typescript/widgets/src/messages/MessageTimeline.tsx index 3bf153ca5..74a50b976 100644 --- a/typescript/widgets/src/messages/MessageTimeline.tsx +++ b/typescript/widgets/src/messages/MessageTimeline.tsx @@ -5,7 +5,7 @@ import { AirplaneIcon } from '../icons/Airplane.js'; import { EnvelopeIcon } from '../icons/Envelope.js'; import { LockIcon } from '../icons/Lock.js'; import { ShieldIcon } from '../icons/Shield.js'; -import { WideChevron } from '../icons/WideChevron.js'; +import { WideChevronIcon } from '../icons/WideChevron.js'; import { MessageStatus, MessageStage as Stage, StageTimings } from './types.js'; @@ -157,7 +157,12 @@ function StageIcon({ Icon, size }: { Icon: any; size?: number }) { function ChevronWhite() { return (
- +
); } @@ -165,7 +170,7 @@ function ChevronWhite() { function ChevronBlue() { return (
- +
); } diff --git a/typescript/widgets/src/stories/Fade.stories.tsx b/typescript/widgets/src/stories/Fade.stories.tsx new file mode 100644 index 000000000..7c6a582b5 --- /dev/null +++ b/typescript/widgets/src/stories/Fade.stories.tsx @@ -0,0 +1,21 @@ +import { Meta, StoryObj } from '@storybook/react'; +import React from 'react'; + +import { Fade } from '../animations/Fade'; + +function MyFadeAnimation({ show }: { show: boolean }) { + return ( + +
Hello Fade
+
+ ); +} + +const meta = { + title: 'Fade', + component: MyFadeAnimation, +} satisfies Meta; +export default meta; +type Story = StoryObj; + +export const BaseFadeAnimation = { args: { show: false } } satisfies Story; diff --git a/typescript/widgets/src/stories/IconList.stories.tsx b/typescript/widgets/src/stories/IconList.stories.tsx new file mode 100644 index 000000000..48570f106 --- /dev/null +++ b/typescript/widgets/src/stories/IconList.stories.tsx @@ -0,0 +1,102 @@ +import { Meta, StoryObj } from '@storybook/react'; +import React from 'react'; + +import * as Hyperlane from '../index'; + +interface StoryIconProps { + width?: number; + height?: number; + color?: string; + direction?: 'n' | 'e' | 's' | 'w'; + rounded?: boolean; +} + +const iconList = Object.entries(Hyperlane) + .filter(([name]) => name.includes('Icon') && !name.includes('IconButton')) + .map(([_, Component]) => Component as React.ComponentType); + +function IconList({ + width, + height, + color, + direction, + bgColorSeed, + roundedWideChevron, +}: { + width: number; + height: number; + color: string; + direction: 'n' | 'e' | 's' | 'w'; + bgColorSeed: number | undefined; + roundedWideChevron: boolean; +}) { + return ( + <> +
+ {iconList.map((Icon) => ( + + {Icon.displayName} + + + ))} + + Circle + + +
+ + ); +} + +function IconContainer({ children }: { children: React.ReactNode }) { + return ( +
+ {children} +
+ ); +} + +const meta = { + title: 'Icon List', + component: IconList, + argTypes: { + direction: { + options: ['n', 'e', 's', 'w'], + control: { type: 'select' }, + }, + }, +} satisfies Meta; +export default meta; +type Story = StoryObj; + +export const DefaultIconList = { + args: { + width: 24, + height: 24, + color: Hyperlane.ColorPalette.Black, + direction: 's', + bgColorSeed: 0, + roundedWideChevron: false, + }, +} satisfies Story; diff --git a/typescript/widgets/src/stories/WideChevron.stories.tsx b/typescript/widgets/src/stories/WideChevron.stories.tsx index cb81ae5c3..0738b5451 100644 --- a/typescript/widgets/src/stories/WideChevron.stories.tsx +++ b/typescript/widgets/src/stories/WideChevron.stories.tsx @@ -1,16 +1,16 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { Meta, StoryFn } from '@storybook/react'; import React from 'react'; import { ColorPalette } from '../color.js'; -import { WideChevron } from '../icons/WideChevron.js'; +import { WideChevronIcon } from '../icons/WideChevron.js'; export default { title: 'WideChevron', - component: WideChevron, -} as ComponentMeta; + component: WideChevronIcon, +} as Meta; -const Template: ComponentStory = (args) => ( - +const Template: StoryFn = (args) => ( + ); export const BlueEastRounded = Template.bind({}); From 83a1567a0ad6a5cc227af650ff9bc5c7d4c92cd1 Mon Sep 17 00:00:00 2001 From: Tien Dao <15717476+tiendn@users.noreply.github.com> Date: Tue, 29 Oct 2024 23:47:28 +0700 Subject: [PATCH 214/224] test: append-more-multisigmIsm-test (#4769) ### Description Append more test for `multisigIsm.ts` ### Drive-by changes ### Related issues ### Backward compatibility ### Testing Add 2 test cases: - has a valid number of validators for each threshold - has valid EVM addresses for each validator --- typescript/sdk/src/consts/multisigIsm.test.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/typescript/sdk/src/consts/multisigIsm.test.ts b/typescript/sdk/src/consts/multisigIsm.test.ts index 58b84c7cb..53f93dc16 100644 --- a/typescript/sdk/src/consts/multisigIsm.test.ts +++ b/typescript/sdk/src/consts/multisigIsm.test.ts @@ -1,5 +1,7 @@ import { expect } from 'chai'; +import { isAddress } from '@hyperlane-xyz/utils'; + import { defaultMultisigConfigs } from './multisigIsm.js'; describe('MultisigIsm', () => { @@ -13,5 +15,25 @@ describe('MultisigIsm', () => { ); } }); + + it('has a valid number of validators for each threshold', async () => { + for (const [chain, config] of Object.entries(defaultMultisigConfigs)) { + expect(config.validators.length).to.be.greaterThanOrEqual( + config.threshold, + `Number of validators for ${chain} is less than the threshold, expected at least ${config.threshold}, got ${config.validators.length}`, + ); + } + }); + + it('has valid EVM addresses for each validator', async () => { + for (const [chain, config] of Object.entries(defaultMultisigConfigs)) { + for (const validator of config.validators) { + expect(isAddress(validator)).to.equal( + true, + `Validator address ${validator} for ${chain} is not a valid EVM address`, + ); + } + } + }); }); }); From fc3818d12af3c6672e4df9ccc9217c3184897a75 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Wed, 30 Oct 2024 11:14:07 +0000 Subject: [PATCH 215/224] feat: add taint & toleration to mainnet3 relayer node pool (#4780) ### Description See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ - In GKE, for the larger relayer node pool, added a taint: `NoSchedule`, label `component=relayer` - In our relayer workloads, they now have a toleration that matches that taint - As part of rollout, first did a NoExecute (evicting everything on the big nodes), then moved to NoSchedule (so that some other pods like daemonsets would still get onto these bigger nodes). I made sure the hyperlane and neutron context relayers have these tolerations ### Drive-by changes ### Related issues - Fixes https://github.com/hyperlane-xyz/issues/issues/1309 ### Backward compatibility ### Testing --- typescript/infra/src/agents/index.ts | 13 +++++++++++++ typescript/infra/src/config/agent/agent.ts | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/typescript/infra/src/agents/index.ts b/typescript/infra/src/agents/index.ts index ee0da5889..3f3f6469a 100644 --- a/typescript/infra/src/agents/index.ts +++ b/typescript/infra/src/agents/index.ts @@ -164,6 +164,19 @@ export class RelayerHelmManager extends OmniscientAgentHelmManager { signer: signers[name], })); + if (!values.tolerations) { + values.tolerations = []; + } + + // Relayer pods should only be scheduled on nodes with the component label set to relayer. + // NoSchedule was chosen so that some daemonsets (like the prometheus node exporter) would not be evicted. + values.tolerations.push({ + key: 'component', + operator: 'Equal', + value: 'relayer', + effect: 'NoSchedule', + }); + return values; } } diff --git a/typescript/infra/src/config/agent/agent.ts b/typescript/infra/src/config/agent/agent.ts index e9ff6f3e4..987a05f0e 100644 --- a/typescript/infra/src/config/agent/agent.ts +++ b/typescript/infra/src/config/agent/agent.ts @@ -36,6 +36,7 @@ export interface HelmRootAgentValues { image: HelmImageValues; hyperlane: HelmHyperlaneValues; nameOverride?: string; + tolerations?: KubernetesToleration[]; } // See rust/main/helm/values.yaml for the full list of options and their defaults. @@ -132,6 +133,13 @@ export interface KubernetesComputeResources { memory: string; } +export interface KubernetesToleration { + key: string; + operator: string; + value: string; + effect: string; +} + export class RootAgentConfigHelper implements AgentContextConfig { readonly rawConfig: RootAgentConfig; From cca032fb1879f1103fdd229933d8812e7a66a169 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:34:56 +0530 Subject: [PATCH 216/224] fix(contracts): assume no zero address for beneficiary address in `ProtocolFee` fuzz test (#4781) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- solidity/test/hooks/ProtocolFee.t.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/solidity/test/hooks/ProtocolFee.t.sol b/solidity/test/hooks/ProtocolFee.t.sol index bfd90f687..161d9e9c8 100644 --- a/solidity/test/hooks/ProtocolFee.t.sol +++ b/solidity/test/hooks/ProtocolFee.t.sol @@ -73,6 +73,7 @@ contract ProtocolFeeTest is Test { } function testSetBeneficiary(address beneficiary) public { + vm.assume(beneficiary != address(0)); vm.expectEmit(true, true, true, true); emit ProtocolFee.BeneficiarySet(beneficiary); fees.setBeneficiary(beneficiary); From fc82b30a2e4337a85ba712c5ab8075a8da8a4d35 Mon Sep 17 00:00:00 2001 From: Mantas-M <120508669+Mantas-M@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:17:13 +0000 Subject: [PATCH 217/224] feat: Refactor Relayer Retry Server (#4693) ### Description Refactor of the Relayer Retry Server to utilize matching lists. This allows for a single POST request to be able to retry a wide range of messages. Since a matching list is used it is now possible to retry messages depending on: - Message Id - Origin Domain - Destination Domain - Recipient Address - Sender Address ## Example Instead of the old request format ``` GET http://127.0.0.1:60843/message_retry?destination_domain=42 GET http://127.0.0.1:60843/message_retry?message_id=0x46910b1329ee53c86a023b322e9ca1c17e5f9f0bee789c77b0abced0a173d714 ``` The new one should be used ``` POST http://127.0.0.1:60843/message_retry ``` With a JSON body like so: ``` [{"messageid": "*", "origindomain": "*", "senderaddress": "*", "destinationdomain": "*", "recipientaddress": "*"}] ``` Retry params can be both specific values and wildcards. ### Drive-by changes - Moved `MockPendingOperation` to `hyperlane-test` - Moved certain test utils for the relayer server to `hyperlane-test` - Added functions to retrieve recipient and sender address from the `PendingOperation` - Added a `message_id` to the `MatchingList` struct to allow retries by message id - Removed `MessageRetryRequest` enum since it was no longer in use ### Related issues Fixes #3571 #4079 ### Backward compatibility Yes ### Testing Unit tests --- rust/main/agents/relayer/src/msg/op_queue.rs | 87 ++++-- .../agents/relayer/src/msg/op_submitter.rs | 4 +- .../agents/relayer/src/msg/pending_message.rs | 8 + rust/main/agents/relayer/src/relayer.rs | 4 +- .../relayer/src/server/list_messages.rs | 28 +- .../relayer/src/server/message_retry.rs | 280 +++++++++++------- rust/main/agents/relayer/src/server/mod.rs | 6 +- .../relayer/src/settings/matching_list.rs | 65 +++- .../src/traits/pending_operation.rs | 6 + 9 files changed, 352 insertions(+), 136 deletions(-) diff --git a/rust/main/agents/relayer/src/msg/op_queue.rs b/rust/main/agents/relayer/src/msg/op_queue.rs index d22e0c3c8..95025d391 100644 --- a/rust/main/agents/relayer/src/msg/op_queue.rs +++ b/rust/main/agents/relayer/src/msg/op_queue.rs @@ -6,7 +6,7 @@ use prometheus::{IntGauge, IntGaugeVec}; use tokio::sync::{broadcast::Receiver, Mutex}; use tracing::{debug, info, instrument}; -use crate::server::MessageRetryRequest; +use crate::settings::matching_list::MatchingList; pub type OperationPriorityQueue = Arc>>>; @@ -16,7 +16,7 @@ pub type OperationPriorityQueue = Arc>> pub struct OpQueue { metrics: IntGaugeVec, queue_metrics_label: String, - retry_rx: Arc>>, + retry_rx: Arc>>, #[new(default)] pub queue: OperationPriorityQueue, } @@ -84,9 +84,7 @@ impl OpQueue { let mut reprioritized_queue: BinaryHeap<_> = queue .drain() .map(|Reverse(mut op)| { - // Can check for equality here because of the PartialEq implementation for MessageRetryRequest, - // but can't use `contains` because the types are different - if message_retry_requests.iter().any(|r| r == op) { + if message_retry_requests.iter().any(|r| r.op_matches(&op)) { info!( operation = %op, queue_label = %self.queue_metrics_label, @@ -116,12 +114,14 @@ impl OpQueue { pub mod test { use super::*; use hyperlane_core::{ - HyperlaneDomain, HyperlaneMessage, KnownHyperlaneDomain, PendingOperationResult, + HyperlaneDomain, HyperlaneDomainProtocol, HyperlaneDomainTechnicalStack, + HyperlaneDomainType, HyperlaneMessage, KnownHyperlaneDomain, PendingOperationResult, TryBatchAs, TxOutcome, H256, U256, }; use serde::Serialize; use std::{ collections::VecDeque, + str::FromStr, time::{Duration, Instant}, }; use tokio::sync; @@ -129,6 +129,10 @@ pub mod test { #[derive(Debug, Clone, Serialize)] pub struct MockPendingOperation { id: H256, + sender_address: H256, + origin_domain_id: u32, + destination_domain_id: u32, + recipient_address: H256, seconds_to_next_attempt: u64, destination_domain: HyperlaneDomain, } @@ -138,12 +142,51 @@ pub mod test { Self { id: H256::random(), seconds_to_next_attempt, + destination_domain_id: destination_domain.id(), destination_domain, + sender_address: H256::random(), + recipient_address: H256::random(), + origin_domain_id: 0, } } - pub fn with_id(self, id: H256) -> Self { - Self { id, ..self } + pub fn with_message_data(message: HyperlaneMessage) -> Self { + Self { + id: message.id(), + sender_address: message.sender, + recipient_address: message.recipient, + origin_domain_id: message.origin, + destination_domain_id: message.destination, + seconds_to_next_attempt: 0, + destination_domain: HyperlaneDomain::Unknown { + domain_id: message.destination, + domain_name: "test".to_string(), + domain_type: HyperlaneDomainType::Unknown, + domain_protocol: HyperlaneDomainProtocol::Ethereum, + domain_technical_stack: HyperlaneDomainTechnicalStack::Other, + }, + } + } + + pub fn with_id(self, id: &str) -> Self { + Self { + id: H256::from_str(id).unwrap(), + ..self + } + } + + pub fn with_sender_address(self, sender_address: &str) -> Self { + Self { + sender_address: H256::from_str(sender_address).unwrap(), + ..self + } + } + + pub fn with_recipient_address(self, recipient_address: &str) -> Self { + Self { + recipient_address: H256::from_str(recipient_address).unwrap(), + ..self + } } } @@ -166,6 +209,20 @@ pub mod test { self.seconds_to_next_attempt = 0; } + fn sender_address(&self) -> &H256 { + &self.sender_address + } + + fn recipient_address(&self) -> &H256 { + &self.recipient_address + } + + fn get_metric(&self) -> Option> { + None + } + + fn set_metric(&mut self, _metric: Arc) {} + fn priority(&self) -> u32 { todo!() } @@ -179,7 +236,7 @@ pub mod test { } fn origin_domain_id(&self) -> u32 { - todo!() + self.origin_domain_id } fn destination_domain(&self) -> &HyperlaneDomain { @@ -238,12 +295,6 @@ pub mod test { fn set_retries(&mut self, _retries: u32) { todo!() } - - fn get_metric(&self) -> Option> { - None - } - - fn set_metric(&mut self, _metric: Arc) {} } pub fn dummy_metrics_and_label() -> (IntGaugeVec, String) { @@ -312,10 +363,10 @@ pub mod test { // Retry by message ids broadcaster - .send(MessageRetryRequest::MessageId(op_ids[1])) + .send(MatchingList::with_message_id(op_ids[1])) .unwrap(); broadcaster - .send(MessageRetryRequest::MessageId(op_ids[2])) + .send(MatchingList::with_message_id(op_ids[2])) .unwrap(); // Pop elements from queue 1 @@ -373,7 +424,7 @@ pub mod test { // Retry by domain broadcaster - .send(MessageRetryRequest::DestinationDomain( + .send(MatchingList::with_destination_domain( destination_domain_2.id(), )) .unwrap(); diff --git a/rust/main/agents/relayer/src/msg/op_submitter.rs b/rust/main/agents/relayer/src/msg/op_submitter.rs index f35a991c4..c1e295a24 100644 --- a/rust/main/agents/relayer/src/msg/op_submitter.rs +++ b/rust/main/agents/relayer/src/msg/op_submitter.rs @@ -32,7 +32,7 @@ use hyperlane_core::{ }; use crate::msg::pending_message::CONFIRM_DELAY; -use crate::server::MessageRetryRequest; +use crate::settings::matching_list::MatchingList; use super::op_queue::OpQueue; use super::op_queue::OperationPriorityQueue; @@ -105,7 +105,7 @@ impl SerialSubmitter { pub fn new( domain: HyperlaneDomain, rx: mpsc::UnboundedReceiver, - retry_op_transmitter: Sender, + retry_op_transmitter: Sender, metrics: SerialSubmitterMetrics, max_batch_size: u32, task_monitor: TaskMonitor, diff --git a/rust/main/agents/relayer/src/msg/pending_message.rs b/rust/main/agents/relayer/src/msg/pending_message.rs index 9d43595b5..cee00aed7 100644 --- a/rust/main/agents/relayer/src/msg/pending_message.rs +++ b/rust/main/agents/relayer/src/msg/pending_message.rs @@ -167,6 +167,14 @@ impl PendingOperation for PendingMessage { self.ctx.destination_mailbox.domain() } + fn sender_address(&self) -> &H256 { + &self.message.sender + } + + fn recipient_address(&self) -> &H256 { + &self.message.recipient + } + fn retrieve_status_from_db(&self) -> Option { match self.ctx.origin_db.retrieve_status_by_message_id(&self.id()) { Ok(status) => status, diff --git a/rust/main/agents/relayer/src/relayer.rs b/rust/main/agents/relayer/src/relayer.rs index d5077d678..975f37242 100644 --- a/rust/main/agents/relayer/src/relayer.rs +++ b/rust/main/agents/relayer/src/relayer.rs @@ -41,7 +41,7 @@ use crate::{ pending_message::{MessageContext, MessageSubmissionMetrics}, processor::{MessageProcessor, MessageProcessorMetrics}, }, - server::{self as relayer_server, MessageRetryRequest}, + server::{self as relayer_server}, settings::{matching_list::MatchingList, RelayerSettings}, }; use crate::{ @@ -311,7 +311,7 @@ impl BaseAgent for Relayer { })); tasks.push(console_server.instrument(info_span!("Tokio console server"))); } - let sender = BroadcastSender::::new(ENDPOINT_MESSAGES_QUEUE_SIZE); + let sender = BroadcastSender::::new(ENDPOINT_MESSAGES_QUEUE_SIZE); // send channels by destination chain let mut send_channels = HashMap::with_capacity(self.destination_chains.len()); let mut prep_queues = HashMap::with_capacity(self.destination_chains.len()); diff --git a/rust/main/agents/relayer/src/server/list_messages.rs b/rust/main/agents/relayer/src/server/list_messages.rs index 8eea8446b..e21f39a5d 100644 --- a/rust/main/agents/relayer/src/server/list_messages.rs +++ b/rust/main/agents/relayer/src/server/list_messages.rs @@ -79,8 +79,6 @@ impl ListOperationsApi { } } -// TODO: there's some duplication between the setup for these tests and the one in `message_retry.rs`, -// which should be refactored into a common test setup. #[cfg(test)] mod tests { use crate::msg::op_queue::{ @@ -91,7 +89,7 @@ mod tests { use super::*; use axum::http::StatusCode; use hyperlane_core::KnownHyperlaneDomain; - use std::{cmp::Reverse, net::SocketAddr, str::FromStr, sync::Arc}; + use std::{cmp::Reverse, net::SocketAddr, sync::Arc}; use tokio::sync::{self, Mutex}; const DUMMY_DOMAIN: KnownHyperlaneDomain = KnownHyperlaneDomain::Arbitrum; @@ -109,6 +107,7 @@ mod tests { let list_operations_api = ListOperationsApi::new(op_queues_map); let (path, router) = list_operations_api.get_route(); + let app = Router::new().nest(path, router); // Running the app in the background using a test server @@ -125,13 +124,20 @@ mod tests { let (addr, op_queue) = setup_test_server(); let id_1 = "0x1acbee9798118b11ebef0d94b0a2936eafd58e3bfab91b05da875825c4a1c39b"; let id_2 = "0x51e7be221ce90a49dee46ca0d0270c48d338a7b9d85c2a89d83fac0816571914"; + let sender_address = "0x586d41b02fb35df0f84ecb2b73e076b40c929ee3e1ceeada9a078aa7b46d3b08"; + let recipient_address = + "0x586d41b02fb35df0f84ecb2b73e076b40c929ee3e1ceeada9a078aa7b46d3b08"; let dummy_operation_1 = Box::new( MockPendingOperation::new(1, DUMMY_DOMAIN.into()) - .with_id(H256::from_str(id_1).unwrap()), + .with_id(id_1) + .with_sender_address(sender_address) + .with_recipient_address(recipient_address), ) as QueueOperation; let dummy_operation_2 = Box::new( MockPendingOperation::new(2, DUMMY_DOMAIN.into()) - .with_id(H256::from_str(id_2).unwrap()), + .with_id(id_2) + .with_sender_address(sender_address) + .with_recipient_address(recipient_address), ) as QueueOperation; // The reason there already is an id inside `operation` here is because it's a field on `MockPendingOperation` - that field is @@ -143,8 +149,12 @@ mod tests { "destination_domain": { "Known": "Arbitrum" }, + "destination_domain_id": 42161, "id": "0x1acbee9798118b11ebef0d94b0a2936eafd58e3bfab91b05da875825c4a1c39b", + "origin_domain_id": 0, + "recipient_address": "0x586d41b02fb35df0f84ecb2b73e076b40c929ee3e1ceeada9a078aa7b46d3b08", "seconds_to_next_attempt": 1, + "sender_address": "0x586d41b02fb35df0f84ecb2b73e076b40c929ee3e1ceeada9a078aa7b46d3b08", "type": "MockPendingOperation" } }, @@ -154,8 +164,12 @@ mod tests { "destination_domain": { "Known": "Arbitrum" }, + "destination_domain_id": 42161, "id": "0x51e7be221ce90a49dee46ca0d0270c48d338a7b9d85c2a89d83fac0816571914", + "origin_domain_id": 0, + "recipient_address": "0x586d41b02fb35df0f84ecb2b73e076b40c929ee3e1ceeada9a078aa7b46d3b08", "seconds_to_next_attempt": 2, + "sender_address": "0x586d41b02fb35df0f84ecb2b73e076b40c929ee3e1ceeada9a078aa7b46d3b08", "type": "MockPendingOperation" } } @@ -173,6 +187,8 @@ mod tests { // Check that the response status code is OK assert_eq!(response.status(), StatusCode::OK); - assert_eq!(response.text().await.unwrap(), expected_response); + + let response_text = response.text().await.unwrap(); + assert_eq!(response_text, expected_response); } } diff --git a/rust/main/agents/relayer/src/server/message_retry.rs b/rust/main/agents/relayer/src/server/message_retry.rs index 3fff125ee..6d04eed86 100644 --- a/rust/main/agents/relayer/src/server/message_retry.rs +++ b/rust/main/agents/relayer/src/server/message_retry.rs @@ -1,90 +1,31 @@ -use axum::{ - extract::{Query, State}, - routing, Router, -}; +use crate::settings::matching_list::MatchingList; +use axum::{extract::State, routing, Json, Router}; use derive_new::new; -use hyperlane_core::{ChainCommunicationError, QueueOperation, H256}; -use serde::Deserialize; -use std::str::FromStr; use tokio::sync::broadcast::Sender; const MESSAGE_RETRY_API_BASE: &str = "/message_retry"; -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum MessageRetryRequest { - MessageId(H256), - DestinationDomain(u32), -} - -impl PartialEq for &MessageRetryRequest { - fn eq(&self, other: &QueueOperation) -> bool { - match self { - MessageRetryRequest::MessageId(message_id) => message_id == &other.id(), - MessageRetryRequest::DestinationDomain(destination_domain) => { - destination_domain == &other.destination_domain().id() - } - } - } -} - #[derive(new, Clone)] pub struct MessageRetryApi { - tx: Sender, -} - -#[derive(Deserialize)] -struct RawMessageRetryRequest { - message_id: Option, - destination_domain: Option, -} - -impl TryFrom for Vec { - type Error = ChainCommunicationError; - - fn try_from(request: RawMessageRetryRequest) -> Result { - let mut retry_requests = Vec::new(); - if let Some(message_id) = request.message_id { - retry_requests.push(MessageRetryRequest::MessageId(H256::from_str(&message_id)?)); - } - if let Some(destination_domain) = request.destination_domain { - retry_requests.push(MessageRetryRequest::DestinationDomain(destination_domain)); - } - Ok(retry_requests) - } + tx: Sender, } async fn retry_message( - State(tx): State>, - Query(request): Query, + State(tx): State>, + Json(retry_req_payload): Json, ) -> String { - let retry_requests: Vec = match request.try_into() { - Ok(retry_requests) => retry_requests, + match tx.send(retry_req_payload) { + Ok(_) => "Moved message(s) to the front of the queue".to_string(), // Technically it's bad practice to print the error message to the user, but // this endpoint is for debugging purposes only. - Err(err) => { - return format!("Failed to parse retry request: {}", err); - } - }; - - if retry_requests.is_empty() { - return "No retry requests found. Please provide either a message_id or destination_domain.".to_string(); + Err(err) => format!("Failed to send retry request to the queue: {}", err), } - - if let Err(err) = retry_requests - .into_iter() - .map(|req| tx.send(req)) - .collect::, _>>() - { - return format!("Failed to send retry request to the queue: {}", err); - } - - "Moved message(s) to the front of the queue".to_string() } impl MessageRetryApi { pub fn router(&self) -> Router { Router::new() - .route("/", routing::get(retry_message)) + .route("/", routing::post(retry_message)) .with_state(self.tx.clone()) } @@ -95,18 +36,20 @@ impl MessageRetryApi { #[cfg(test)] mod tests { - use crate::server::ENDPOINT_MESSAGES_QUEUE_SIZE; + use crate::{msg::op_queue::test::MockPendingOperation, server::ENDPOINT_MESSAGES_QUEUE_SIZE}; use super::*; use axum::http::StatusCode; - use ethers::utils::hex::ToHex; + use hyperlane_core::{HyperlaneMessage, QueueOperation}; + use serde_json::json; use std::net::SocketAddr; use tokio::sync::broadcast::{Receiver, Sender}; - fn setup_test_server() -> (SocketAddr, Receiver) { - let broadcast_tx = Sender::::new(ENDPOINT_MESSAGES_QUEUE_SIZE); + fn setup_test_server() -> (SocketAddr, Receiver) { + let broadcast_tx = Sender::::new(ENDPOINT_MESSAGES_QUEUE_SIZE); let message_retry_api = MessageRetryApi::new(broadcast_tx.clone()); let (path, retry_router) = message_retry_api.get_route(); + let app = Router::new().nest(path, retry_router); // Running the app in the background using a test server @@ -122,49 +65,186 @@ mod tests { async fn test_message_id_retry() { let (addr, mut rx) = setup_test_server(); - // Create a random message ID - let message_id = H256::random(); + let client = reqwest::Client::new(); + // Create a random message with a random message ID + let message = HyperlaneMessage::default(); + let pending_operation = MockPendingOperation::with_message_data(message.clone()); + let matching_list_body = json!([ + { + "messageid": message.id() + } + ]); - // Send a GET request to the server - let response = reqwest::get(format!( - "http://{}{}?message_id={}", - addr, - MESSAGE_RETRY_API_BASE, - message_id.encode_hex::() - )) - .await - .unwrap(); + // Send a POST request to the server + let response = client + .post(format!("http://{}{}", addr, MESSAGE_RETRY_API_BASE)) + .json(&matching_list_body) // Set the request body + .send() + .await + .unwrap(); // Check that the response status code is OK assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - rx.try_recv().unwrap(), - MessageRetryRequest::MessageId(message_id) - ); + let list = rx.try_recv().unwrap(); + // Check that the list received by the server matches the pending operation + assert!(list.op_matches(&(Box::new(pending_operation) as QueueOperation))); } #[tokio::test] async fn test_destination_domain_retry() { let (addr, mut rx) = setup_test_server(); - // Create a random destination domain - let destination_domain = 42; + let client = reqwest::Client::new(); + let mut message = HyperlaneMessage::default(); + // Use a random destination domain + message.destination = 42; + let pending_operation = MockPendingOperation::with_message_data(message.clone()); + let matching_list_body = json!([ + { + "destinationdomain": message.destination + } + ]); + + // Send a POST request to the server + let response = client + .post(format!("http://{}{}", addr, MESSAGE_RETRY_API_BASE)) + .json(&matching_list_body) // Set the request body + .send() + .await + .unwrap(); + + // Check that the response status code is OK + assert_eq!(response.status(), StatusCode::OK); + + let list = rx.try_recv().unwrap(); + // Check that the list received by the server matches the pending operation + assert!(list.op_matches(&(Box::new(pending_operation) as QueueOperation))); + } + + #[tokio::test] + async fn test_origin_domain_retry() { + let (addr, mut rx) = setup_test_server(); + + let client = reqwest::Client::new(); + let mut message = HyperlaneMessage::default(); + // Use a random origin domain + message.origin = 42; + let pending_operation = MockPendingOperation::with_message_data(message.clone()); + let matching_list_body = json!([ + { + "origindomain": message.origin + } + ]); + + // Send a POST request to the server + let response = client + .post(format!("http://{}{}", addr, MESSAGE_RETRY_API_BASE)) + .json(&matching_list_body) // Set the request body + .send() + .await + .unwrap(); + + // Check that the response status code is OK + assert_eq!(response.status(), StatusCode::OK); + + let list = rx.try_recv().unwrap(); + // Check that the list received by the server matches the pending operation + assert!(list.op_matches(&(Box::new(pending_operation) as QueueOperation))); + } + + #[tokio::test] + async fn test_sender_address_retry() { + let (addr, mut rx) = setup_test_server(); + + let client = reqwest::Client::new(); + let message = HyperlaneMessage::default(); + let pending_operation = MockPendingOperation::with_message_data(message.clone()); + let matching_list_body = json!([ + { + "senderaddress": message.sender + } + ]); + + // Send a POST request to the server + let response = client + .post(format!("http://{}{}", addr, MESSAGE_RETRY_API_BASE)) + .json(&matching_list_body) // Set the request body + .send() + .await + .unwrap(); + + // Check that the response status code is OK + assert_eq!(response.status(), StatusCode::OK); + + let list = rx.try_recv().unwrap(); + // Check that the list received by the server matches the pending operation + assert!(list.op_matches(&(Box::new(pending_operation) as QueueOperation))); + } + + #[tokio::test] + async fn test_recipient_address_retry() { + let (addr, mut rx) = setup_test_server(); + + let client = reqwest::Client::new(); + let message = HyperlaneMessage::default(); + let pending_operation = MockPendingOperation::with_message_data(message.clone()); + let matching_list_body = json!([ + { + "recipientaddress": message.recipient + } + ]); + + // Send a POST request to the server + let response = client + .post(format!("http://{}{}", addr, MESSAGE_RETRY_API_BASE)) + .json(&matching_list_body) // Set the request body + .send() + .await + .unwrap(); + + // Check that the response status code is OK + assert_eq!(response.status(), StatusCode::OK); + + let list = rx.try_recv().unwrap(); + // Check that the list received by the server matches the pending operation + assert!(list.op_matches(&(Box::new(pending_operation) as QueueOperation))); + } + + #[tokio::test] + async fn test_multiple_retry() { + let (addr, mut rx) = setup_test_server(); + + let client = reqwest::Client::new(); + let mut message = HyperlaneMessage::default(); + // Use a random origin domain + message.origin = 42; + let pending_operation = MockPendingOperation::with_message_data(message.clone()); + let matching_list_body = json!([ + { + "origindomain": message.origin + }, + { + "destinationdomain": message.destination + }, + { + "messageid": message.id() + } + ]); - // Send a GET request to the server - let response = reqwest::get(format!( - "http://{}{}?destination_domain={}", - addr, MESSAGE_RETRY_API_BASE, destination_domain - )) - .await - .unwrap(); + // Send a POST request to the server + let response = client + .post(format!("http://{}{}", addr, MESSAGE_RETRY_API_BASE)) + .json(&matching_list_body) // Set the request body + .send() + .await + .unwrap(); // Check that the response status code is OK assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - rx.try_recv().unwrap(), - MessageRetryRequest::DestinationDomain(destination_domain) - ); + let list = rx.try_recv().unwrap(); + // Check that the list received by the server matches the pending operation + assert!(list.op_matches(&(Box::new(pending_operation) as QueueOperation))); } } diff --git a/rust/main/agents/relayer/src/server/mod.rs b/rust/main/agents/relayer/src/server/mod.rs index 4b60e7bb5..083f8d94d 100644 --- a/rust/main/agents/relayer/src/server/mod.rs +++ b/rust/main/agents/relayer/src/server/mod.rs @@ -3,7 +3,7 @@ use derive_new::new; use std::collections::HashMap; use tokio::sync::broadcast::Sender; -use crate::msg::op_queue::OperationPriorityQueue; +use crate::{msg::op_queue::OperationPriorityQueue, settings::matching_list::MatchingList}; pub const ENDPOINT_MESSAGES_QUEUE_SIZE: usize = 100; @@ -16,13 +16,13 @@ mod message_retry; #[derive(new)] pub struct Server { #[new(default)] - retry_transmitter: Option>, + retry_transmitter: Option>, #[new(default)] op_queues: Option>, } impl Server { - pub fn with_op_retry(mut self, transmitter: Sender) -> Self { + pub fn with_op_retry(mut self, transmitter: Sender) -> Self { self.retry_transmitter = Some(transmitter); self } diff --git a/rust/main/agents/relayer/src/settings/matching_list.rs b/rust/main/agents/relayer/src/settings/matching_list.rs index 6424283e3..ca65ed67f 100644 --- a/rust/main/agents/relayer/src/settings/matching_list.rs +++ b/rust/main/agents/relayer/src/settings/matching_list.rs @@ -8,7 +8,9 @@ use std::{ marker::PhantomData, }; -use hyperlane_core::{config::StrOrInt, utils::hex_or_base58_to_h256, HyperlaneMessage, H256}; +use hyperlane_core::{ + config::StrOrInt, utils::hex_or_base58_to_h256, HyperlaneMessage, QueueOperation, H256, +}; use serde::{ de::{Error, SeqAccess, Visitor}, Deserialize, Deserializer, @@ -223,6 +225,8 @@ impl<'de> Deserialize<'de> for Filter { #[derive(Debug, Deserialize, Clone)] #[serde(tag = "type")] struct ListElement { + #[serde(default, rename = "messageid")] + message_id: Filter, #[serde(default, rename = "origindomain")] origin_domain: Filter, #[serde(default, rename = "senderaddress")] @@ -237,7 +241,8 @@ impl Display for ListElement { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( f, - "{{originDomain: {}, senderAddress: {}, destinationDomain: {}, recipientAddress: {}}}", + "{{messageId: {}, originDomain: {}, senderAddress: {}, destinationDomain: {}, recipientAddress: {}}}", + self.message_id, self.origin_domain, self.sender_address, self.destination_domain, @@ -248,6 +253,7 @@ impl Display for ListElement { #[derive(Copy, Clone, Debug)] struct MatchInfo<'a> { + src_msg_id: H256, src_domain: u32, src_addr: &'a H256, dst_domain: u32, @@ -257,6 +263,7 @@ struct MatchInfo<'a> { impl<'a> From<&'a HyperlaneMessage> for MatchInfo<'a> { fn from(msg: &'a HyperlaneMessage) -> Self { Self { + src_msg_id: msg.id(), src_domain: msg.origin, src_addr: &msg.sender, dst_domain: msg.destination, @@ -265,13 +272,51 @@ impl<'a> From<&'a HyperlaneMessage> for MatchInfo<'a> { } } +impl<'a> From<&'a QueueOperation> for MatchInfo<'a> { + fn from(op: &'a QueueOperation) -> Self { + Self { + src_msg_id: op.id(), + src_domain: op.origin_domain_id(), + src_addr: op.sender_address(), + dst_domain: op.destination_domain().id(), + dst_addr: op.recipient_address(), + } + } +} + impl MatchingList { + pub fn with_message_id(message_id: H256) -> Self { + Self(Some(vec![ListElement { + message_id: Filter::Enumerated(vec![message_id]), + origin_domain: Default::default(), + sender_address: Default::default(), + destination_domain: Default::default(), + recipient_address: Default::default(), + }])) + } + + pub fn with_destination_domain(destination_domain: u32) -> Self { + Self(Some(vec![ListElement { + message_id: Default::default(), + origin_domain: Default::default(), + sender_address: Default::default(), + destination_domain: Filter::Enumerated(vec![destination_domain]), + recipient_address: Default::default(), + }])) + } + /// Check if a message matches any of the rules. /// - `default`: What to return if the matching list is empty. pub fn msg_matches(&self, msg: &HyperlaneMessage, default: bool) -> bool { self.matches(msg.into(), default) } + /// Check if queue operation matches any of the rules. + /// If the matching list is empty, we assume the queue operation does not match. + pub fn op_matches(&self, op: &QueueOperation) -> bool { + self.matches(op.into(), false) + } + /// Check if a message matches any of the rules. /// - `default`: What to return if the matching list is empty. fn matches(&self, info: MatchInfo, default: bool) -> bool { @@ -285,7 +330,8 @@ impl MatchingList { fn matches_any_rule<'a>(mut rules: impl Iterator, info: MatchInfo) -> bool { rules.any(|rule| { - rule.origin_domain.matches(&info.src_domain) + rule.message_id.matches(&info.src_msg_id) + && rule.origin_domain.matches(&info.src_domain) && rule.sender_address.matches(info.src_addr) && rule.destination_domain.matches(&info.dst_domain) && rule.recipient_address.matches(info.dst_addr) @@ -323,23 +369,26 @@ mod test { #[test] fn basic_config() { - let list: MatchingList = serde_json::from_str(r#"[{"origindomain": "*", "senderaddress": "*", "destinationdomain": "*", "recipientaddress": "*"}, {}]"#).unwrap(); + let list: MatchingList = serde_json::from_str(r#"[{"messageid": "*", "origindomain": "*", "senderaddress": "*", "destinationdomain": "*", "recipientaddress": "*"}, {}]"#).unwrap(); assert!(list.0.is_some()); assert_eq!(list.0.as_ref().unwrap().len(), 2); let elem = &list.0.as_ref().unwrap()[0]; assert_eq!(elem.destination_domain, Wildcard); + assert_eq!(elem.message_id, Wildcard); assert_eq!(elem.recipient_address, Wildcard); assert_eq!(elem.origin_domain, Wildcard); assert_eq!(elem.sender_address, Wildcard); let elem = &list.0.as_ref().unwrap()[1]; assert_eq!(elem.destination_domain, Wildcard); + assert_eq!(elem.message_id, Wildcard); assert_eq!(elem.recipient_address, Wildcard); assert_eq!(elem.origin_domain, Wildcard); assert_eq!(elem.sender_address, Wildcard); assert!(list.matches( MatchInfo { + src_msg_id: H256::random(), src_domain: 0, src_addr: &H256::default(), dst_domain: 0, @@ -350,6 +399,7 @@ mod test { assert!(list.matches( MatchInfo { + src_msg_id: H256::random(), src_domain: 34, src_addr: &"0x9d4454B023096f34B160D6B654540c56A1F81688" .parse::() @@ -369,6 +419,7 @@ mod test { assert_eq!(list.0.as_ref().unwrap().len(), 1); let elem = &list.0.as_ref().unwrap()[0]; assert_eq!(elem.destination_domain, Wildcard); + assert_eq!(elem.message_id, Wildcard); assert_eq!( elem.recipient_address, Enumerated(vec!["0x9d4454B023096f34B160D6B654540c56A1F81688" @@ -387,6 +438,7 @@ mod test { assert!(list.matches( MatchInfo { + src_msg_id: H256::default(), src_domain: 34, src_addr: &"0x9d4454B023096f34B160D6B654540c56A1F81688" .parse::() @@ -403,6 +455,7 @@ mod test { assert!(!list.matches( MatchInfo { + src_msg_id: H256::default(), src_domain: 34, src_addr: &"0x9d4454B023096f34B160D6B654540c56A1F81688" .parse::() @@ -423,6 +476,7 @@ mod test { assert_eq!(whitelist.0.as_ref().unwrap().len(), 1); let elem = &whitelist.0.as_ref().unwrap()[0]; assert_eq!(elem.destination_domain, Enumerated(vec![9913372, 9913373])); + assert_eq!(elem.message_id, Wildcard); assert_eq!(elem.recipient_address, Wildcard); assert_eq!(elem.origin_domain, Wildcard); assert_eq!(elem.sender_address, Wildcard); @@ -437,6 +491,7 @@ mod test { #[test] fn matches_empty_list() { let info = MatchInfo { + src_msg_id: H256::default(), src_domain: 0, src_addr: &H256::default(), dst_domain: 0, @@ -451,7 +506,7 @@ mod test { #[test] fn supports_base58() { serde_json::from_str::( - r#"[{"origindomain":1399811151,"senderaddress":"DdTMkk9nuqH5LnD56HLkPiKMV3yB3BNEYSQfgmJHa5i7","destinationdomain":11155111,"recipientaddress":"0x6AD4DEBA8A147d000C09de6465267a9047d1c217"}]"#, + r#"[{"messageid": "*", "origindomain":1399811151,"senderaddress":"DdTMkk9nuqH5LnD56HLkPiKMV3yB3BNEYSQfgmJHa5i7","destinationdomain":11155111,"recipientaddress":"0x6AD4DEBA8A147d000C09de6465267a9047d1c217"}]"#, ).unwrap(); } diff --git a/rust/main/hyperlane-core/src/traits/pending_operation.rs b/rust/main/hyperlane-core/src/traits/pending_operation.rs index f5480b197..e0a6622c3 100644 --- a/rust/main/hyperlane-core/src/traits/pending_operation.rs +++ b/rust/main/hyperlane-core/src/traits/pending_operation.rs @@ -61,6 +61,12 @@ pub trait PendingOperation: Send + Sync + Debug + TryBatchAs { /// The domain this operation will take place on. fn destination_domain(&self) -> &HyperlaneDomain; + /// The sender address of this operation. + fn sender_address(&self) -> &H256; + + /// The recipient address of this operation. + fn recipient_address(&self) -> &H256; + /// Label to use for metrics granularity. fn app_context(&self) -> Option; From 8dbc2e636ef61ae8d351f0939e3cdaca2c78bcbb Mon Sep 17 00:00:00 2001 From: Daniel Savu <23065004+daniel-savu@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:46:41 +0000 Subject: [PATCH 218/224] fix: another sealevel unit test flake (#4784) Applies the same fix from https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4655 to a flake that showed up in this PRs CI: https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4693#event-15004545304 --- rust/sealevel/programs/mailbox-test/src/functional.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rust/sealevel/programs/mailbox-test/src/functional.rs b/rust/sealevel/programs/mailbox-test/src/functional.rs index 3c4ace00e..0870ef2fa 100644 --- a/rust/sealevel/programs/mailbox-test/src/functional.rs +++ b/rust/sealevel/programs/mailbox-test/src/functional.rs @@ -1,3 +1,5 @@ +use std::thread::sleep; + use borsh::BorshDeserialize; use hyperlane_core::{ accumulator::incremental::IncrementalMerkle as MerkleTree, HyperlaneMessage, H256, @@ -976,6 +978,10 @@ async fn test_process_errors_if_message_already_processed() { .await .unwrap(); + // there's a race condition that isn't fixed by setting `CommitmentLevel::Confirmed` + // just wait a bit to ensure the message is processed + sleep(std::time::Duration::from_secs(1)); + let result = process( &mut banks_client, &payer, From 1b5bfa3466f290745fbf9ac751fa85e3152edbe9 Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Wed, 30 Oct 2024 13:18:13 +0000 Subject: [PATCH 219/224] feat: add a script for getting typical remote gas amounts (#4782) ### Description - Sometimes Jake requests an update on these for his own models, this makes it easier for us to get it for him ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../infra/config/environments/mainnet3/igp.ts | 4 +- .../scripts/get-typical-remote-gas-amounts.ts | 49 +++++++++++++++++++ typescript/infra/src/config/gas-oracle.ts | 18 ++++++- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 typescript/infra/scripts/get-typical-remote-gas-amounts.ts diff --git a/typescript/infra/config/environments/mainnet3/igp.ts b/typescript/infra/config/environments/mainnet3/igp.ts index fa4ab8e91..2b388afdd 100644 --- a/typescript/infra/config/environments/mainnet3/igp.ts +++ b/typescript/infra/config/environments/mainnet3/igp.ts @@ -23,13 +23,13 @@ import rawTokenPrices from './tokenPrices.json'; const tokenPrices: ChainMap = rawTokenPrices; -const getOverheadWithOverrides = (local: ChainName, remote: ChainName) => { +export function getOverheadWithOverrides(local: ChainName, remote: ChainName) { let overhead = getOverhead(local, remote, ethereumChainNames); if (remote === 'moonbeam') { overhead *= 4; } return overhead; -}; +} const storageGasOracleConfig: AllStorageGasOracleConfigs = getAllStorageGasOracleConfigs( diff --git a/typescript/infra/scripts/get-typical-remote-gas-amounts.ts b/typescript/infra/scripts/get-typical-remote-gas-amounts.ts new file mode 100644 index 000000000..5f190a72d --- /dev/null +++ b/typescript/infra/scripts/get-typical-remote-gas-amounts.ts @@ -0,0 +1,49 @@ +import { ChainMap } from '@hyperlane-xyz/sdk'; +import { stringifyObject } from '@hyperlane-xyz/utils'; + +import { getOverheadWithOverrides } from '../config/environments/mainnet3/igp.js'; +import { getTypicalRemoteGasAmount } from '../src/config/gas-oracle.js'; + +import { getArgs } from './agent-utils.js'; +import { getEnvironmentConfig } from './core-utils.js'; + +// This script exists to print the typical local -> remote gas amounts for a given environment. +// This is useful for Jake to use in his own models for assessing message costs. + +async function main() { + const args = await getArgs().argv; + + if (args.environment !== 'mainnet3') { + throw new Error('This script only supports the mainnet3 environment'); + } + + const environmentConfig = getEnvironmentConfig(args.environment); + + // Local -> Remote -> Amount of gas. + // Local is important because depending on the validator threshold, the cost + // to verify changes. Remote is important because the cost to execute the + // message can change depending on the chain (e.g. alt VMs, or some exceptions like Moonbeam + // that has non-standard EVM gas usage). + const amounts: ChainMap> = {}; + + for (const local of environmentConfig.supportedChainNames) { + for (const remote of environmentConfig.supportedChainNames) { + if (local === remote) { + continue; + } + amounts[local] = amounts[local] || {}; + amounts[local][remote] = getTypicalRemoteGasAmount( + local, + remote, + getOverheadWithOverrides, + ); + } + } + + console.log(stringifyObject(amounts, 'json', 2)); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/typescript/infra/src/config/gas-oracle.ts b/typescript/infra/src/config/gas-oracle.ts index c040ff45b..622ad18b3 100644 --- a/typescript/infra/src/config/gas-oracle.ts +++ b/typescript/infra/src/config/gas-oracle.ts @@ -22,6 +22,10 @@ export type AllStorageGasOracleConfigs = ChainMap< // Overcharge by 50% to account for market making risk export const EXCHANGE_RATE_MARGIN_PCT = 50; +// Arbitrarily chosen as a typical amount of gas used in a message's handle function. +// Used for determining typical gas costs for a message. +export const TYPICAL_HANDLE_GAS_USAGE = 50_000; + // Gets the StorageGasOracleConfig for each remote chain for a particular local chain. // Accommodates small non-integer gas prices by scaling up the gas price // and scaling down the exchange rate by the same factor. @@ -81,7 +85,11 @@ function getLocalStorageGasOracleConfigOverride( // If we have access to these, let's use the USD prices to apply some minimum // typical USD payment heuristics. if (getTokenUsdPrice && getOverhead) { - const typicalRemoteGasAmount = getOverhead(local, remote) + 50_000; + const typicalRemoteGasAmount = getTypicalRemoteGasAmount( + local, + remote, + getOverhead, + ); const typicalIgpQuoteUsd = getUsdQuote( local, gasPriceBn, @@ -112,6 +120,14 @@ function getLocalStorageGasOracleConfigOverride( }, {}); } +export function getTypicalRemoteGasAmount( + local: ChainName, + remote: ChainName, + getOverhead: (local: ChainName, remote: ChainName) => number, +): number { + return getOverhead(local, remote) + TYPICAL_HANDLE_GAS_USAGE; +} + function getMinUsdCost(local: ChainName, remote: ChainName): number { // By default, min cost is 20 cents let minUsdCost = 0.2; From 7e9e248beff122e7f1093eb8883b4ffe9f04a919 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:45:46 -0400 Subject: [PATCH 220/224] feat: allow update destination gas (#4674) ### Description Updates destination gas on all chain by getting the value from warpConfig.gas. It then synchronizes all destination gas amounts across all chains. ### Related issues - Fixes #4529 ### Backward compatibility Yes ### Testing Manual/e2e --- .changeset/long-queens-deny.md | 6 + .changeset/tidy-meals-add.md | 2 +- typescript/cli/src/deploy/warp.ts | 151 ++++++++++++------ .../cli/src/tests/warp-apply.e2e-test.ts | 56 +++++++ typescript/sdk/src/index.ts | 1 + typescript/sdk/src/router/schemas.ts | 7 + typescript/sdk/src/router/types.ts | 2 + .../token/EvmERC20WarpModule.hardhat-test.ts | 34 ++++ .../sdk/src/token/EvmERC20WarpModule.ts | 62 +++++++ .../sdk/src/token/EvmERC20WarpRouteReader.ts | 28 +++- 10 files changed, 301 insertions(+), 48 deletions(-) create mode 100644 .changeset/long-queens-deny.md diff --git a/.changeset/long-queens-deny.md b/.changeset/long-queens-deny.md new file mode 100644 index 000000000..9ffa67201 --- /dev/null +++ b/.changeset/long-queens-deny.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Add feat to allow updates to destination gas using warp apply diff --git a/.changeset/tidy-meals-add.md b/.changeset/tidy-meals-add.md index 47b2fee5a..2d1ba70ca 100644 --- a/.changeset/tidy-meals-add.md +++ b/.changeset/tidy-meals-add.md @@ -1,5 +1,5 @@ --- -"@hyperlane-xyz/utils": patch +'@hyperlane-xyz/utils': patch --- Filter undefined/null values in invertKeysAndValues function diff --git a/typescript/cli/src/deploy/warp.ts b/typescript/cli/src/deploy/warp.ts index 36bbc2ad8..38a5e14f2 100644 --- a/typescript/cli/src/deploy/warp.ts +++ b/typescript/cli/src/deploy/warp.ts @@ -12,6 +12,7 @@ import { ChainSubmissionStrategy, ChainSubmissionStrategySchema, ContractVerifier, + DestinationGas, EvmERC20WarpModule, EvmERC20WarpRouteReader, EvmIsmModule, @@ -54,7 +55,6 @@ import { Address, ProtocolType, assert, - isObjEmpty, objFilter, objKeys, objMap, @@ -474,7 +474,6 @@ async function extendWarpRoute( warpDeployConfig: WarpRouteDeployConfig, warpCoreConfigByChain: ChainMap, ) { - logBlue('Extending Warp Route'); const { multiProvider } = params.context; const warpCoreChains = Object.keys(warpCoreConfigByChain); @@ -489,7 +488,10 @@ async function extendWarpRoute( (chain, _config): _config is any => !warpCoreChains.includes(chain), ); - if (isObjEmpty(extendedConfigs)) return []; + const extendedChains = Object.keys(extendedConfigs); + if (extendedChains.length === 0) return []; + + logBlue(`Extending Warp Route to ${extendedChains.join(', ')}`); extendedConfigs = await deriveMetadataFromExisting( multiProvider, @@ -536,28 +538,33 @@ async function updateExistingWarpRoute( ExplorerLicenseType.MIT, ); const transactions: AnnotatedEV5Transaction[] = []; + await promiseObjAll( objMap(warpDeployConfig, async (chain, config) => { - const deployedConfig = warpCoreConfigByChain[chain]; - if (!deployedConfig) - return logGray( - `Missing artifacts for ${chain}. Probably new deployment. Skipping update...`, - ); - config.ismFactoryAddresses = addresses[ - chain - ] as ProxyFactoryFactoriesAddresses; - const evmERC20WarpModule = new EvmERC20WarpModule( - multiProvider, - { - config, - chain, - addresses: { - deployedTokenRoute: deployedConfig.addressOrDenom!, + await retryAsync(async () => { + logGray(`Update existing warp route for chain ${chain}`); + const deployedConfig = warpCoreConfigByChain[chain]; + if (!deployedConfig) + return logGray( + `Missing artifacts for ${chain}. Probably new deployment. Skipping update...`, + ); + + config.ismFactoryAddresses = addresses[ + chain + ] as ProxyFactoryFactoriesAddresses; + const evmERC20WarpModule = new EvmERC20WarpModule( + multiProvider, + { + config, + chain, + addresses: { + deployedTokenRoute: deployedConfig.addressOrDenom!, + }, }, - }, - contractVerifier, - ); - transactions.push(...(await evmERC20WarpModule.update(config))); + contractVerifier, + ); + transactions.push(...(await evmERC20WarpModule.update(config))); + }); }), ); return transactions; @@ -636,11 +643,17 @@ async function enrollRemoteRouters( ): Promise { logBlue(`Enrolling deployed routers with each other...`); const { multiProvider } = params.context; - const deployedRouters: ChainMap
= objMap( + const deployedRoutersAddresses: ChainMap
= objMap( deployedContractsMap, (_, contracts) => getRouter(contracts).address, ); - const allChains = Object.keys(deployedRouters); + const deployedDestinationGas: DestinationGas = await populateDestinationGas( + multiProvider, + params.warpDeployConfig, + deployedContractsMap, + ); + + const deployedChains = Object.keys(deployedRoutersAddresses); const transactions: AnnotatedEV5Transaction[] = []; await promiseObjAll( objMap(deployedContractsMap, async (chain, contracts) => { @@ -662,14 +675,23 @@ async function enrollRemoteRouters( const otherChains = multiProvider .getRemoteChains(chain) - .filter((c) => allChains.includes(c)); + .filter((c) => deployedChains.includes(c)); mutatedWarpRouteConfig.remoteRouters = - otherChains.reduce((remoteRouters, chain) => { - remoteRouters[multiProvider.getDomainId(chain)] = - deployedRouters[chain]; + otherChains.reduce((remoteRouters, otherChain) => { + remoteRouters[multiProvider.getDomainId(otherChain)] = + deployedRoutersAddresses[otherChain]; return remoteRouters; }, {}); + + mutatedWarpRouteConfig.destinationGas = + otherChains.reduce((destinationGas, otherChain) => { + const otherChainDomain = multiProvider.getDomainId(otherChain); + destinationGas[otherChainDomain] = + deployedDestinationGas[otherChainDomain]; + return destinationGas; + }, {}); + const mutatedConfigTxs: AnnotatedEV5Transaction[] = await evmERC20WarpModule.update(mutatedWarpRouteConfig); @@ -685,6 +707,38 @@ async function enrollRemoteRouters( return transactions; } +/** + * Populates the destination gas amounts for each chain using warpConfig.gas OR querying other router's destinationGas + */ +async function populateDestinationGas( + multiProvider: MultiProvider, + warpDeployConfig: WarpRouteDeployConfig, + deployedContractsMap: HyperlaneContractsMap, +): Promise { + const destinationGas: DestinationGas = {}; + const deployedChains = Object.keys(deployedContractsMap); + await promiseObjAll( + objMap(deployedContractsMap, async (chain, contracts) => { + await retryAsync(async () => { + const router = getRouter(contracts); + + const otherChains = multiProvider + .getRemoteChains(chain) + .filter((c) => deployedChains.includes(c)); + + for (const otherChain of otherChains) { + const otherDomain = multiProvider.getDomainId(otherChain); + if (!destinationGas[otherDomain]) + destinationGas[otherDomain] = + warpDeployConfig[otherChain].gas?.toString() || + (await router.destinationGas(otherDomain)).toString(); + } + }); + }), + ); + return destinationGas; +} + function getRouter(contracts: HyperlaneContracts) { for (const key of objKeys(hypERC20factories)) { if (contracts[key]) return contracts[key]; @@ -830,24 +884,29 @@ async function submitWarpApplyTransactions( const { multiProvider } = params.context; await promiseObjAll( objMap(chainTransactions, async (chainId, transactions) => { - const chain = multiProvider.getChainName(chainId); - const submitter: TxSubmitterBuilder = - await getWarpApplySubmitter({ - chain, - context: params.context, - strategyUrl: params.strategyUrl, - }); - - const transactionReceipts = await submitter.submit(...transactions); - if (transactionReceipts) { - const receiptPath = `${params.receiptsDir}/${chain}-${ - submitter.txSubmitterType - }-${Date.now()}-receipts.json`; - writeYamlOrJson(receiptPath, transactionReceipts); - logGreen( - `Transactions receipts successfully written to ${receiptPath}`, - ); - } + await retryAsync( + async () => { + const chain = multiProvider.getChainName(chainId); + const submitter: TxSubmitterBuilder = + await getWarpApplySubmitter({ + chain, + context: params.context, + strategyUrl: params.strategyUrl, + }); + const transactionReceipts = await submitter.submit(...transactions); + if (transactionReceipts) { + const receiptPath = `${params.receiptsDir}/${chain}-${ + submitter.txSubmitterType + }-${Date.now()}-receipts.json`; + writeYamlOrJson(receiptPath, transactionReceipts); + logGreen( + `Transactions receipts successfully written to ${receiptPath}`, + ); + } + }, + 5, // attempts + 100, // baseRetryMs + ); }), ); } diff --git a/typescript/cli/src/tests/warp-apply.e2e-test.ts b/typescript/cli/src/tests/warp-apply.e2e-test.ts index 2346038d6..ff891448d 100644 --- a/typescript/cli/src/tests/warp-apply.e2e-test.ts +++ b/typescript/cli/src/tests/warp-apply.e2e-test.ts @@ -259,4 +259,60 @@ describe('WarpApply e2e tests', async function () { expect(remoteRouterKeys2).to.include(chain3Id); expect(remoteRouterKeys3).to.include(chain2Id); }); + + it('should extend an existing warp route and update all destination domains', async () => { + // Read existing config into a file + const warpConfigPath = `${TEMP_PATH}/warp-route-deployment-2.yaml`; + const warpDeployConfig = await readWarpConfig( + CHAIN_NAME_2, + WARP_CORE_CONFIG_PATH_2, + warpConfigPath, + ); + warpDeployConfig[CHAIN_NAME_2].gas = 7777; + + // Extend with new config + const GAS = 694200; + const extendedConfig: TokenRouterConfig = { + decimals: 18, + mailbox: chain2Addresses!.mailbox, + name: 'Ether', + owner: new Wallet(ANVIL_KEY).address, + symbol: 'ETH', + totalSupply: 0, + type: TokenType.native, + gas: GAS, + }; + warpDeployConfig[CHAIN_NAME_3] = extendedConfig; + writeYamlOrJson(warpConfigPath, warpDeployConfig); + await hyperlaneWarpApply(warpConfigPath, WARP_CORE_CONFIG_PATH_2); + + const COMBINED_WARP_CORE_CONFIG_PATH = `${REGISTRY_PATH}/deployments/warp_routes/ETH/anvil2-anvil3-config.yaml`; + + // Check that chain2 is enrolled in chain1 + const updatedWarpDeployConfig_2 = await readWarpConfig( + CHAIN_NAME_2, + COMBINED_WARP_CORE_CONFIG_PATH, + warpConfigPath, + ); + + const chain2Id = await getChainId(CHAIN_NAME_2, ANVIL_KEY); + const chain3Id = await getChainId(CHAIN_NAME_3, ANVIL_KEY); + + // Destination gas should be set in the existing chain (chain2) to include the extended chain (chain3) + const destinationGas_2 = + updatedWarpDeployConfig_2[CHAIN_NAME_2].destinationGas!; + expect(Object.keys(destinationGas_2)).to.include(chain3Id); + expect(destinationGas_2[chain3Id]).to.equal(GAS.toString()); + + // Destination gas should be set for the extended chain (chain3) + const updatedWarpDeployConfig_3 = await readWarpConfig( + CHAIN_NAME_3, + COMBINED_WARP_CORE_CONFIG_PATH, + warpConfigPath, + ); + const destinationGas_3 = + updatedWarpDeployConfig_3[CHAIN_NAME_3].destinationGas!; + expect(Object.keys(destinationGas_3)).to.include(chain2Id); + expect(destinationGas_3[chain2Id]).to.equal('7777'); + }); }); diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index 5ab4630b9..efadabc44 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -394,6 +394,7 @@ export { ProxiedFactories, ProxiedRouterConfig, RemoteRouters, + DestinationGas, RouterAddress, RouterConfig, RouterViolation, diff --git a/typescript/sdk/src/router/schemas.ts b/typescript/sdk/src/router/schemas.ts index abccd9161..d49a72dbd 100644 --- a/typescript/sdk/src/router/schemas.ts +++ b/typescript/sdk/src/router/schemas.ts @@ -32,6 +32,13 @@ export const RouterConfigSchema = MailboxClientConfigSchema.merge( }), ); +const DestinationGasDomain = z.string(); +const DestinationGasAmount = z.string(); // This must be a string type to match Ether's type +export const DestinationGasSchema = z.record( + DestinationGasDomain, + DestinationGasAmount, +); export const GasRouterConfigSchema = RouterConfigSchema.extend({ gas: z.number().optional(), + destinationGas: DestinationGasSchema.optional(), }); diff --git a/typescript/sdk/src/router/types.ts b/typescript/sdk/src/router/types.ts index 2b0c81de5..17e36ead6 100644 --- a/typescript/sdk/src/router/types.ts +++ b/typescript/sdk/src/router/types.ts @@ -14,6 +14,7 @@ import { CheckerViolation } from '../deploy/types.js'; import { ChainMap } from '../types.js'; import { + DestinationGasSchema, GasRouterConfigSchema, MailboxClientConfigSchema, RemoteRoutersSchema, @@ -66,3 +67,4 @@ export interface RouterViolation extends CheckerViolation { } export type RemoteRouters = z.infer; +export type DestinationGas = z.infer; diff --git a/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts b/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts index 467a150ad..33b9bdaa4 100644 --- a/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts +++ b/typescript/sdk/src/token/EvmERC20WarpModule.hardhat-test.ts @@ -518,5 +518,39 @@ describe('EvmERC20WarpHyperlaneModule', async () => { }); expect(txs.length).to.equal(0); }); + + it('should update the destination gas', async () => { + const domain = 3; + const config: TokenRouterConfig = { + ...baseConfig, + type: TokenType.native, + hook: hookAddress, + ismFactoryAddresses, + remoteRouters: { + [domain]: randomAddress(), + }, + }; + + // Deploy using WarpModule + const evmERC20WarpModule = await EvmERC20WarpModule.create({ + chain, + config: { + ...config, + }, + multiProvider, + }); + await sendTxs( + await evmERC20WarpModule.update({ + ...config, + destinationGas: { + [domain]: '5000', + }, + }), + ); + + const updatedConfig = await evmERC20WarpModule.read(); + expect(Object.keys(updatedConfig.destinationGas!).length).to.be.equal(1); + expect(updatedConfig.destinationGas![domain]).to.equal('5000'); + }); }); }); diff --git a/typescript/sdk/src/token/EvmERC20WarpModule.ts b/typescript/sdk/src/token/EvmERC20WarpModule.ts index 6dec4b093..462a5b646 100644 --- a/typescript/sdk/src/token/EvmERC20WarpModule.ts +++ b/typescript/sdk/src/token/EvmERC20WarpModule.ts @@ -1,4 +1,7 @@ +import { BigNumberish } from 'ethers'; + import { + GasRouter__factory, MailboxClient__factory, TokenRouter__factory, } from '@hyperlane-xyz/core'; @@ -12,6 +15,7 @@ import { assert, deepEquals, isObjEmpty, + objMap, rootLogger, } from '@hyperlane-xyz/utils'; @@ -93,9 +97,16 @@ export class EvmERC20WarpModule extends HyperlaneModule< const transactions = []; + /** + * @remark + * The order of operations matter + * 1. createOwnershipUpdateTxs() must always be LAST because no updates possible after ownership transferred + * 2. createRemoteRoutersUpdateTxs() must always be BEFORE createSetDestinationGasUpdateTxs() because gas enumeration depends on domains + */ transactions.push( ...(await this.createIsmUpdateTxs(actualConfig, expectedConfig)), ...this.createRemoteRoutersUpdateTxs(actualConfig, expectedConfig), + ...this.createSetDestinationGasUpdateTxs(actualConfig, expectedConfig), ...this.createOwnershipUpdateTxs(actualConfig, expectedConfig), ); @@ -153,6 +164,57 @@ export class EvmERC20WarpModule extends HyperlaneModule< return updateTransactions; } + /** + * Create a transaction to update the remote routers for the Warp Route contract. + * + * @param actualConfig - The on-chain router configuration, including the remoteRouters array. + * @param expectedConfig - The expected token router configuration. + * @returns A array with a single Ethereum transaction that need to be executed to enroll the routers + */ + createSetDestinationGasUpdateTxs( + actualConfig: TokenRouterConfig, + expectedConfig: TokenRouterConfig, + ): AnnotatedEV5Transaction[] { + const updateTransactions: AnnotatedEV5Transaction[] = []; + if (!expectedConfig.destinationGas) { + return []; + } + + assert(actualConfig.destinationGas, 'actualDestinationGas is undefined'); + assert(expectedConfig.destinationGas, 'actualDestinationGas is undefined'); + + const { destinationGas: actualDestinationGas } = actualConfig; + const { destinationGas: expectedDestinationGas } = expectedConfig; + + if (!deepEquals(actualDestinationGas, expectedDestinationGas)) { + const contractToUpdate = GasRouter__factory.connect( + this.args.addresses.deployedTokenRoute, + this.multiProvider.getProvider(this.domainId), + ); + + // Convert { 1: 2, 2: 3, ... } to [{ 1: 2 }, { 2: 3 }] + const gasRouterConfigs: { domain: BigNumberish; gas: BigNumberish }[] = + []; + objMap(expectedDestinationGas, (domain: string, gas: string) => { + gasRouterConfigs.push({ + domain, + gas, + }); + }); + + updateTransactions.push({ + 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)[])', + [gasRouterConfigs], + ), + }); + } + return updateTransactions; + } + /** * Create transactions to update an existing ISM config, or deploy a new ISM and return a tx to setInterchainSecurityModule * diff --git a/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts b/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts index 8ffbe82cc..0be06f7ca 100644 --- a/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts +++ b/typescript/sdk/src/token/EvmERC20WarpRouteReader.ts @@ -25,7 +25,7 @@ import { DEFAULT_CONTRACT_READ_CONCURRENCY } from '../consts/concurrency.js'; import { EvmHookReader } from '../hook/EvmHookReader.js'; import { EvmIsmReader } from '../ism/EvmIsmReader.js'; import { MultiProvider } from '../providers/MultiProvider.js'; -import { RemoteRouters } from '../router/types.js'; +import { DestinationGas, RemoteRouters } from '../router/types.js'; import { ChainNameOrId } from '../types.js'; import { HyperlaneReader } from '../utils/HyperlaneReader.js'; @@ -64,11 +64,13 @@ export class EvmERC20WarpRouteReader extends HyperlaneReader { const baseMetadata = await this.fetchMailboxClientConfig(warpRouteAddress); const tokenMetadata = await this.fetchTokenMetadata(type, warpRouteAddress); const remoteRouters = await this.fetchRemoteRouters(warpRouteAddress); + const destinationGas = await this.fetchDestinationGas(warpRouteAddress); return { ...baseMetadata, ...tokenMetadata, remoteRouters, + destinationGas, type, } as TokenRouterConfig; } @@ -245,4 +247,28 @@ export class EvmERC20WarpRouteReader extends HyperlaneReader { ), ); } + + async fetchDestinationGas( + warpRouteAddress: Address, + ): Promise { + const warpRoute = TokenRouter__factory.connect( + warpRouteAddress, + this.provider, + ); + + /** + * @remark + * Router.domains() is used to enumerate the destination gas because GasRouter.destinationGas is not EnumerableMapExtended type + * This means that if a domain is removed, then we cannot read the destinationGas for it. This may impact updates. + */ + const domains = await warpRoute.domains(); + + return Object.fromEntries( + await Promise.all( + domains.map(async (domain) => { + return [domain, (await warpRoute.destinationGas(domain)).toString()]; + }), + ), + ); + } } From c87cfbd51298eba41da1e57ca3a8c9f6e1d4edc3 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Wed, 30 Oct 2024 17:57:47 +0000 Subject: [PATCH 221/224] feat: Scrape Sealevel dispatched messages (#4776) ### Description Scraper is able to index dispatch messages: 1. Blocks are stored into database 2. Transactions are stored into database (need population of all fields) 3. Dispatched messages are stored into database ### Drive-by changes Initial indexing of delivered messages (so that Scraper does not crush) ### Related issues - Contributes into https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4272 ### Backward compatibility Yes (Solana-like chains should not be enabled for Scraper) ### Testing Manual run of Scraper E2E Tests --------- Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- .../chains/hyperlane-sealevel/src/account.rs | 68 ++++ .../chains/hyperlane-sealevel/src/error.rs | 18 +- .../hyperlane-sealevel/src/interchain_gas.rs | 114 +++--- .../main/chains/hyperlane-sealevel/src/lib.rs | 3 + .../chains/hyperlane-sealevel/src/mailbox.rs | 231 +++++++----- .../chains/hyperlane-sealevel/src/provider.rs | 73 +++- .../hyperlane-sealevel/src/rpc/client.rs | 39 ++- .../hyperlane-sealevel/src/transaction.rs | 188 ++++++++++ .../src/transaction/tests.rs | 329 ++++++++++++++++++ .../chains/hyperlane-sealevel/src/utils.rs | 33 ++ 10 files changed, 916 insertions(+), 180 deletions(-) create mode 100644 rust/main/chains/hyperlane-sealevel/src/account.rs create mode 100644 rust/main/chains/hyperlane-sealevel/src/transaction.rs create mode 100644 rust/main/chains/hyperlane-sealevel/src/transaction/tests.rs create mode 100644 rust/main/chains/hyperlane-sealevel/src/utils.rs diff --git a/rust/main/chains/hyperlane-sealevel/src/account.rs b/rust/main/chains/hyperlane-sealevel/src/account.rs new file mode 100644 index 000000000..f671c432e --- /dev/null +++ b/rust/main/chains/hyperlane-sealevel/src/account.rs @@ -0,0 +1,68 @@ +use base64::{engine::general_purpose::STANDARD as Base64, Engine}; +use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}; +use solana_client::{ + rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}, + rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType}, +}; +use solana_sdk::{account::Account, commitment_config::CommitmentConfig, pubkey::Pubkey}; + +use hyperlane_core::{ChainCommunicationError, ChainResult}; + +use crate::rpc::SealevelRpcClient; + +pub async fn search_accounts_by_discriminator( + client: &SealevelRpcClient, + program_id: &Pubkey, + discriminator: &[u8; 8], + nonce_bytes: &[u8], + offset: usize, + length: usize, +) -> ChainResult> { + let target_message_account_bytes = &[discriminator, nonce_bytes].concat(); + let target_message_account_bytes = Base64.encode(target_message_account_bytes); + + // First, find all accounts with the matching account data. + // To keep responses small in case there is ever more than 1 + // match, we don't request the full account data, and just request + // the field which was used to generate account id + #[allow(deprecated)] + let memcmp = RpcFilterType::Memcmp(Memcmp { + // Ignore the first byte, which is the `initialized` bool flag. + offset: 1, + bytes: MemcmpEncodedBytes::Base64(target_message_account_bytes), + encoding: None, + }); + let config = RpcProgramAccountsConfig { + filters: Some(vec![memcmp]), + account_config: RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64), + data_slice: Some(UiDataSliceConfig { offset, length }), + commitment: Some(CommitmentConfig::finalized()), + min_context_slot: None, + }, + with_context: Some(false), + }; + let accounts = client + .get_program_accounts_with_config(program_id, config) + .await?; + Ok(accounts) +} + +pub fn search_and_validate_account( + accounts: Vec<(Pubkey, Account)>, + message_account: F, +) -> ChainResult +where + F: Fn(&Account) -> ChainResult, +{ + for (pubkey, account) in accounts { + let expected_pubkey = message_account(&account)?; + if expected_pubkey == pubkey { + return Ok(pubkey); + } + } + + Err(ChainCommunicationError::from_other_str( + "Could not find valid storage PDA pubkey", + )) +} diff --git a/rust/main/chains/hyperlane-sealevel/src/error.rs b/rust/main/chains/hyperlane-sealevel/src/error.rs index ff0142c39..4ba217119 100644 --- a/rust/main/chains/hyperlane-sealevel/src/error.rs +++ b/rust/main/chains/hyperlane-sealevel/src/error.rs @@ -1,6 +1,7 @@ -use hyperlane_core::ChainCommunicationError; +use hyperlane_core::{ChainCommunicationError, H512}; use solana_client::client_error::ClientError; use solana_sdk::pubkey::ParsePubkeyError; +use solana_transaction_status::EncodedTransaction; /// Errors from the crates specific to the hyperlane-sealevel /// implementation. @@ -17,6 +18,21 @@ pub enum HyperlaneSealevelError { /// Decoding error #[error("{0}")] Decoding(#[from] solana_sdk::bs58::decode::Error), + /// No transaction in block error + #[error("{0}")] + NoTransactions(String), + /// Too many transactions of particular content in block + #[error("{0}")] + TooManyTransactions(String), + /// Unsupported transaction encoding + #[error("{0:?}")] + UnsupportedTransactionEncoding(EncodedTransaction), + /// Unsigned transaction + #[error("{0}")] + UnsignedTransaction(H512), + /// Incorrect transaction + #[error("received incorrect transaction, expected hash: {0:?}, received hash: {1:?}")] + IncorrectTransaction(Box, Box), } impl From for ChainCommunicationError { diff --git a/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs b/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs index d2f78eb4b..3c2cbd1c1 100644 --- a/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs +++ b/rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs @@ -1,25 +1,22 @@ +use std::ops::RangeInclusive; + use async_trait::async_trait; -use hyperlane_core::{ - config::StrOrIntParseError, ChainCommunicationError, ChainResult, ContractLocator, - HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, - InterchainGasPaymaster, InterchainGasPayment, LogMeta, SequenceAwareIndexer, H256, H512, -}; +use derive_new::new; use hyperlane_sealevel_igp::{ accounts::{GasPaymentAccount, ProgramDataAccount}, igp_gas_payment_pda_seeds, igp_program_data_pda_seeds, }; -use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}; -use solana_client::{ - rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}, - rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType}, -}; -use std::ops::RangeInclusive; +use solana_sdk::{account::Account, pubkey::Pubkey}; use tracing::{info, instrument}; -use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; -use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey}; +use hyperlane_core::{ + config::StrOrIntParseError, ChainCommunicationError, ChainResult, ContractLocator, + HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, + InterchainGasPaymaster, InterchainGasPayment, LogMeta, SequenceAwareIndexer, H256, H512, +}; -use derive_new::new; +use crate::account::{search_accounts_by_discriminator, search_and_validate_account}; +use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; /// The offset to get the `unique_gas_payment_pubkey` field from the serialized GasPaymentData. /// The account data includes prefixes that are accounted for here: a 1 byte initialized flag @@ -121,70 +118,23 @@ impl SealevelInterchainGasPaymasterIndexer { &self, sequence_number: u64, ) -> ChainResult { - let payment_bytes = &[ - &hyperlane_sealevel_igp::accounts::GAS_PAYMENT_DISCRIMINATOR[..], - &sequence_number.to_le_bytes()[..], - ] - .concat(); - #[allow(deprecated)] - let payment_bytes: String = base64::encode(payment_bytes); - - // First, find all accounts with the matching gas payment data. - // To keep responses small in case there is ever more than 1 - // match, we don't request the full account data, and just request - // the `unique_gas_payment_pubkey` field. - #[allow(deprecated)] - let memcmp = RpcFilterType::Memcmp(Memcmp { - // Ignore the first byte, which is the `initialized` bool flag. - offset: 1, - bytes: MemcmpEncodedBytes::Base64(payment_bytes), - encoding: None, - }); - let config = RpcProgramAccountsConfig { - filters: Some(vec![memcmp]), - account_config: RpcAccountInfoConfig { - encoding: Some(UiAccountEncoding::Base64), - // Don't return any data - data_slice: Some(UiDataSliceConfig { - offset: UNIQUE_GAS_PAYMENT_PUBKEY_OFFSET, - length: 32, // the length of the `unique_gas_payment_pubkey` field - }), - commitment: Some(CommitmentConfig::finalized()), - min_context_slot: None, - }, - with_context: Some(false), - }; - tracing::debug!(config=?config, "Fetching program accounts"); - let accounts = self - .rpc_client - .get_program_accounts_with_config(&self.igp.program_id, config) - .await?; + let discriminator = hyperlane_sealevel_igp::accounts::GAS_PAYMENT_DISCRIMINATOR; + let sequence_number_bytes = sequence_number.to_le_bytes(); + let unique_gas_payment_pubkey_length = 32; // the length of the `unique_gas_payment_pubkey` field + let accounts = search_accounts_by_discriminator( + &self.rpc_client, + &self.igp.program_id, + discriminator, + &sequence_number_bytes, + UNIQUE_GAS_PAYMENT_PUBKEY_OFFSET, + unique_gas_payment_pubkey_length, + ) + .await?; tracing::debug!(accounts=?accounts, "Fetched program accounts"); - // Now loop through matching accounts and find the one with a valid account pubkey - // that proves it's an actual gas payment PDA. - let mut valid_payment_pda_pubkey = Option::::None; - - for (pubkey, account) in accounts { - let unique_gas_payment_pubkey = Pubkey::new(&account.data); - let (expected_pubkey, _bump) = Pubkey::try_find_program_address( - igp_gas_payment_pda_seeds!(unique_gas_payment_pubkey), - &self.igp.program_id, - ) - .ok_or_else(|| { - ChainCommunicationError::from_other_str( - "Could not find program address for unique_gas_payment_pubkey", - ) - })?; - if expected_pubkey == pubkey { - valid_payment_pda_pubkey = Some(pubkey); - break; - } - } - - let valid_payment_pda_pubkey = valid_payment_pda_pubkey.ok_or_else(|| { - ChainCommunicationError::from_other_str("Could not find valid gas payment PDA pubkey") + let valid_payment_pda_pubkey = search_and_validate_account(accounts, |account| { + self.interchain_payment_account(account) })?; // Now that we have the valid gas payment PDA pubkey, we can get the full account data. @@ -224,6 +174,20 @@ impl SealevelInterchainGasPaymasterIndexer { H256::from(gas_payment_account.igp.to_bytes()), )) } + + fn interchain_payment_account(&self, account: &Account) -> ChainResult { + let unique_gas_payment_pubkey = Pubkey::new(&account.data); + let (expected_pubkey, _bump) = Pubkey::try_find_program_address( + igp_gas_payment_pda_seeds!(unique_gas_payment_pubkey), + &self.igp.program_id, + ) + .ok_or_else(|| { + ChainCommunicationError::from_other_str( + "Could not find program address for unique_gas_payment_pubkey", + ) + })?; + Ok(expected_pubkey) + } } #[async_trait] diff --git a/rust/main/chains/hyperlane-sealevel/src/lib.rs b/rust/main/chains/hyperlane-sealevel/src/lib.rs index 04e2218c6..941c64a7b 100644 --- a/rust/main/chains/hyperlane-sealevel/src/lib.rs +++ b/rust/main/chains/hyperlane-sealevel/src/lib.rs @@ -15,6 +15,7 @@ pub use solana_sdk::signer::keypair::Keypair; pub use trait_builder::*; pub use validator_announce::*; +mod account; mod error; mod interchain_gas; mod interchain_security_module; @@ -24,4 +25,6 @@ mod multisig_ism; mod provider; mod rpc; mod trait_builder; +mod transaction; +mod utils; mod validator_announce; diff --git a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs index 5e348d999..45e446127 100644 --- a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs @@ -4,22 +4,15 @@ use std::{collections::HashMap, num::NonZeroU64, ops::RangeInclusive, str::FromS use async_trait::async_trait; use borsh::{BorshDeserialize, BorshSerialize}; -use jsonrpc_core::futures_util::TryFutureExt; -use tracing::{debug, info, instrument, warn}; - -use hyperlane_core::{ - accumulator::incremental::IncrementalMerkle, BatchItem, ChainCommunicationError, - ChainCommunicationError::ContractError, ChainResult, Checkpoint, ContractLocator, Decode as _, - Encode as _, FixedPointNumber, HyperlaneAbi, HyperlaneChain, HyperlaneContract, - HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Indexed, Indexer, KnownHyperlaneDomain, - LogMeta, Mailbox, MerkleTreeHook, ReorgPeriod, SequenceAwareIndexer, TxCostEstimate, TxOutcome, - H256, H512, U256, -}; use hyperlane_sealevel_interchain_security_module_interface::{ InterchainSecurityModuleInstruction, VerifyInstruction, }; use hyperlane_sealevel_mailbox::{ - accounts::{DispatchedMessageAccount, InboxAccount, OutboxAccount}, + accounts::{ + DispatchedMessageAccount, InboxAccount, OutboxAccount, ProcessedMessage, + ProcessedMessageAccount, DISPATCHED_MESSAGE_DISCRIMINATOR, PROCESSED_MESSAGE_DISCRIMINATOR, + }, + instruction, instruction::InboxProcess, mailbox_dispatched_message_pda_seeds, mailbox_inbox_pda_seeds, mailbox_outbox_pda_seeds, mailbox_process_authority_pda_seeds, mailbox_processed_message_pda_seeds, @@ -27,6 +20,7 @@ use hyperlane_sealevel_mailbox::{ use hyperlane_sealevel_message_recipient_interface::{ HandleInstruction, MessageRecipientInstruction, }; +use jsonrpc_core::futures_util::TryFutureExt; use serializable_account_meta::SimulationReturnData; use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}; use solana_client::{ @@ -51,10 +45,24 @@ use solana_sdk::{ }; use solana_transaction_status::{ EncodedConfirmedBlock, EncodedTransaction, EncodedTransactionWithStatusMeta, TransactionStatus, - UiInnerInstructions, UiInstruction, UiMessage, UiParsedInstruction, UiReturnDataEncoding, - UiTransaction, UiTransactionReturnData, UiTransactionStatusMeta, + UiCompiledInstruction, UiInnerInstructions, UiInstruction, UiMessage, UiParsedInstruction, + UiReturnDataEncoding, UiTransaction, UiTransactionReturnData, UiTransactionStatusMeta, +}; +use tracing::{debug, info, instrument, warn}; + +use hyperlane_core::{ + accumulator::incremental::IncrementalMerkle, BatchItem, ChainCommunicationError, + ChainCommunicationError::ContractError, ChainResult, Checkpoint, ContractLocator, Decode as _, + Encode as _, FixedPointNumber, HyperlaneAbi, HyperlaneChain, HyperlaneContract, + HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Indexed, Indexer, KnownHyperlaneDomain, + LogMeta, Mailbox, MerkleTreeHook, ReorgPeriod, SequenceAwareIndexer, TxCostEstimate, TxOutcome, + H256, H512, U256, }; +use crate::account::{search_accounts_by_discriminator, search_and_validate_account}; +use crate::error::HyperlaneSealevelError; +use crate::transaction::search_dispatched_message_transactions; +use crate::utils::{decode_h256, decode_h512, from_base58}; use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; const SYSTEM_PROGRAM: &str = "11111111111111111111111111111111"; @@ -653,73 +661,26 @@ impl SealevelMailboxIndexer { self.rpc().get_block_height().await } - async fn get_message_with_nonce( + async fn get_dispatched_message_with_nonce( &self, nonce: u32, ) -> ChainResult<(Indexed, LogMeta)> { - let target_message_account_bytes = &[ - &hyperlane_sealevel_mailbox::accounts::DISPATCHED_MESSAGE_DISCRIMINATOR[..], - &nonce.to_le_bytes()[..], - ] - .concat(); - let target_message_account_bytes = base64::encode(target_message_account_bytes); - - // First, find all accounts with the matching account data. - // To keep responses small in case there is ever more than 1 - // match, we don't request the full account data, and just request - // the `unique_message_pubkey` field. - let memcmp = RpcFilterType::Memcmp(Memcmp { - // Ignore the first byte, which is the `initialized` bool flag. - offset: 1, - bytes: MemcmpEncodedBytes::Base64(target_message_account_bytes), - encoding: None, - }); - let config = RpcProgramAccountsConfig { - filters: Some(vec![memcmp]), - account_config: RpcAccountInfoConfig { - encoding: Some(UiAccountEncoding::Base64), - // Don't return any data - data_slice: Some(UiDataSliceConfig { - offset: 1 + 8 + 4 + 8, // the offset to get the `unique_message_pubkey` field - length: 32, // the length of the `unique_message_pubkey` field - }), - commitment: Some(CommitmentConfig::finalized()), - min_context_slot: None, - }, - with_context: Some(false), - }; - let accounts = self - .rpc() - .get_program_accounts_with_config(&self.mailbox.program_id, config) - .await?; - - // Now loop through matching accounts and find the one with a valid account pubkey - // that proves it's an actual message storage PDA. - let mut valid_message_storage_pda_pubkey = Option::::None; - - for (pubkey, account) in accounts { - let unique_message_pubkey = Pubkey::new(&account.data); - let (expected_pubkey, _bump) = Pubkey::try_find_program_address( - mailbox_dispatched_message_pda_seeds!(unique_message_pubkey), - &self.mailbox.program_id, - ) - .ok_or_else(|| { - ChainCommunicationError::from_other_str( - "Could not find program address for unique_message_pubkey", - ) - })?; - if expected_pubkey == pubkey { - valid_message_storage_pda_pubkey = Some(pubkey); - break; - } - } + let nonce_bytes = nonce.to_le_bytes(); + let unique_dispatched_message_pubkey_offset = 1 + 8 + 4 + 8; // the offset to get the `unique_message_pubkey` field + let unique_dispatch_message_pubkey_length = 32; // the length of the `unique_message_pubkey` field + let accounts = search_accounts_by_discriminator( + self.rpc(), + &self.program_id, + &DISPATCHED_MESSAGE_DISCRIMINATOR, + &nonce_bytes, + unique_dispatched_message_pubkey_offset, + unique_dispatch_message_pubkey_length, + ) + .await?; - let valid_message_storage_pda_pubkey = - valid_message_storage_pda_pubkey.ok_or_else(|| { - ChainCommunicationError::from_other_str( - "Could not find valid message storage PDA pubkey", - ) - })?; + let valid_message_storage_pda_pubkey = search_and_validate_account(accounts, |account| { + self.dispatched_message_account(&account) + })?; // Now that we have the valid message storage PDA pubkey, we can get the full account data. let account = self @@ -733,11 +694,99 @@ impl SealevelMailboxIndexer { let hyperlane_message = HyperlaneMessage::read_from(&mut &dispatched_message_account.encoded_message[..])?; + let block = self + .mailbox + .provider + .rpc() + .get_block(dispatched_message_account.slot) + .await?; + let block_hash = decode_h256(&block.blockhash)?; + + let transactions = + block.transactions.ok_or(HyperlaneSealevelError::NoTransactions("block which should contain message dispatch transaction does not contain any transaction".to_owned()))?; + + let transaction_hashes = search_dispatched_message_transactions( + &self.mailbox.program_id, + &valid_message_storage_pda_pubkey, + transactions, + ); + + // We expect to see that there is only one message dispatch transaction + if transaction_hashes.len() > 1 { + Err(HyperlaneSealevelError::TooManyTransactions("Block contains more than one dispatch message transaction operating on the same dispatch message store PDA".to_owned()))? + } + + let (transaction_index, transaction_hash) = transaction_hashes + .into_iter() + .next() + .ok_or(HyperlaneSealevelError::NoTransactions("block which should contain message dispatch transaction does not contain any after filtering".to_owned()))?; + Ok(( hyperlane_message.into(), LogMeta { address: self.mailbox.program_id.to_bytes().into(), block_number: dispatched_message_account.slot, + block_hash, + transaction_id: transaction_hash, + transaction_index: transaction_index as u64, + log_index: U256::from(nonce), + }, + )) + } + + fn dispatched_message_account(&self, account: &Account) -> ChainResult { + let unique_message_pubkey = Pubkey::new(&account.data); + let (expected_pubkey, _bump) = Pubkey::try_find_program_address( + mailbox_dispatched_message_pda_seeds!(unique_message_pubkey), + &self.mailbox.program_id, + ) + .ok_or_else(|| { + ChainCommunicationError::from_other_str( + "Could not find program address for unique message pubkey", + ) + })?; + Ok(expected_pubkey) + } + + async fn get_delivered_message_with_nonce( + &self, + nonce: u32, + ) -> ChainResult<(Indexed, LogMeta)> { + let nonce_bytes = nonce.to_le_bytes(); + let delivered_message_id_offset = 1 + 8 + 8; // the offset to get the `message_id` field + let delivered_message_id_length = 32; + let accounts = search_accounts_by_discriminator( + self.rpc(), + &self.program_id, + &PROCESSED_MESSAGE_DISCRIMINATOR, + &nonce_bytes, + delivered_message_id_offset, + delivered_message_id_length, + ) + .await?; + + debug!(account_len = ?accounts.len(), "Found accounts with processed message discriminator"); + + let valid_message_storage_pda_pubkey = search_and_validate_account(accounts, |account| { + self.delivered_message_account(&account) + })?; + + // Now that we have the valid delivered message storage PDA pubkey, + // we can get the full account data. + let account = self + .rpc() + .get_account_with_finalized_commitment(&valid_message_storage_pda_pubkey) + .await?; + let delivered_message_account = ProcessedMessageAccount::fetch(&mut account.data.as_ref()) + .map_err(ChainCommunicationError::from_other)? + .into_inner(); + let message_id = delivered_message_account.message_id; + + Ok(( + message_id.into(), + LogMeta { + address: self.mailbox.program_id.to_bytes().into(), + block_number: delivered_message_account.slot, // TODO: get these when building out scraper support. // It's inconvenient to get these :| block_hash: H256::zero(), @@ -747,6 +796,18 @@ impl SealevelMailboxIndexer { }, )) } + + fn delivered_message_account(&self, account: &Account) -> ChainResult { + let message_id = H256::from_slice(&account.data); + let (expected_pubkey, _bump) = Pubkey::try_find_program_address( + mailbox_processed_message_pda_seeds!(message_id), + &self.mailbox.program_id, + ) + .ok_or_else(|| { + ChainCommunicationError::from_other_str("Could not find program address for message id") + })?; + Ok(expected_pubkey) + } } #[async_trait] @@ -774,7 +835,7 @@ impl Indexer for SealevelMailboxIndexer { let message_capacity = range.end().saturating_sub(*range.start()); let mut messages = Vec::with_capacity(message_capacity as usize); for nonce in range { - messages.push(self.get_message_with_nonce(nonce).await?); + messages.push(self.get_dispatched_message_with_nonce(nonce).await?); } Ok(messages) } @@ -788,9 +849,19 @@ impl Indexer for SealevelMailboxIndexer { impl Indexer for SealevelMailboxIndexer { async fn fetch_logs_in_range( &self, - _range: RangeInclusive, + range: RangeInclusive, ) -> ChainResult, LogMeta)>> { - todo!() + info!( + ?range, + "Fetching SealevelMailboxIndexer HyperlaneMessage Delivery logs" + ); + + let message_capacity = range.end().saturating_sub(*range.start()); + let mut message_ids = Vec::with_capacity(message_capacity as usize); + for nonce in range { + message_ids.push(self.get_delivered_message_with_nonce(nonce).await?); + } + Ok(message_ids) } async fn get_finalized_block_number(&self) -> ChainResult { diff --git a/rust/main/chains/hyperlane-sealevel/src/provider.rs b/rust/main/chains/hyperlane-sealevel/src/provider.rs index 932a7191e..a0c5a41ea 100644 --- a/rust/main/chains/hyperlane-sealevel/src/provider.rs +++ b/rust/main/chains/hyperlane-sealevel/src/provider.rs @@ -1,14 +1,17 @@ -use std::{str::FromStr, sync::Arc}; +use std::sync::Arc; use async_trait::async_trait; +use solana_sdk::signature::Signature; +use solana_transaction_status::EncodedTransaction; + use hyperlane_core::{ - BlockInfo, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, HyperlaneProvider, - HyperlaneProviderError, TxnInfo, H256, H512, U256, + BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, HyperlaneChain, HyperlaneDomain, + HyperlaneProvider, HyperlaneProviderError, TxnInfo, TxnReceiptInfo, H256, H512, U256, }; -use solana_sdk::bs58; -use solana_sdk::pubkey::Pubkey; -use crate::{error::HyperlaneSealevelError, ConnectionConf, SealevelRpcClient}; +use crate::error::HyperlaneSealevelError; +use crate::utils::{decode_h256, decode_h512, decode_pubkey}; +use crate::{ConnectionConf, SealevelRpcClient}; /// A wrapper around a Sealevel provider to get generic blockchain information. #[derive(Debug)] @@ -50,10 +53,7 @@ impl HyperlaneProvider for SealevelProvider { async fn get_block_by_height(&self, slot: u64) -> ChainResult { let confirmed_block = self.rpc_client.get_block(slot).await?; - let hash_binary = bs58::decode(confirmed_block.blockhash) - .into_vec() - .map_err(HyperlaneSealevelError::Decoding)?; - let block_hash = H256::from_slice(&hash_binary); + let block_hash = decode_h256(&confirmed_block.blockhash)?; let block_time = confirmed_block .block_time @@ -68,8 +68,55 @@ impl HyperlaneProvider for SealevelProvider { Ok(block_info) } - async fn get_txn_by_hash(&self, _hash: &H512) -> ChainResult { - todo!() // FIXME + /// TODO This method is superfluous for Solana. + /// Since we have to request full block to find transaction hash and transaction index + /// for Solana, we have all the data about transaction mach earlier before this + /// method is invoked. + /// We can refactor abstractions so that our chain-agnostic code is more suitable + /// for all chains, not only Ethereum-like chains. + async fn get_txn_by_hash(&self, hash: &H512) -> ChainResult { + let signature = Signature::new(hash.as_bytes()); + let transaction = self.rpc_client.get_transaction(&signature).await?; + + let ui_transaction = match transaction.transaction.transaction { + EncodedTransaction::Json(t) => t, + t => Err(Into::::into( + HyperlaneSealevelError::UnsupportedTransactionEncoding(t), + ))?, + }; + + let received_signature = ui_transaction + .signatures + .first() + .ok_or(HyperlaneSealevelError::UnsignedTransaction(*hash))?; + let received_hash = decode_h512(received_signature)?; + + if &received_hash != hash { + Err(Into::::into( + HyperlaneSealevelError::IncorrectTransaction( + Box::new(*hash), + Box::new(received_hash), + ), + ))?; + } + + let receipt = TxnReceiptInfo { + gas_used: Default::default(), + cumulative_gas_used: Default::default(), + effective_gas_price: None, + }; + + Ok(TxnInfo { + hash: *hash, + gas_limit: Default::default(), + max_priority_fee_per_gas: None, + max_fee_per_gas: None, + gas_price: None, + nonce: 0, + sender: Default::default(), + recipient: None, + receipt: Some(receipt), + }) } async fn is_contract(&self, _address: &H256) -> ChainResult { @@ -78,7 +125,7 @@ impl HyperlaneProvider for SealevelProvider { } async fn get_balance(&self, address: String) -> ChainResult { - let pubkey = Pubkey::from_str(&address).map_err(Into::::into)?; + let pubkey = decode_pubkey(&address)?; self.rpc_client.get_balance(&pubkey).await } diff --git a/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs b/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs index 44ba2c8d5..88a474cbb 100644 --- a/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs +++ b/rust/main/chains/hyperlane-sealevel/src/rpc/client.rs @@ -1,10 +1,9 @@ use base64::Engine; use borsh::{BorshDeserialize, BorshSerialize}; -use hyperlane_core::{ChainCommunicationError, ChainResult, U256}; use serializable_account_meta::{SerializableAccountMeta, SimulationReturnData}; use solana_client::{ nonblocking::rpc_client::RpcClient, rpc_config::RpcBlockConfig, - rpc_config::RpcProgramAccountsConfig, rpc_response::Response, + rpc_config::RpcProgramAccountsConfig, rpc_config::RpcTransactionConfig, rpc_response::Response, }; use solana_sdk::{ account::Account, @@ -17,9 +16,12 @@ use solana_sdk::{ transaction::Transaction, }; use solana_transaction_status::{ - TransactionStatus, UiConfirmedBlock, UiReturnDataEncoding, UiTransactionReturnData, + EncodedConfirmedTransactionWithStatusMeta, TransactionStatus, UiConfirmedBlock, + UiReturnDataEncoding, UiTransactionReturnData, }; +use hyperlane_core::{ChainCommunicationError, ChainResult, U256}; + use crate::error::HyperlaneSealevelError; pub struct SealevelRpcClient(RpcClient); @@ -99,6 +101,17 @@ impl SealevelRpcClient { Ok(account) } + pub async fn get_balance(&self, pubkey: &Pubkey) -> ChainResult { + let balance = self + .0 + .get_balance(pubkey) + .await + .map_err(Into::::into) + .map_err(ChainCommunicationError::from)?; + + Ok(balance.into()) + } + pub async fn get_block(&self, height: u64) -> ChainResult { let config = RpcBlockConfig { commitment: Some(CommitmentConfig::finalized()), @@ -170,15 +183,19 @@ impl SealevelRpcClient { .map_err(ChainCommunicationError::from_other) } - pub async fn get_balance(&self, pubkey: &Pubkey) -> ChainResult { - let balance = self - .0 - .get_balance(pubkey) + pub async fn get_transaction( + &self, + signature: &Signature, + ) -> ChainResult { + let config = RpcTransactionConfig { + commitment: Some(CommitmentConfig::finalized()), + ..Default::default() + }; + self.0 + .get_transaction_with_config(signature, config) .await - .map_err(Into::::into) - .map_err(ChainCommunicationError::from)?; - - Ok(balance.into()) + .map_err(HyperlaneSealevelError::ClientError) + .map_err(Into::into) } pub async fn is_blockhash_valid(&self, hash: &Hash) -> ChainResult { diff --git a/rust/main/chains/hyperlane-sealevel/src/transaction.rs b/rust/main/chains/hyperlane-sealevel/src/transaction.rs new file mode 100644 index 000000000..26a0722cf --- /dev/null +++ b/rust/main/chains/hyperlane-sealevel/src/transaction.rs @@ -0,0 +1,188 @@ +use std::collections::HashMap; + +use hyperlane_sealevel_mailbox::instruction::Instruction; +use solana_sdk::pubkey::Pubkey; +use solana_transaction_status::option_serializer::OptionSerializer; +use solana_transaction_status::{ + EncodedTransaction, EncodedTransactionWithStatusMeta, UiCompiledInstruction, UiInstruction, + UiMessage, UiTransaction, UiTransactionStatusMeta, +}; +use tracing::warn; + +use hyperlane_core::H512; + +use crate::utils::{decode_h512, from_base58}; + +/// This function searches for a transaction which dispatches Hyperlane message and returns +/// list of hashes of such transactions. +/// +/// This function takes the mailbox program identifier and the identifier for PDA for storing +/// a dispatched message and searches a message dispatch transaction in a list of transaction. +/// The list of transaction is usually comes from a block. The function returns list of hashes +/// of such transactions. +/// +/// The transaction will be searched with the following criteria: +/// 1. Transaction contains Mailbox program id in the list of accounts. +/// 2. Transaction contains dispatched message PDA in the list of accounts. +/// 3. Transaction is performing message dispatch (OutboxDispatch). +/// +/// * `mailbox_program_id` - Identifier of Mailbox program +/// * `message_storage_pda_pubkey` - Identifier for dispatch message store PDA +/// * `transactions` - List of transactions +pub fn search_dispatched_message_transactions( + mailbox_program_id: &Pubkey, + message_storage_pda_pubkey: &Pubkey, + transactions: Vec, +) -> Vec<(usize, H512)> { + transactions + .into_iter() + .enumerate() + .filter_map(|(index, tx)| filter_by_encoding(tx).map(|(tx, meta)| (index, tx, meta))) + .filter_map(|(index, tx, meta)| { + filter_by_validity(tx, meta) + .map(|(hash, account_keys, instructions)| (index, hash, account_keys, instructions)) + }) + .filter_map(|(index, hash, account_keys, instructions)| { + filter_not_relevant( + mailbox_program_id, + message_storage_pda_pubkey, + hash, + account_keys, + instructions, + ) + .map(|hash| (index, hash)) + }) + .collect::>() +} + +fn filter_not_relevant( + mailbox_program_id: &Pubkey, + message_storage_pda_pubkey: &Pubkey, + hash: H512, + account_keys: Vec, + instructions: Vec, +) -> Option { + let account_index_map = account_index_map(account_keys); + + let mailbox_program_id_str = mailbox_program_id.to_string(); + let mailbox_program_index = match account_index_map.get(&mailbox_program_id_str) { + Some(i) => *i as u8, + None => return None, // If account keys do not contain Mailbox program, transaction is not message dispatch. + }; + + let message_storage_pda_pubkey_str = message_storage_pda_pubkey.to_string(); + let dispatch_message_pda_account_index = + match account_index_map.get(&message_storage_pda_pubkey_str) { + Some(i) => *i as u8, + None => return None, // If account keys do not contain dispatch message store PDA account, transaction is not message dispatch. + }; + + let mailbox_program_maybe = instructions + .into_iter() + .find(|instruction| instruction.program_id_index == mailbox_program_index); + + let mailbox_program = match mailbox_program_maybe { + Some(p) => p, + None => return None, // If transaction does not contain call into Mailbox, transaction is not message dispatch. + }; + + // If Mailbox program does not operate on dispatch message store PDA account, transaction is not message dispatch. + if !mailbox_program + .accounts + .contains(&dispatch_message_pda_account_index) + { + return None; + } + + let instruction_data = match from_base58(&mailbox_program.data) { + Ok(d) => d, + Err(_) => return None, // If we cannot decode instruction data, transaction is not message dispatch. + }; + + let instruction = match Instruction::from_instruction_data(&instruction_data) { + Ok(ii) => ii, + Err(_) => return None, // If we cannot parse instruction data, transaction is not message dispatch. + }; + + // If the call into Mailbox program is not OutboxDispatch, transaction is not message dispatch. + if !matches!(instruction, Instruction::OutboxDispatch(_)) { + return None; + } + + Some(hash) +} + +fn filter_by_validity( + tx: UiTransaction, + meta: UiTransactionStatusMeta, +) -> Option<(H512, Vec, Vec)> { + let Some(transaction_hash) = tx + .signatures + .first() + .map(|signature| decode_h512(signature)) + .and_then(|r| r.ok()) + else { + warn!( + transaction = ?tx, + "transaction does not have any signatures or signatures cannot be decoded", + ); + return None; + }; + + let UiMessage::Raw(message) = tx.message else { + warn!(message = ?tx.message, "we expect messages in Raw format"); + return None; + }; + + let instructions = instructions(message.instructions, meta); + + Some((transaction_hash, message.account_keys, instructions)) +} + +fn filter_by_encoding( + tx: EncodedTransactionWithStatusMeta, +) -> Option<(UiTransaction, UiTransactionStatusMeta)> { + match (tx.transaction, tx.meta) { + // We support only transactions encoded as JSON + // We need none-empty metadata as well + (EncodedTransaction::Json(t), Some(m)) => Some((t, m)), + t => { + warn!( + ?t, + "transaction is not encoded as json or metadata is empty" + ); + None + } + } +} + +fn account_index_map(account_keys: Vec) -> HashMap { + account_keys + .into_iter() + .enumerate() + .map(|(index, key)| (key, index)) + .collect::>() +} + +/// Extract all instructions from transaction +fn instructions( + instruction: Vec, + meta: UiTransactionStatusMeta, +) -> Vec { + let inner_instructions = match meta.inner_instructions { + OptionSerializer::Some(ii) => ii + .into_iter() + .flat_map(|ii| ii.instructions) + .flat_map(|ii| match ii { + UiInstruction::Compiled(ci) => Some(ci), + _ => None, + }) + .collect::>(), + OptionSerializer::None | OptionSerializer::Skip => vec![], + }; + + [instruction, inner_instructions].concat() +} + +#[cfg(test)] +mod tests; diff --git a/rust/main/chains/hyperlane-sealevel/src/transaction/tests.rs b/rust/main/chains/hyperlane-sealevel/src/transaction/tests.rs new file mode 100644 index 000000000..759f15de9 --- /dev/null +++ b/rust/main/chains/hyperlane-sealevel/src/transaction/tests.rs @@ -0,0 +1,329 @@ +use solana_transaction_status::EncodedTransactionWithStatusMeta; + +use crate::transaction::search_dispatched_message_transactions; +use crate::utils::decode_pubkey; + +#[test] +pub fn test_search_dispatched_message_transaction() { + // given + let mailbox_program_id = decode_pubkey("E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi").unwrap(); + let dispatched_message_pda_account = + decode_pubkey("6eG8PheL41qLFFUtPjSYMtsp4aoAQsMgcsYwkGCB8kwT").unwrap(); + let transaction = serde_json::from_str::(JSON).unwrap(); + let transactions = vec![transaction]; + + // when + let transaction_hashes = search_dispatched_message_transactions( + &mailbox_program_id, + &dispatched_message_pda_account, + transactions, + ); + + // then + assert!(!transaction_hashes.is_empty()); +} + +const JSON: &str = r#" +{ + "blockTime": 1729865514, + "meta": { + "computeUnitsConsumed": 171834, + "err": null, + "fee": 3564950, + "innerInstructions": [ + { + "index": 2, + "instructions": [ + { + "accounts": [ + 8, + 7, + 6, + 0 + ], + "data": "gCzo5F74HA9Pb", + "programIdIndex": 19, + "stackHeight": 2 + }, + { + "accounts": [ + 5, + 11, + 10, + 18, + 0, + 1, + 2 + ], + "data": "2Nsbnwq8JuYnSefHfRznxFtFqdPnbeydtt5kenfF8GR1ZU2XtF8jJDo4SUc2VY52V5C25WsKsQZBLsoCVQNzefgVj2bVznkThjuZuSKXJfZN9ADggiM2soRKVsAjf3xHm3CC3w3iyvK5U9LsjmYtiDNbJCFtEPRTDxsfvMS45Bg3q6EogmBN9JiZNLP", + "programIdIndex": 17, + "stackHeight": 2 + }, + { + "accounts": [ + 0, + 5 + ], + "data": "3Bxs3zrfFUZbEPqZ", + "programIdIndex": 10, + "stackHeight": 3 + }, + { + "accounts": [ + 0, + 2 + ], + "data": "11114XfZCGKrze4PNou1GXiYCJgiBCGpHks9hxjb8tFwYMjtgVtMzvriDxwYPdRqSoqztL", + "programIdIndex": 10, + "stackHeight": 3 + }, + { + "accounts": [ + 10, + 0, + 3, + 1, + 4, + 9, + 14 + ], + "data": "5MtKiLZhPB3NhS7Gus6CenAEMS2QBtpY9QtuLeVH4CkpUN7599vsYzZXhk8Vu", + "programIdIndex": 15, + "stackHeight": 2 + }, + { + "accounts": [ + 0, + 9 + ], + "data": "3Bxs4A3YxXXYy5gj", + "programIdIndex": 10, + "stackHeight": 3 + }, + { + "accounts": [ + 0, + 4 + ], + "data": "111158VjdPaAaGVkCbPZoXJqknHXBEqoypfVjf96mwePbKxAkrKfR2gUFyN7wD8ccc9g1z", + "programIdIndex": 10, + "stackHeight": 3 + } + ] + } + ], + "loadedAddresses": { + "readonly": [], + "writable": [] + }, + "logMessages": [ + "Program ComputeBudget111111111111111111111111111111 invoke [1]", + "Program ComputeBudget111111111111111111111111111111 success", + "Program ComputeBudget111111111111111111111111111111 invoke [1]", + "Program ComputeBudget111111111111111111111111111111 success", + "Program 3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm invoke [1]", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", + "Program log: Instruction: TransferChecked", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 6200 of 983051 compute units", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", + "Program E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi invoke [2]", + "Program 11111111111111111111111111111111 invoke [3]", + "Program 11111111111111111111111111111111 success", + "Program log: Protocol fee of 0 paid from FGyh1FfooV7AtVrYjFGmjMxbELC8RMxNp4xY5WY4L4md to BvZpTuYLAR77mPhH4GtvwEWUTs53GQqkgBNuXpCePVNk", + "Program 11111111111111111111111111111111 invoke [3]", + "Program 11111111111111111111111111111111 success", + "Program log: Dispatched message to 1408864445, ID 0x09c74f3e10d98c112696b72ba1609aae47616f64f28b4cb1ad8a4a710e93ee89", + "Program E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi consumed 86420 of 972001 compute units", + "Program return: E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi CcdPPhDZjBEmlrcroWCarkdhb2Tyi0yxrYpKcQ6T7ok=", + "Program E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi success", + "Program BhNcatUDC2D5JTyeaqrdSukiVFsEHK7e3hVmKMztwefv invoke [2]", + "Program 11111111111111111111111111111111 invoke [3]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [3]", + "Program 11111111111111111111111111111111 success", + "Program log: Paid IGP JAvHW21tYXE9dtdG83DReqU2b4LUexFuCbtJT5tF8X6M for 431000 gas for message 0x09c7…ee89 to 1408864445", + "Program BhNcatUDC2D5JTyeaqrdSukiVFsEHK7e3hVmKMztwefv consumed 42792 of 882552 compute units", + "Program BhNcatUDC2D5JTyeaqrdSukiVFsEHK7e3hVmKMztwefv success", + "Program log: Warp route transfer completed to destination: 1408864445, recipient: 0xd41b…f050, remote_amount: 2206478600", + "Program 3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm consumed 171534 of 999700 compute units", + "Program 3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm success" + ], + "postBalances": [ + 12374928, + 0, + 2241120, + 1016160, + 1872240, + 8679120, + 2039280, + 319231603414, + 2039280, + 10172586528, + 1, + 890880, + 1141440, + 3361680, + 1830480, + 1141440, + 1, + 1141440, + 1141440, + 934087680 + ], + "postTokenBalances": [ + { + "accountIndex": 6, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "owner": "CcquFeCYNZM48kLPyG3HWxdwgigmyxPBi6iHwve9Myhj", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "uiTokenAmount": { + "amount": "165697511204", + "decimals": 6, + "uiAmount": 165697.511204, + "uiAmountString": "165697.511204" + } + }, + { + "accountIndex": 8, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "owner": "FGyh1FfooV7AtVrYjFGmjMxbELC8RMxNp4xY5WY4L4md", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "uiTokenAmount": { + "amount": "94", + "decimals": 6, + "uiAmount": 9.4E-5, + "uiAmountString": "0.000094" + } + } + ], + "preBalances": [ + 22211372, + 0, + 0, + 1016160, + 0, + 8679120, + 2039280, + 319231603414, + 2039280, + 10170428394, + 1, + 890880, + 1141440, + 3361680, + 1830480, + 1141440, + 1, + 1141440, + 1141440, + 934087680 + ], + "preTokenBalances": [ + { + "accountIndex": 6, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "owner": "CcquFeCYNZM48kLPyG3HWxdwgigmyxPBi6iHwve9Myhj", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "uiTokenAmount": { + "amount": "163491032604", + "decimals": 6, + "uiAmount": 163491.032604, + "uiAmountString": "163491.032604" + } + }, + { + "accountIndex": 8, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "owner": "FGyh1FfooV7AtVrYjFGmjMxbELC8RMxNp4xY5WY4L4md", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "uiTokenAmount": { + "amount": "2206478694", + "decimals": 6, + "uiAmount": 2206.478694, + "uiAmountString": "2206.478694" + } + } + ], + "rewards": [], + "status": { + "Ok": null + } + }, + "slot": 297626301, + "transaction": { + "message": { + "accountKeys": [ + "FGyh1FfooV7AtVrYjFGmjMxbELC8RMxNp4xY5WY4L4md", + "8DqWVhEZcg4rDYwe5UFaopmGuEajiPz9L3A1ZnytMcUm", + "6eG8PheL41qLFFUtPjSYMtsp4aoAQsMgcsYwkGCB8kwT", + "8Cv4PHJ6Cf3xY7dse7wYeZKtuQv9SAN6ujt5w22a2uho", + "9yMwrDqHsbmmvYPS9h4MLPbe2biEykcL51W7qJSDL5hF", + "BvZpTuYLAR77mPhH4GtvwEWUTs53GQqkgBNuXpCePVNk", + "CcquFeCYNZM48kLPyG3HWxdwgigmyxPBi6iHwve9Myhj", + "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "FDDbaNtod9pt7pmR8qtmRZJtEj9NViDA7J6cazqUjXQj", + "JAvHW21tYXE9dtdG83DReqU2b4LUexFuCbtJT5tF8X6M", + "11111111111111111111111111111111", + "37N3sbyVAd3KvQsPw42i1LWkLahzL4ninVQ4n1NmnHjS", + "3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm", + "AHX3iiEPFMyygANrp15cyUr63o9qGkwkB6ki1pgpZ7gZ", + "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF", + "BhNcatUDC2D5JTyeaqrdSukiVFsEHK7e3hVmKMztwefv", + "ComputeBudget111111111111111111111111111111", + "E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi", + "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV", + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + ], + "header": { + "numReadonlySignedAccounts": 1, + "numReadonlyUnsignedAccounts": 10, + "numRequiredSignatures": 2 + }, + "instructions": [ + { + "accounts": [], + "data": "FjL4FH", + "programIdIndex": 16, + "stackHeight": null + }, + { + "accounts": [], + "data": "3butUEijJrLf", + "programIdIndex": 16, + "stackHeight": null + }, + { + "accounts": [ + 10, + 18, + 13, + 17, + 5, + 11, + 0, + 1, + 2, + 15, + 3, + 4, + 14, + 9, + 19, + 7, + 8, + 6 + ], + "data": "RpjV6TtUSvt6UnMXdNo4h1Ze2VGVifo65r2jqRBUq6HJKhskSnwWybXyB4NxgfvedV9vhKdmDPg8sFT64JEZvxF8VfoGdqoAFt4WFLSB", + "programIdIndex": 12, + "stackHeight": null + } + ], + "recentBlockhash": "GHQhVUy7Eq3hcps8YoG9DCd1Tb6ccQZ9xhh81ju8ujHJ" + }, + "signatures": [ + "4nRGgV9tqCuiKUXeBzWdvdk6YC9BsGWUZurAVQLMX1NwNPpysbZNwXu97Sw4aM9REwaRmWS7gaiSKXbwtmw6oLRi", + "hXjvQbAuFH9vAxZMdGqfnSjN7t7Z7NLTzRq1SG8i6fLr9LS6XahTduPWqakiTsLDyWSofvq3MSncUAkbQLEj85f" + ] + } +} +"#; diff --git a/rust/main/chains/hyperlane-sealevel/src/utils.rs b/rust/main/chains/hyperlane-sealevel/src/utils.rs new file mode 100644 index 000000000..56b8202c6 --- /dev/null +++ b/rust/main/chains/hyperlane-sealevel/src/utils.rs @@ -0,0 +1,33 @@ +use std::str::FromStr; + +use solana_sdk::bs58; +use solana_sdk::pubkey::Pubkey; + +use hyperlane_core::{H256, H512}; + +use crate::error::HyperlaneSealevelError; + +pub fn from_base58(base58: &str) -> Result, HyperlaneSealevelError> { + let binary = bs58::decode(base58) + .into_vec() + .map_err(HyperlaneSealevelError::Decoding)?; + Ok(binary) +} + +pub fn decode_h256(base58: &str) -> Result { + let binary = from_base58(base58)?; + let hash = H256::from_slice(&binary); + + Ok(hash) +} + +pub fn decode_h512(base58: &str) -> Result { + let binary = from_base58(base58)?; + let hash = H512::from_slice(&binary); + + Ok(hash) +} + +pub fn decode_pubkey(address: &str) -> Result { + Pubkey::from_str(address).map_err(Into::::into) +} From 1c0ef45c35e8b45d4bfe67a08a34626bb28491be Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Wed, 30 Oct 2024 18:10:29 +0000 Subject: [PATCH 222/224] feat: add new ezETH addresses to app contexts (#4789) ### Description This was missed in the recent chain addition. We should consolidate this with what exists in the registry - the duplication in infra is too much atm now that we're kicking into high gear with warp routes. Deployed the relayer with this change ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- .../warp/renzo-ezETH-addresses-v3.json | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v3.json b/typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v3.json index 97fd3082b..e5c7023b2 100644 --- a/typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v3.json +++ b/typescript/infra/config/environments/mainnet3/warp/renzo-ezETH-addresses-v3.json @@ -2,9 +2,6 @@ "arbitrum": { "xERC20": "0xB26bBfC6d1F469C821Ea25099017862e7368F4E8" }, - "optimism": { - "xERC20": "0xacEB607CdF59EB8022Cc0699eEF3eCF246d149e2" - }, "base": { "xERC20": "0x2552516453368e42705D791F674b312b8b87CD9e" }, @@ -14,18 +11,27 @@ "bsc": { "xERC20": "0xE00C6185a5c19219F1FFeD213b4406a254968c26" }, - "mode": { - "xERC20": "0xC59336D8edDa9722B4f1Ec104007191Ec16f7087" - }, - "linea": { - "xERC20": "0xC59336D8edDa9722B4f1Ec104007191Ec16f7087" - }, "ethereum": { "xERC20Lockbox": "0xC59336D8edDa9722B4f1Ec104007191Ec16f7087" }, "fraxtal": { "xERC20": "0x3aE8635A4D581d40a6Edfb3f2ED480f9532994F5" }, + "linea": { + "xERC20": "0xC59336D8edDa9722B4f1Ec104007191Ec16f7087" + }, + "mode": { + "xERC20": "0xC59336D8edDa9722B4f1Ec104007191Ec16f7087" + }, + "optimism": { + "xERC20": "0xacEB607CdF59EB8022Cc0699eEF3eCF246d149e2" + }, + "sei": { + "xERC20": "0xE5163F148C82a0818545d5D34e30BC1EDA870cB9" + }, + "taiko": { + "xERC20": "0x5eAFB1D4b5BDFaFE81715EeBcC7713e418C80E78" + }, "zircuit": { "xERC20": "0x2552516453368e42705D791F674b312b8b87CD9e" } From 469f2f34030d9539f2038df302195b6a2dbc94c6 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Thu, 31 Oct 2024 06:55:59 +0530 Subject: [PATCH 223/224] fix(contracts): quote management for L2->L1 hooks (#4552) ### Description - check for sufficient fees in `AbstractMessageIdAuthHook` and refund surplus - add a child hook to OPL2ToL1Hook and ArbL2ToL1Hook to use the igp to pay for the destination gas fees ~~Note: LayerzeroL2Hook currently also refunds from msg.value, will make it into issue to be fixed later as we're using the layerzero hooks right now.~~ ### Drive-by changes - None ### Related issues - fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/10 ### Backward compatibility No ### Testing Fuzz --- .changeset/cuddly-baboons-drive.md | 6 ++ solidity/contracts/hooks/ArbL2ToL1Hook.sol | 35 +++++--- solidity/contracts/hooks/OPL2ToL1Hook.sol | 35 +++++--- solidity/contracts/hooks/OPStackHook.sol | 15 ++-- solidity/contracts/hooks/PolygonPosHook.sol | 13 ++- .../hooks/aggregation/ERC5164Hook.sol | 11 ++- .../hooks/layer-zero/LayerZeroV2Hook.sol | 14 +++- .../hooks/libs/AbstractMessageIdAuthHook.sol | 30 +++++-- solidity/script/DeployArbHook.s.sol | 84 ------------------- .../hooks/layerzero/LayerZeroV2Hook.t.sol | 10 +-- solidity/test/isms/ArbL2ToL1Ism.t.sol | 20 ++++- solidity/test/isms/ERC5164ISM.t.sol | 2 + solidity/test/isms/ExternalBridgeTest.sol | 45 ++++++++-- solidity/test/isms/OPL2ToL1Ism.t.sol | 23 ++++- typescript/sdk/src/hook/EvmHookModule.ts | 4 +- typescript/sdk/src/hook/EvmHookReader.ts | 3 + typescript/sdk/src/hook/schemas.ts | 1 + .../ism/metadata/arbL2ToL1.hardhat-test.ts | 25 ++++-- 18 files changed, 222 insertions(+), 154 deletions(-) create mode 100644 .changeset/cuddly-baboons-drive.md delete mode 100644 solidity/script/DeployArbHook.s.sol diff --git a/.changeset/cuddly-baboons-drive.md b/.changeset/cuddly-baboons-drive.md new file mode 100644 index 000000000..b5a02fb3d --- /dev/null +++ b/.changeset/cuddly-baboons-drive.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/sdk': minor +'@hyperlane-xyz/core': minor +--- + +Checking for sufficient fees in `AbstractMessageIdAuthHook` and refund surplus diff --git a/solidity/contracts/hooks/ArbL2ToL1Hook.sol b/solidity/contracts/hooks/ArbL2ToL1Hook.sol index 488dabc1e..76c67c0ec 100644 --- a/solidity/contracts/hooks/ArbL2ToL1Hook.sol +++ b/solidity/contracts/hooks/ArbL2ToL1Hook.sol @@ -14,17 +14,16 @@ pragma solidity >=0.8.0; @@@@@@@@@ @@@@@@@@*/ // ============ Internal Imports ============ +import {Message} from "../libs/Message.sol"; +import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {AbstractPostDispatchHook} from "./libs/AbstractMessageIdAuthHook.sol"; import {AbstractMessageIdAuthHook} from "./libs/AbstractMessageIdAuthHook.sol"; -import {Mailbox} from "../Mailbox.sol"; +import {AbstractMessageIdAuthorizedIsm} from "../isms/hook/AbstractMessageIdAuthorizedIsm.sol"; import {StandardHookMetadata} from "./libs/StandardHookMetadata.sol"; import {Message} from "../libs/Message.sol"; import {TypeCasts} from "../libs/TypeCasts.sol"; -import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; -import {MailboxClient} from "../client/MailboxClient.sol"; // ============ External Imports ============ -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {ArbSys} from "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; /** @@ -35,13 +34,14 @@ import {ArbSys} from "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; */ contract ArbL2ToL1Hook is AbstractMessageIdAuthHook { using StandardHookMetadata for bytes; + using Message for bytes; // ============ Constants ============ // precompile contract on L2 for sending messages to L1 ArbSys public immutable arbSys; - // Immutable quote amount - uint256 public immutable GAS_QUOTE; + // child hook to call first + IPostDispatchHook public immutable childHook; // ============ Constructor ============ @@ -50,21 +50,24 @@ contract ArbL2ToL1Hook is AbstractMessageIdAuthHook { uint32 _destinationDomain, bytes32 _ism, address _arbSys, - uint256 _gasQuote + address _childHook ) AbstractMessageIdAuthHook(_mailbox, _destinationDomain, _ism) { arbSys = ArbSys(_arbSys); - GAS_QUOTE = _gasQuote; + childHook = AbstractPostDispatchHook(_childHook); } + /// @inheritdoc IPostDispatchHook function hookType() external pure override returns (uint8) { return uint8(IPostDispatchHook.Types.ARB_L2_TO_L1); } + /// @inheritdoc AbstractPostDispatchHook function _quoteDispatch( - bytes calldata, - bytes calldata + bytes calldata metadata, + bytes calldata message ) internal view override returns (uint256) { - return GAS_QUOTE; + return + metadata.msgValue(0) + childHook.quoteDispatch(metadata, message); } // ============ Internal functions ============ @@ -72,8 +75,16 @@ contract ArbL2ToL1Hook is AbstractMessageIdAuthHook { /// @inheritdoc AbstractMessageIdAuthHook function _sendMessageId( bytes calldata metadata, - bytes memory payload + bytes calldata message ) internal override { + bytes memory payload = abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + message.id() + ); + + childHook.postDispatch{ + value: childHook.quoteDispatch(metadata, message) + }(metadata, message); arbSys.sendTxToL1{value: metadata.msgValue(0)}( TypeCasts.bytes32ToAddress(ism), payload diff --git a/solidity/contracts/hooks/OPL2ToL1Hook.sol b/solidity/contracts/hooks/OPL2ToL1Hook.sol index 7d0fcf36a..e82f4f4ab 100644 --- a/solidity/contracts/hooks/OPL2ToL1Hook.sol +++ b/solidity/contracts/hooks/OPL2ToL1Hook.sol @@ -14,10 +14,13 @@ pragma solidity >=0.8.0; @@@@@@@@@ @@@@@@@@*/ // ============ Internal Imports ============ +import {Message} from "../libs/Message.sol"; import {AbstractPostDispatchHook, AbstractMessageIdAuthHook} from "./libs/AbstractMessageIdAuthHook.sol"; +import {AbstractMessageIdAuthorizedIsm} from "../isms/hook/AbstractMessageIdAuthorizedIsm.sol"; import {StandardHookMetadata} from "./libs/StandardHookMetadata.sol"; import {TypeCasts} from "../libs/TypeCasts.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; +import {InterchainGasPaymaster} from "./igp/InterchainGasPaymaster.sol"; // ============ External Imports ============ import {ICrossDomainMessenger} from "../interfaces/optimism/ICrossDomainMessenger.sol"; @@ -30,13 +33,16 @@ import {ICrossDomainMessenger} from "../interfaces/optimism/ICrossDomainMessenge */ contract OPL2ToL1Hook is AbstractMessageIdAuthHook { using StandardHookMetadata for bytes; + using Message for bytes; // ============ Constants ============ // precompile contract on L2 for sending messages to L1 ICrossDomainMessenger public immutable l2Messenger; - // Immutable quote amount - uint32 public immutable GAS_QUOTE; + // child hook to call first + IPostDispatchHook public immutable childHook; + // Minimum gas limit that the message can be executed with - OP specific + uint32 public constant MIN_GAS_LIMIT = 300_000; // ============ Constructor ============ @@ -45,10 +51,10 @@ contract OPL2ToL1Hook is AbstractMessageIdAuthHook { uint32 _destinationDomain, bytes32 _ism, address _l2Messenger, - uint32 _gasQuote + address _childHook ) AbstractMessageIdAuthHook(_mailbox, _destinationDomain, _ism) { - GAS_QUOTE = _gasQuote; l2Messenger = ICrossDomainMessenger(_l2Messenger); + childHook = AbstractPostDispatchHook(_childHook); } /// @inheritdoc IPostDispatchHook @@ -58,10 +64,11 @@ contract OPL2ToL1Hook is AbstractMessageIdAuthHook { /// @inheritdoc AbstractPostDispatchHook function _quoteDispatch( - bytes calldata, - bytes calldata + bytes calldata metadata, + bytes calldata message ) internal view override returns (uint256) { - return GAS_QUOTE; + return + metadata.msgValue(0) + childHook.quoteDispatch(metadata, message); } // ============ Internal functions ============ @@ -69,16 +76,20 @@ contract OPL2ToL1Hook is AbstractMessageIdAuthHook { /// @inheritdoc AbstractMessageIdAuthHook function _sendMessageId( bytes calldata metadata, - bytes memory payload + bytes calldata message ) internal override { - require( - msg.value >= metadata.msgValue(0) + GAS_QUOTE, - "OPL2ToL1Hook: insufficient msg.value" + bytes memory payload = abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + message.id() ); + + childHook.postDispatch{ + value: childHook.quoteDispatch(metadata, message) + }(metadata, message); l2Messenger.sendMessage{value: metadata.msgValue(0)}( TypeCasts.bytes32ToAddress(ism), payload, - GAS_QUOTE + MIN_GAS_LIMIT ); } } diff --git a/solidity/contracts/hooks/OPStackHook.sol b/solidity/contracts/hooks/OPStackHook.sol index a0a33dabc..0ddb713d3 100644 --- a/solidity/contracts/hooks/OPStackHook.sol +++ b/solidity/contracts/hooks/OPStackHook.sol @@ -18,6 +18,7 @@ import {AbstractMessageIdAuthHook} from "./libs/AbstractMessageIdAuthHook.sol"; import {StandardHookMetadata} from "./libs/StandardHookMetadata.sol"; import {TypeCasts} from "../libs/TypeCasts.sol"; import {Message} from "../libs/Message.sol"; +import {AbstractMessageIdAuthorizedIsm} from "../isms/hook/AbstractMessageIdAuthorizedIsm.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; // ============ External Imports ============ @@ -32,6 +33,7 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; */ contract OPStackHook is AbstractMessageIdAuthHook { using StandardHookMetadata for bytes; + using Message for bytes; // ============ Constants ============ @@ -60,21 +62,22 @@ contract OPStackHook is AbstractMessageIdAuthHook { // ============ Internal functions ============ function _quoteDispatch( - bytes calldata, + bytes calldata metadata, bytes calldata ) internal pure override returns (uint256) { - return 0; // gas subsidized by the L2 + return metadata.msgValue(0); // gas subsidized by the L2 } /// @inheritdoc AbstractMessageIdAuthHook function _sendMessageId( bytes calldata metadata, - bytes memory payload + bytes calldata message ) internal override { - require( - metadata.msgValue(0) < 2 ** 255, - "OPStackHook: msgValue must be less than 2 ** 255" + bytes memory payload = abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + message.id() ); + l1Messenger.sendMessage{value: metadata.msgValue(0)}( TypeCasts.bytes32ToAddress(ism), payload, diff --git a/solidity/contracts/hooks/PolygonPosHook.sol b/solidity/contracts/hooks/PolygonPosHook.sol index 6831f9a33..2959adc3d 100644 --- a/solidity/contracts/hooks/PolygonPosHook.sol +++ b/solidity/contracts/hooks/PolygonPosHook.sol @@ -19,6 +19,7 @@ import {StandardHookMetadata} from "./libs/StandardHookMetadata.sol"; import {TypeCasts} from "../libs/TypeCasts.sol"; import {Message} from "../libs/Message.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; +import {AbstractMessageIdAuthorizedIsm} from "../isms/hook/AbstractMessageIdAuthorizedIsm.sol"; // ============ External Imports ============ import {FxBaseRootTunnel} from "fx-portal/contracts/tunnel/FxBaseRootTunnel.sol"; @@ -31,6 +32,7 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; */ contract PolygonPosHook is AbstractMessageIdAuthHook, FxBaseRootTunnel { using StandardHookMetadata for bytes; + using Message for bytes; // ============ Constructor ============ @@ -56,22 +58,27 @@ contract PolygonPosHook is AbstractMessageIdAuthHook, FxBaseRootTunnel { // ============ Internal functions ============ function _quoteDispatch( - bytes calldata, + bytes calldata metadata, bytes calldata ) internal pure override returns (uint256) { - return 0; + return metadata.msgValue(0); } /// @inheritdoc AbstractMessageIdAuthHook function _sendMessageId( bytes calldata metadata, - bytes memory payload + bytes calldata message ) internal override { require( metadata.msgValue(0) == 0, "PolygonPosHook: does not support msgValue" ); require(msg.value == 0, "PolygonPosHook: does not support msgValue"); + + bytes memory payload = abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + message.id() + ); _sendMessageToChild(payload); } diff --git a/solidity/contracts/hooks/aggregation/ERC5164Hook.sol b/solidity/contracts/hooks/aggregation/ERC5164Hook.sol index 8cfc80f06..ece1bf80d 100644 --- a/solidity/contracts/hooks/aggregation/ERC5164Hook.sol +++ b/solidity/contracts/hooks/aggregation/ERC5164Hook.sol @@ -15,9 +15,11 @@ pragma solidity >=0.8.0; // ============ Internal Imports ============ import {TypeCasts} from "../../libs/TypeCasts.sol"; +import {Message} from "../../libs/Message.sol"; import {IPostDispatchHook} from "../../interfaces/hooks/IPostDispatchHook.sol"; import {IMessageDispatcher} from "../../interfaces/hooks/IMessageDispatcher.sol"; import {AbstractMessageIdAuthHook} from "../libs/AbstractMessageIdAuthHook.sol"; +import {AbstractMessageIdAuthorizedIsm} from "../../isms/hook/AbstractMessageIdAuthorizedIsm.sol"; // ============ External Imports ============ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; @@ -28,6 +30,8 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; * any of the 5164 adapters. */ contract ERC5164Hook is AbstractMessageIdAuthHook { + using Message for bytes; + IMessageDispatcher public immutable dispatcher; constructor( @@ -55,9 +59,14 @@ contract ERC5164Hook is AbstractMessageIdAuthHook { function _sendMessageId( bytes calldata, /* metadata */ - bytes memory payload + bytes calldata message ) internal override { require(msg.value == 0, "ERC5164Hook: no value allowed"); + + bytes memory payload = abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + message.id() + ); dispatcher.dispatchMessage( destinationDomain, TypeCasts.bytes32ToAddress(ism), diff --git a/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol b/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol index 244fea5c7..3a0955e59 100644 --- a/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol +++ b/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol @@ -18,6 +18,7 @@ import {TypeCasts} from "../../libs/TypeCasts.sol"; import {Indexed} from "../../libs/Indexed.sol"; import {IPostDispatchHook} from "../../interfaces/hooks/IPostDispatchHook.sol"; import {AbstractMessageIdAuthHook} from "../libs/AbstractMessageIdAuthHook.sol"; +import {AbstractMessageIdAuthorizedIsm} from "../../isms/hook/AbstractMessageIdAuthorizedIsm.sol"; import {StandardHookMetadata} from "../libs/StandardHookMetadata.sol"; struct LayerZeroV2Metadata { @@ -55,8 +56,13 @@ contract LayerZeroV2Hook is AbstractMessageIdAuthHook { /// @inheritdoc AbstractMessageIdAuthHook function _sendMessageId( bytes calldata metadata, - bytes memory payload + bytes calldata message ) internal override { + bytes memory payload = abi.encodeCall( + AbstractMessageIdAuthorizedIsm.verifyMessageId, + message.id() + ); + bytes calldata lZMetadata = metadata.getCustomMetadata(); ( uint32 eid, @@ -72,7 +78,9 @@ contract LayerZeroV2Hook is AbstractMessageIdAuthHook { options, false // payInLzToken ); - lZEndpoint.send{value: msg.value}(msgParams, refundAddress); + + uint256 quote = _quoteDispatch(metadata, message); + lZEndpoint.send{value: quote}(msgParams, refundAddress); } /// @dev payInZRO is hardcoded to false because zro tokens should not be directly accepted @@ -96,7 +104,7 @@ contract LayerZeroV2Hook is AbstractMessageIdAuthHook { message.senderAddress() ); - return msgFee.nativeFee; + return metadata.msgValue(0) + msgFee.nativeFee; } /** diff --git a/solidity/contracts/hooks/libs/AbstractMessageIdAuthHook.sol b/solidity/contracts/hooks/libs/AbstractMessageIdAuthHook.sol index a9e3a41e9..05c2c1d08 100644 --- a/solidity/contracts/hooks/libs/AbstractMessageIdAuthHook.sol +++ b/solidity/contracts/hooks/libs/AbstractMessageIdAuthHook.sol @@ -22,6 +22,9 @@ import {Message} from "../../libs/Message.sol"; import {StandardHookMetadata} from "./StandardHookMetadata.sol"; import {MailboxClient} from "../../client/MailboxClient.sol"; +// ============ External Imports ============ +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; + /** * @title AbstractMessageIdAuthHook * @notice Message hook to inform an Abstract Message ID ISM of messages published through @@ -31,8 +34,10 @@ abstract contract AbstractMessageIdAuthHook is AbstractPostDispatchHook, MailboxClient { + using Address for address payable; using StandardHookMetadata for bytes; using Message for bytes; + using TypeCasts for bytes32; // ============ Constants ============ @@ -68,7 +73,7 @@ abstract contract AbstractMessageIdAuthHook is function _postDispatch( bytes calldata metadata, bytes calldata message - ) internal override { + ) internal virtual override { bytes32 id = message.id(); require( _isLatestDispatched(id), @@ -82,20 +87,29 @@ abstract contract AbstractMessageIdAuthHook is metadata.msgValue(0) < 2 ** 255, "AbstractMessageIdAuthHook: msgValue must be less than 2 ** 255" ); - bytes memory payload = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - id - ); - _sendMessageId(metadata, payload); + + _sendMessageId(metadata, message); + + uint256 _overpayment = msg.value - _quoteDispatch(metadata, message); + if (_overpayment > 0) { + address _refundAddress = metadata.refundAddress( + message.sender().bytes32ToAddress() + ); + require( + _refundAddress != address(0), + "AbstractPostDispatchHook: no refund address" + ); + payable(_refundAddress).sendValue(_overpayment); + } } /** * @notice Send a message to the ISM. * @param metadata The metadata for the hook caller - * @param payload The payload for call to the ISM + * @param message The message to send to the ISM */ function _sendMessageId( bytes calldata metadata, - bytes memory payload + bytes calldata message ) internal virtual; } diff --git a/solidity/script/DeployArbHook.s.sol b/solidity/script/DeployArbHook.s.sol deleted file mode 100644 index 89f35f8d4..000000000 --- a/solidity/script/DeployArbHook.s.sol +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity >=0.8.0; - -import "forge-std/Script.sol"; - -import {Mailbox} from "../../contracts/Mailbox.sol"; -import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; -import {ArbL2ToL1Hook} from "../../contracts/hooks/ArbL2ToL1Hook.sol"; -import {ArbL2ToL1Ism} from "../../contracts/isms/hook/ArbL2ToL1Ism.sol"; -import {TestRecipient} from "../../contracts/test/TestRecipient.sol"; -import {TestIsm} from "../../contracts/test/TestIsm.sol"; - -contract DeployArbHook is Script { - uint256 deployerPrivateKey; - - ArbL2ToL1Hook hook; - ArbL2ToL1Ism ism; - - uint32 constant L1_DOMAIN = 11155111; - address constant L1_MAILBOX = 0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766; - address constant L1_BRIDGE = 0x38f918D0E9F1b721EDaA41302E399fa1B79333a9; - address constant L1_ISM = 0x096A1c034c7Ad113B6dB786b7BA852cB67025458; // placeholder - bytes32 TEST_RECIPIENT = - 0x000000000000000000000000155b1cd2f7cbc58d403b9be341fab6cd77425175; // placeholder - - address constant ARBSYS = 0x0000000000000000000000000000000000000064; - address constant L2_MAILBOX = 0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8; - address constant L2_HOOK = 0xd9d99AC1C645563576b8Df22cBebFC23FB60Ec73; // placeholder - - function deployIsm() external { - deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY"); - - vm.startBroadcast(deployerPrivateKey); - - ism = new ArbL2ToL1Ism(L1_BRIDGE); - - TestRecipient testRecipient = new TestRecipient(); - testRecipient.setInterchainSecurityModule(address(ism)); - - vm.stopBroadcast(); - } - - function deployHook() external { - deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY"); - - vm.startBroadcast(deployerPrivateKey); - - hook = new ArbL2ToL1Hook( - L2_MAILBOX, - L1_DOMAIN, - TypeCasts.addressToBytes32(L1_ISM), - ARBSYS, - 200_000 // estimated gas amount used for verify - ); - - vm.stopBroadcast(); - } - - function deployTestRecipient() external { - deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY"); - - vm.startBroadcast(deployerPrivateKey); - - TestIsm noopIsm = new TestIsm(); - noopIsm.setVerify(true); - TestRecipient testRecipient = new TestRecipient(); - testRecipient.setInterchainSecurityModule(address(noopIsm)); - - console.log("TestRecipient address: %s", address(testRecipient)); - - vm.stopBroadcast(); - } - - function setAuthorizedHook() external { - deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY"); - - vm.startBroadcast(deployerPrivateKey); - - ism = ArbL2ToL1Ism(L1_ISM); - ism.setAuthorizedHook(TypeCasts.addressToBytes32(L2_HOOK)); - - vm.stopBroadcast(); - } -} diff --git a/solidity/test/hooks/layerzero/LayerZeroV2Hook.t.sol b/solidity/test/hooks/layerzero/LayerZeroV2Hook.t.sol index 94225d287..8b5d6004c 100644 --- a/solidity/test/hooks/layerzero/LayerZeroV2Hook.t.sol +++ b/solidity/test/hooks/layerzero/LayerZeroV2Hook.t.sol @@ -147,15 +147,7 @@ contract LayerZeroV2HookTest is Test { vm.assume(balance < nativeFee - 1); vm.deal(address(this), balance); - vm.expectRevert( - abi.encodeWithSelector( - Errors.InsufficientFee.selector, - 100, - balance, - 0, - 0 - ) - ); + vm.expectRevert(); // OutOfFunds mailbox.dispatch{value: balance}( HYPERLANE_DEST_DOMAIN, address(crossChainCounterApp).addressToBytes32(), diff --git a/solidity/test/isms/ArbL2ToL1Ism.t.sol b/solidity/test/isms/ArbL2ToL1Ism.t.sol index a251cfda4..c44665cb5 100644 --- a/solidity/test/isms/ArbL2ToL1Ism.t.sol +++ b/solidity/test/isms/ArbL2ToL1Ism.t.sol @@ -12,6 +12,7 @@ import {ArbL2ToL1Ism} from "../../contracts/isms/hook/ArbL2ToL1Ism.sol"; import {MockArbBridge, MockArbSys} from "../../contracts/mock/MockArbBridge.sol"; import {TestRecipient} from "../../contracts/test/TestRecipient.sol"; import {ExternalBridgeTest} from "./ExternalBridgeTest.sol"; +import {TestInterchainGasPaymaster} from "../../contracts/test/TestInterchainGasPaymaster.sol"; contract ArbL2ToL1IsmTest is ExternalBridgeTest { uint256 internal constant MOCK_LEAF_INDEX = 40160; @@ -22,10 +23,10 @@ contract ArbL2ToL1IsmTest is ExternalBridgeTest { 0x0000000000000000000000000000000000000064; MockArbBridge internal arbBridge; + TestInterchainGasPaymaster internal mockOverheadIgp; function setUp() public override { // Arbitrum bridge mock setup - GAS_QUOTE = 120_000; vm.etch(L2_ARBSYS_ADDRESS, address(new MockArbSys()).code); deployAll(); @@ -38,12 +39,13 @@ contract ArbL2ToL1IsmTest is ExternalBridgeTest { function deployHook() public { originMailbox = new TestMailbox(ORIGIN_DOMAIN); + mockOverheadIgp = new TestInterchainGasPaymaster(); hook = new ArbL2ToL1Hook( address(originMailbox), DESTINATION_DOMAIN, TypeCasts.addressToBytes32(address(ism)), L2_ARBSYS_ADDRESS, - GAS_QUOTE + address(mockOverheadIgp) ); } @@ -60,6 +62,20 @@ contract ArbL2ToL1IsmTest is ExternalBridgeTest { ism.setAuthorizedHook(TypeCasts.addressToBytes32(address(hook))); } + function test_postDispatch_childHook() public { + bytes memory encodedHookData = _encodeHookData(messageId); + originMailbox.updateLatestDispatchedId(messageId); + _expectOriginExternalBridgeCall(encodedHookData); + + bytes memory igpMetadata = StandardHookMetadata.overrideGasLimit( + 78_000 + ); + + uint256 quote = hook.quoteDispatch(igpMetadata, encodedMessage); + assertEq(quote, mockOverheadIgp.quoteGasPayment(ORIGIN_DOMAIN, 78_000)); + hook.postDispatch{value: quote}(igpMetadata, encodedMessage); + } + /* ============ helper functions ============ */ function _expectOriginExternalBridgeCall( diff --git a/solidity/test/isms/ERC5164ISM.t.sol b/solidity/test/isms/ERC5164ISM.t.sol index 8063979f4..57b467fde 100644 --- a/solidity/test/isms/ERC5164ISM.t.sol +++ b/solidity/test/isms/ERC5164ISM.t.sol @@ -150,6 +150,8 @@ contract ERC5164IsmTest is ExternalBridgeTest { function test_verify_valueAlreadyClaimed(uint256) public override {} + function testFuzz_postDispatch_refundsExtraValue(uint256) public override {} + function test_verify_false_arbitraryCall() public override {} /* ============ helper functions ============ */ diff --git a/solidity/test/isms/ExternalBridgeTest.sol b/solidity/test/isms/ExternalBridgeTest.sol index 344e001af..dca5a3c96 100644 --- a/solidity/test/isms/ExternalBridgeTest.sol +++ b/solidity/test/isms/ExternalBridgeTest.sol @@ -18,6 +18,7 @@ abstract contract ExternalBridgeTest is Test { uint8 internal constant HYPERLANE_VERSION = 1; uint32 internal constant ORIGIN_DOMAIN = 1; uint32 internal constant DESTINATION_DOMAIN = 2; + uint256 internal constant MSG_VALUE = 1 ether; uint256 internal constant MAX_MSG_VALUE = 2 ** 255 - 1; uint256 internal GAS_QUOTE; @@ -53,7 +54,8 @@ abstract contract ExternalBridgeTest is Test { originMailbox.updateLatestDispatchedId(messageId); _expectOriginExternalBridgeCall(encodedHookData); - hook.postDispatch{value: GAS_QUOTE}(testMetadata, encodedMessage); + uint256 quote = hook.quoteDispatch(testMetadata, encodedMessage); + hook.postDispatch{value: quote}(testMetadata, encodedMessage); } function test_postDispatch_revertWhen_chainIDNotSupported() public { @@ -89,6 +91,37 @@ abstract contract ExternalBridgeTest is Test { hook.postDispatch(excessValueMetadata, encodedMessage); } + function testFuzz_postDispatch_refundsExtraValue( + uint256 extraValue + ) public virtual { + vm.assume(extraValue < MAX_MSG_VALUE); + vm.deal(address(this), address(this).balance + extraValue); + uint256 valueBefore = address(this).balance; + + bytes memory encodedHookData = _encodeHookData(messageId); + originMailbox.updateLatestDispatchedId(messageId); + _expectOriginExternalBridgeCall(encodedHookData); + + uint256 quote = hook.quoteDispatch(testMetadata, encodedMessage); + hook.postDispatch{value: quote + extraValue}( + testMetadata, + encodedMessage + ); + + assertEq(address(this).balance, valueBefore - quote); + } + + function test_postDispatch_revertWhen_insufficientValue() public { + bytes memory encodedHookData = _encodeHookData(messageId); + originMailbox.updateLatestDispatchedId(messageId); + _expectOriginExternalBridgeCall(encodedHookData); + + uint256 quote = hook.quoteDispatch(testMetadata, encodedMessage); + + vm.expectRevert(); //arithmetic underflow + hook.postDispatch{value: quote - 1}(testMetadata, encodedMessage); + } + /* ============ ISM.verifyMessageId ============ */ function test_verifyMessageId_asyncCall() public { @@ -122,17 +155,17 @@ abstract contract ExternalBridgeTest is Test { function test_verify_msgValue_asyncCall() public virtual { bytes memory encodedHookData = _encodeHookData(messageId); - _externalBridgeDestinationCall(encodedHookData, 1 ether); + _externalBridgeDestinationCall(encodedHookData, MSG_VALUE); assertTrue(ism.verify(new bytes(0), encodedMessage)); - assertEq(address(testRecipient).balance, 1 ether); + assertEq(address(testRecipient).balance, MSG_VALUE); } function test_verify_msgValue_externalBridgeCall() public virtual { bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( address(hook), address(ism), - 1 ether, + MSG_VALUE, messageId ); assertTrue(ism.verify(externalCalldata, encodedMessage)); @@ -279,6 +312,8 @@ abstract contract ExternalBridgeTest is Test { address _sender ) internal virtual returns (bytes memory) {} - // meant to mock an arbitrary successful call made by the external bridge + receive() external payable {} + + // meant to be mock an arbitrary successful call made by the external bridge function verifyMessageId(bytes32 /*messageId*/) public payable {} } diff --git a/solidity/test/isms/OPL2ToL1Ism.t.sol b/solidity/test/isms/OPL2ToL1Ism.t.sol index d829e0211..7287ba0e1 100644 --- a/solidity/test/isms/OPL2ToL1Ism.t.sol +++ b/solidity/test/isms/OPL2ToL1Ism.t.sol @@ -14,6 +14,7 @@ import {MockOptimismMessenger, MockOptimismPortal} from "../../contracts/mock/Mo import {OPL2ToL1Hook} from "../../contracts/hooks/OPL2ToL1Hook.sol"; import {OPL2ToL1Ism} from "../../contracts/isms/hook/OPL2ToL1Ism.sol"; import {ExternalBridgeTest} from "./ExternalBridgeTest.sol"; +import {TestInterchainGasPaymaster} from "../../contracts/test/TestInterchainGasPaymaster.sol"; contract OPL2ToL1IsmTest is ExternalBridgeTest { address internal constant L2_MESSENGER_ADDRESS = @@ -21,6 +22,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { uint256 internal constant MOCK_NONCE = 0; + TestInterchainGasPaymaster internal mockOverheadIgp; MockOptimismPortal internal portal; MockOptimismMessenger internal l1Messenger; @@ -30,7 +32,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { function setUp() public override { // Optimism messenger mock setup - GAS_QUOTE = 120_000; + // GAS_QUOTE = 300_000; vm.etch( L2_MESSENGER_ADDRESS, address(new MockOptimismMessenger()).code @@ -42,12 +44,13 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { function deployHook() public { originMailbox = new TestMailbox(ORIGIN_DOMAIN); + mockOverheadIgp = new TestInterchainGasPaymaster(); hook = new OPL2ToL1Hook( address(originMailbox), DESTINATION_DOMAIN, TypeCasts.addressToBytes32(address(ism)), L2_MESSENGER_ADDRESS, - uint32(GAS_QUOTE) + address(mockOverheadIgp) ); } @@ -67,6 +70,20 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { ism.setAuthorizedHook(TypeCasts.addressToBytes32(address(hook))); } + function test_postDispatch_childHook() public { + bytes memory encodedHookData = _encodeHookData(messageId); + originMailbox.updateLatestDispatchedId(messageId); + _expectOriginExternalBridgeCall(encodedHookData); + + bytes memory igpMetadata = StandardHookMetadata.overrideGasLimit( + 78_000 + ); + + uint256 quote = hook.quoteDispatch(igpMetadata, encodedMessage); + assertEq(quote, mockOverheadIgp.quoteGasPayment(ORIGIN_DOMAIN, 78_000)); + hook.postDispatch{value: quote}(igpMetadata, encodedMessage); + } + /* ============ helper functions ============ */ function _expectOriginExternalBridgeCall( @@ -76,7 +93,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { L2_MESSENGER_ADDRESS, abi.encodeCall( ICrossDomainMessenger.sendMessage, - (address(ism), _encodedHookData, uint32(GAS_QUOTE)) + (address(ism), _encodedHookData, uint32(300_000)) ) ); } diff --git a/typescript/sdk/src/hook/EvmHookModule.ts b/typescript/sdk/src/hook/EvmHookModule.ts index a1b6d1412..b09099464 100644 --- a/typescript/sdk/src/hook/EvmHookModule.ts +++ b/typescript/sdk/src/hook/EvmHookModule.ts @@ -862,6 +862,8 @@ export class EvmHookModule extends HyperlaneModule< this.multiProvider.getSignerOrProvider(config.destinationChain), ); + const childHook = await this.deploy({ config: config.childHook }); + // deploy arbL1ToL1 hook const hook = await this.deployer.deployContract( chain, @@ -871,7 +873,7 @@ export class EvmHookModule extends HyperlaneModule< this.multiProvider.getDomainId(config.destinationChain), addressToBytes32(arbL2ToL1IsmAddress), config.arbSys, - BigNumber.from(200_000), // 2x estimate of executeTransaction call overhead + childHook.address, ], ); // set authorized hook on arbL2ToL1 ism diff --git a/typescript/sdk/src/hook/EvmHookReader.ts b/typescript/sdk/src/hook/EvmHookReader.ts index 1ed1f42ab..f84eecc8a 100644 --- a/typescript/sdk/src/hook/EvmHookReader.ts +++ b/typescript/sdk/src/hook/EvmHookReader.ts @@ -365,11 +365,14 @@ export class EvmHookReader extends HyperlaneReader implements HookReader { const destinationChainName = this.multiProvider.getChainName(destinationDomain); + const childHookAddress = await hook.childHook(); + const childHookConfig = await this.deriveHookConfig(childHookAddress); const config: WithAddress = { address, type: HookType.ARB_L2_TO_L1, destinationChain: destinationChainName, arbSys, + childHook: childHookConfig, }; this._cache.set(address, config); diff --git a/typescript/sdk/src/hook/schemas.ts b/typescript/sdk/src/hook/schemas.ts index 1111098e8..16bd01b27 100644 --- a/typescript/sdk/src/hook/schemas.ts +++ b/typescript/sdk/src/hook/schemas.ts @@ -46,6 +46,7 @@ export const ArbL2ToL1HookSchema = z.object({ 'address of the bridge contract on L1, optional only needed for non @arbitrum/sdk chains', ), destinationChain: z.string(), + childHook: z.lazy((): z.ZodSchema => HookConfigSchema), }); export const IgpSchema = OwnableSchema.extend({ diff --git a/typescript/sdk/src/ism/metadata/arbL2ToL1.hardhat-test.ts b/typescript/sdk/src/ism/metadata/arbL2ToL1.hardhat-test.ts index 519571067..f2b66d9cb 100644 --- a/typescript/sdk/src/ism/metadata/arbL2ToL1.hardhat-test.ts +++ b/typescript/sdk/src/ism/metadata/arbL2ToL1.hardhat-test.ts @@ -41,7 +41,7 @@ import { ArbL2ToL1MetadataBuilder } from './arbL2ToL1.js'; import { MetadataContext } from './builder.js'; describe('ArbL2ToL1MetadataBuilder', () => { - const origin: ChainName = 'test1'; + const origin: ChainName = 'test4'; const destination: ChainName = 'test2'; let core: HyperlaneCore; let ismFactory: HyperlaneIsmFactory; @@ -93,14 +93,29 @@ describe('ArbL2ToL1MetadataBuilder', () => { [], ); hookConfig = { - test1: { + test4: { type: HookType.ARB_L2_TO_L1, arbSys: mockArbSys.address, destinationChain: destination, + childHook: { + type: HookType.INTERCHAIN_GAS_PAYMASTER, + beneficiary: relayer.address, + owner: relayer.address, + oracleKey: relayer.address, + overhead: { + [destination]: 200000, + }, + oracleConfig: { + [destination]: { + gasPrice: '20', + tokenExchangeRate: '10000000000', + }, + }, + }, }, }; - factoryContracts = contractsMap.test1; + factoryContracts = contractsMap.test4; proxyFactoryAddresses = Object.keys(factoryContracts).reduce((acc, key) => { acc[key] = contractsMap[origin][key as keyof ProxyFactoryFactories].address; @@ -111,11 +126,11 @@ describe('ArbL2ToL1MetadataBuilder', () => { new MockArbBridge__factory(), [], ); - hookConfig.test1.bridge = arbBridge.address; + hookConfig.test4.bridge = arbBridge.address; const hookModule = await EvmHookModule.create({ chain: origin, - config: hookConfig.test1, + config: hookConfig.test4, proxyFactoryFactories: proxyFactoryAddresses, coreAddresses: core.getAddresses(origin), multiProvider, From f26453ee55a444b4ee1a1ac948ebebc92be26ac5 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:44:30 +0530 Subject: [PATCH 224/224] fix(contracts): add `msg.Value` to `verifyMessageId` (#4541) ### Description - Added to the msg.value to verifyMessageId to test if the msgValue passed in is the same as the msgValue used postDispatch ### Drive-by changes - None ### Related issues - fixes https://github.com/chainlight-io/2024-08-hyperlane/issues/3 ### Backward compatibility Yes ### Testing Unit tests --- .changeset/neat-sloths-agree.md | 5 ++ solidity/contracts/hooks/ArbL2ToL1Hook.sol | 4 +- solidity/contracts/hooks/OPL2ToL1Hook.sol | 4 +- solidity/contracts/hooks/OPStackHook.sol | 4 +- solidity/contracts/hooks/PolygonPosHook.sol | 4 +- .../hooks/aggregation/ERC5164Hook.sol | 9 ++-- .../hooks/layer-zero/LayerZeroV2Hook.sol | 4 +- .../hook/AbstractMessageIdAuthorizedIsm.sol | 21 +++++--- solidity/contracts/isms/hook/ArbL2ToL1Ism.sol | 13 +++-- solidity/contracts/isms/hook/ERC5164Ism.sol | 2 +- solidity/contracts/isms/hook/OPStackIsm.sol | 2 +- .../contracts/isms/hook/PolygonPosIsm.sol | 2 +- .../isms/hook/layer-zero/LayerZeroV2Ism.sol | 21 ++++++-- solidity/contracts/libs/OPL2ToL1Metadata.sol | 10 ++-- solidity/test/isms/ArbL2ToL1Ism.t.sol | 7 +-- solidity/test/isms/ERC5164ISM.t.sol | 8 ++-- solidity/test/isms/ExternalBridgeTest.sol | 48 ++++++++++++------- solidity/test/isms/OPL2ToL1Ism.t.sol | 16 +++---- solidity/test/isms/OPStackIsm.t.sol | 20 ++++---- solidity/test/isms/PolygonPosIsm.t.sol | 26 +++++----- .../test/isms/layer-zero/LayerZeroV2Ism.t.sol | 6 +-- 21 files changed, 141 insertions(+), 95 deletions(-) create mode 100644 .changeset/neat-sloths-agree.md diff --git a/.changeset/neat-sloths-agree.md b/.changeset/neat-sloths-agree.md new file mode 100644 index 000000000..979753ebe --- /dev/null +++ b/.changeset/neat-sloths-agree.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/core': minor +--- + +Added msg.value to preverifyMessage to commit it as part of external hook payload diff --git a/solidity/contracts/hooks/ArbL2ToL1Hook.sol b/solidity/contracts/hooks/ArbL2ToL1Hook.sol index 76c67c0ec..9a6365b24 100644 --- a/solidity/contracts/hooks/ArbL2ToL1Hook.sol +++ b/solidity/contracts/hooks/ArbL2ToL1Hook.sol @@ -78,8 +78,8 @@ contract ArbL2ToL1Hook is AbstractMessageIdAuthHook { bytes calldata message ) internal override { bytes memory payload = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - message.id() + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (message.id(), metadata.msgValue(0)) ); childHook.postDispatch{ diff --git a/solidity/contracts/hooks/OPL2ToL1Hook.sol b/solidity/contracts/hooks/OPL2ToL1Hook.sol index e82f4f4ab..165289e57 100644 --- a/solidity/contracts/hooks/OPL2ToL1Hook.sol +++ b/solidity/contracts/hooks/OPL2ToL1Hook.sol @@ -79,8 +79,8 @@ contract OPL2ToL1Hook is AbstractMessageIdAuthHook { bytes calldata message ) internal override { bytes memory payload = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - message.id() + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (message.id(), metadata.msgValue(0)) ); childHook.postDispatch{ diff --git a/solidity/contracts/hooks/OPStackHook.sol b/solidity/contracts/hooks/OPStackHook.sol index 0ddb713d3..695fab9cc 100644 --- a/solidity/contracts/hooks/OPStackHook.sol +++ b/solidity/contracts/hooks/OPStackHook.sol @@ -74,8 +74,8 @@ contract OPStackHook is AbstractMessageIdAuthHook { bytes calldata message ) internal override { bytes memory payload = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - message.id() + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (message.id(), metadata.msgValue(0)) ); l1Messenger.sendMessage{value: metadata.msgValue(0)}( diff --git a/solidity/contracts/hooks/PolygonPosHook.sol b/solidity/contracts/hooks/PolygonPosHook.sol index 2959adc3d..e3b1c7628 100644 --- a/solidity/contracts/hooks/PolygonPosHook.sol +++ b/solidity/contracts/hooks/PolygonPosHook.sol @@ -76,8 +76,8 @@ contract PolygonPosHook is AbstractMessageIdAuthHook, FxBaseRootTunnel { require(msg.value == 0, "PolygonPosHook: does not support msgValue"); bytes memory payload = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - message.id() + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (message.id(), metadata.msgValue(0)) ); _sendMessageToChild(payload); } diff --git a/solidity/contracts/hooks/aggregation/ERC5164Hook.sol b/solidity/contracts/hooks/aggregation/ERC5164Hook.sol index ece1bf80d..e1156679c 100644 --- a/solidity/contracts/hooks/aggregation/ERC5164Hook.sol +++ b/solidity/contracts/hooks/aggregation/ERC5164Hook.sol @@ -16,6 +16,7 @@ pragma solidity >=0.8.0; // ============ Internal Imports ============ import {TypeCasts} from "../../libs/TypeCasts.sol"; import {Message} from "../../libs/Message.sol"; +import {StandardHookMetadata} from "../libs/StandardHookMetadata.sol"; import {IPostDispatchHook} from "../../interfaces/hooks/IPostDispatchHook.sol"; import {IMessageDispatcher} from "../../interfaces/hooks/IMessageDispatcher.sol"; import {AbstractMessageIdAuthHook} from "../libs/AbstractMessageIdAuthHook.sol"; @@ -30,6 +31,7 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; * any of the 5164 adapters. */ contract ERC5164Hook is AbstractMessageIdAuthHook { + using StandardHookMetadata for bytes; using Message for bytes; IMessageDispatcher public immutable dispatcher; @@ -57,15 +59,14 @@ contract ERC5164Hook is AbstractMessageIdAuthHook { } function _sendMessageId( - bytes calldata, - /* metadata */ + bytes calldata metadata, bytes calldata message ) internal override { require(msg.value == 0, "ERC5164Hook: no value allowed"); bytes memory payload = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - message.id() + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (message.id(), metadata.msgValue(0)) ); dispatcher.dispatchMessage( destinationDomain, diff --git a/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol b/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol index 3a0955e59..5e0de4a8e 100644 --- a/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol +++ b/solidity/contracts/hooks/layer-zero/LayerZeroV2Hook.sol @@ -59,8 +59,8 @@ contract LayerZeroV2Hook is AbstractMessageIdAuthHook { bytes calldata message ) internal override { bytes memory payload = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - message.id() + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (message.id(), metadata.msgValue(0)) ); bytes calldata lZMetadata = metadata.getCustomMetadata(); diff --git a/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol b/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol index 43d851345..51a896129 100644 --- a/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol +++ b/solidity/contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol @@ -53,7 +53,7 @@ abstract contract AbstractMessageIdAuthorizedIsm is // ============ Events ============ /// @notice Emitted when a message is received from the external bridge - event ReceivedMessage(bytes32 indexed messageId); + event ReceivedMessage(bytes32 indexed messageId, uint256 msgValue); // ============ Initializer ============ @@ -101,7 +101,7 @@ abstract contract AbstractMessageIdAuthorizedIsm is } /** - * @notice Check if a message is verified through verifyMessageId first. + * @notice Check if a message is verified through preVerifyMessage first. * @param message Message to check. */ function isVerified(bytes calldata message) public view returns (bool) { @@ -115,24 +115,31 @@ abstract contract AbstractMessageIdAuthorizedIsm is * @dev Only callable by the authorized hook. * @param messageId Hyperlane Id of the message. */ - function verifyMessageId(bytes32 messageId) public payable virtual { + function preVerifyMessage( + bytes32 messageId, + uint256 msgValue + ) public payable virtual { require( _isAuthorized(), "AbstractMessageIdAuthorizedIsm: sender is not the hook" ); require( - msg.value < 2 ** VERIFIED_MASK_INDEX, - "AbstractMessageIdAuthorizedIsm: msg.value must be less than 2^255" + msg.value < 2 ** VERIFIED_MASK_INDEX && msg.value == msgValue, + "AbstractMessageIdAuthorizedIsm: invalid msg.value" + ); + require( + verifiedMessages[messageId] == 0, + "AbstractMessageIdAuthorizedIsm: message already verified" ); verifiedMessages[messageId] = msg.value.setBit(VERIFIED_MASK_INDEX); - emit ReceivedMessage(messageId); + emit ReceivedMessage(messageId, msgValue); } // ============ Internal Functions ============ /** - * @notice Check if sender is authorized to message `verifyMessageId`. + * @notice Check if sender is authorized to message `preVerifyMessage`. */ function _isAuthorized() internal view virtual returns (bool); } diff --git a/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol b/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol index 98b5f9bd6..42593f85c 100644 --- a/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol +++ b/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol @@ -44,6 +44,10 @@ contract ArbL2ToL1Ism is // arbitrum nitro contract on L1 to forward verification IOutbox public arbOutbox; + uint256 private constant DATA_LENGTH = 68; + + uint256 private constant MESSAGE_ID_END = 36; + // ============ Constructor ============ constructor(address _bridge) CrossChainEnabledArbitrumL1(_bridge) { @@ -110,13 +114,16 @@ contract ArbL2ToL1Ism is l2Sender == TypeCasts.bytes32ToAddress(authorizedHook), "ArbL2ToL1Ism: l2Sender != authorizedHook" ); - // this data is an abi encoded call of verifyMessageId(bytes32 messageId) - require(data.length == 36, "ArbL2ToL1Ism: invalid data length"); + // this data is an abi encoded call of preVerifyMessage(bytes32 messageId) + require( + data.length == DATA_LENGTH, + "ArbL2ToL1Ism: invalid data length" + ); bytes32 messageId = message.id(); bytes32 convertedBytes; assembly { // data = 0x[4 bytes function signature][32 bytes messageId] - convertedBytes := mload(add(data, 36)) + convertedBytes := mload(add(data, MESSAGE_ID_END)) } // check if the parsed message id matches the message id of the message require( diff --git a/solidity/contracts/isms/hook/ERC5164Ism.sol b/solidity/contracts/isms/hook/ERC5164Ism.sol index 0e0d788c5..d2735039c 100644 --- a/solidity/contracts/isms/hook/ERC5164Ism.sol +++ b/solidity/contracts/isms/hook/ERC5164Ism.sol @@ -44,7 +44,7 @@ contract ERC5164Ism is AbstractMessageIdAuthorizedIsm { } /** - * @notice Check if sender is authorized to message `verifyMessageId`. + * @notice Check if sender is authorized to message `preVerifyMessage`. */ function _isAuthorized() internal view override returns (bool) { return msg.sender == executor; diff --git a/solidity/contracts/isms/hook/OPStackIsm.sol b/solidity/contracts/isms/hook/OPStackIsm.sol index 1db350fec..504ed0d9d 100644 --- a/solidity/contracts/isms/hook/OPStackIsm.sol +++ b/solidity/contracts/isms/hook/OPStackIsm.sol @@ -49,7 +49,7 @@ contract OPStackIsm is // ============ Internal function ============ /** - * @notice Check if sender is authorized to message `verifyMessageId`. + * @notice Check if sender is authorized to message `preVerifyMessage`. */ function _isAuthorized() internal view override returns (bool) { return diff --git a/solidity/contracts/isms/hook/PolygonPosIsm.sol b/solidity/contracts/isms/hook/PolygonPosIsm.sol index 34a40360e..8a1471d1d 100644 --- a/solidity/contracts/isms/hook/PolygonPosIsm.sol +++ b/solidity/contracts/isms/hook/PolygonPosIsm.sol @@ -49,7 +49,7 @@ contract PolygonPosIsm is // ============ Internal function ============ /** - * @notice Check if sender is authorized to message `verifyMessageId`. + * @notice Check if sender is authorized to message `preVerifyMessage`. */ function _isAuthorized() internal view override returns (bool) { return diff --git a/solidity/contracts/isms/hook/layer-zero/LayerZeroV2Ism.sol b/solidity/contracts/isms/hook/layer-zero/LayerZeroV2Ism.sol index 1388f32cf..fedbffcda 100644 --- a/solidity/contracts/isms/hook/layer-zero/LayerZeroV2Ism.sol +++ b/solidity/contracts/isms/hook/layer-zero/LayerZeroV2Ism.sol @@ -57,7 +57,7 @@ contract LayerZeroV2Ism is AbstractMessageIdAuthorizedIsm { /** * @notice Entry point for receiving msg/packet from the LayerZero endpoint. * @param _lzMessage The payload of the received message. - * @dev Authorization verification is done within verifyMessageId() -> _isAuthorized() + * @dev Authorization verification is done within preVerifyMessage() -> _isAuthorized() */ function lzReceive( Origin calldata, @@ -66,25 +66,36 @@ contract LayerZeroV2Ism is AbstractMessageIdAuthorizedIsm { address, bytes calldata ) external payable { - verifyMessageId(_messageId(_lzMessage)); + preVerifyMessage(_messageId(_lzMessage), _msgValue(_lzMessage)); } // ============ Internal function ============ /** * @notice Slices the messageId from the message delivered from LayerZeroV2Hook - * @dev message is created as abi.encodeCall(AbstractMessageIdAuthorizedIsm.verifyMessageId, id) + * @dev message is created as abi.encodeCall(AbstractMessageIdAuthorizedIsm.preVerifyMessage, id) * @dev _message will be 36 bytes (4 bytes for function selector, and 32 bytes for messageId) */ function _messageId( bytes calldata _message ) internal pure returns (bytes32) { - return bytes32(_message[FUNC_SELECTOR_OFFSET:]); + return bytes32(_message[FUNC_SELECTOR_OFFSET:ORIGIN_SENDER_OFFSET]); + } + + /** + * @notice Slices the msgValue from the message delivered from LayerZeroV2Hook + * @dev message is created as abi.encodeCall(AbstractMessageIdAuthorizedIsm.preVerifyMessage, (id,msgValue)) + * @dev _message will be 68 bytes (4 bytes for function selector, and 32 bytes for messageId, another 32 for msgValue) + */ + function _msgValue( + bytes calldata _message + ) internal pure returns (uint256) { + return uint256(bytes32(_message[ORIGIN_SENDER_OFFSET:])); } /** * @notice Validates criteria to verify a message - * @dev this is called by AbstractMessageIdAuthorizedIsm.verifyMessageId + * @dev this is called by AbstractMessageIdAuthorizedIsm.preVerifyMessage * @dev parses msg.value to get parameters from lzReceive() */ function _isAuthorized() internal view override returns (bool) { diff --git a/solidity/contracts/libs/OPL2ToL1Metadata.sol b/solidity/contracts/libs/OPL2ToL1Metadata.sol index 704ce3d4d..f0e933891 100644 --- a/solidity/contracts/libs/OPL2ToL1Metadata.sol +++ b/solidity/contracts/libs/OPL2ToL1Metadata.sol @@ -7,7 +7,7 @@ pragma solidity >=0.8.0; */ library OPL2ToL1Metadata { // bottom offset to the start of message id in the metadata - uint256 private constant MESSAGE_ID_OFFSET = 88; + uint256 private constant MESSAGE_ID_OFFSET = 120; // from IOptimismPortal.WithdrawalTransaction // Σ { // nonce = 32 bytes @@ -20,7 +20,7 @@ library OPL2ToL1Metadata { // LENGTH = 32 bytes // } = 252 bytes uint256 private constant FIXED_METADATA_LENGTH = 252; - // metadata here is double encoded call relayMessage(..., verifyMessageId) + // metadata here is double encoded call relayMessage(..., preVerifyMessage) // Σ { // _selector = 4 bytes // _nonce = 32 bytes @@ -31,9 +31,9 @@ library OPL2ToL1Metadata { // _data // OFFSET = 32 bytes // LENGTH = 32 bytes - // PADDING + verifyMessageId = 64 bytes - // } = 292 bytes - uint256 private constant MESSENGER_CALLDATA_LENGTH = 292; + // PADDING + preVerifyMessage = 96 bytes + // } = 324 bytes + uint256 private constant MESSENGER_CALLDATA_LENGTH = 324; /** * @notice Returns the message ID. diff --git a/solidity/test/isms/ArbL2ToL1Ism.t.sol b/solidity/test/isms/ArbL2ToL1Ism.t.sol index c44665cb5..ec0fd9392 100644 --- a/solidity/test/isms/ArbL2ToL1Ism.t.sol +++ b/solidity/test/isms/ArbL2ToL1Ism.t.sol @@ -63,7 +63,7 @@ contract ArbL2ToL1IsmTest is ExternalBridgeTest { } function test_postDispatch_childHook() public { - bytes memory encodedHookData = _encodeHookData(messageId); + bytes memory encodedHookData = _encodeHookData(messageId, 0); originMailbox.updateLatestDispatchedId(messageId); _expectOriginExternalBridgeCall(encodedHookData); @@ -131,10 +131,7 @@ contract ArbL2ToL1IsmTest is ExternalBridgeTest { bytes32 _messageId, uint256 _value ) internal view returns (bytes memory) { - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (_messageId) - ); + bytes memory encodedHookData = _encodeHookData(_messageId, _value); bytes32[] memory proof = new bytes32[](16); return diff --git a/solidity/test/isms/ERC5164ISM.t.sol b/solidity/test/isms/ERC5164ISM.t.sol index 57b467fde..f3900e621 100644 --- a/solidity/test/isms/ERC5164ISM.t.sol +++ b/solidity/test/isms/ERC5164ISM.t.sol @@ -134,7 +134,7 @@ contract ERC5164IsmTest is ExternalBridgeTest { vm.expectRevert( "AbstractMessageIdAuthorizedIsm: sender is not the hook" ); - ism.verifyMessageId(messageId); + ism.preVerifyMessage(messageId, 0); assertFalse(ism.isVerified(encodedMessage)); } @@ -150,6 +150,8 @@ contract ERC5164IsmTest is ExternalBridgeTest { function test_verify_valueAlreadyClaimed(uint256) public override {} + function test_verify_override_msgValue() public override {} + function testFuzz_postDispatch_refundsExtraValue(uint256) public override {} function test_verify_false_arbitraryCall() public override {} @@ -161,7 +163,7 @@ contract ERC5164IsmTest is ExternalBridgeTest { uint256 _msgValue ) internal override { vm.prank(address(executor)); - ism.verifyMessageId(messageId); + ism.preVerifyMessage(messageId, 0); } function _encodeExternalDestinationBridgeCall( @@ -172,7 +174,7 @@ contract ERC5164IsmTest is ExternalBridgeTest { ) internal override returns (bytes memory) { if (_from == address(hook)) { vm.prank(address(executor)); - ism.verifyMessageId{value: _msgValue}(messageId); + ism.preVerifyMessage{value: _msgValue}(messageId, 0); } } } diff --git a/solidity/test/isms/ExternalBridgeTest.sol b/solidity/test/isms/ExternalBridgeTest.sol index dca5a3c96..937e39311 100644 --- a/solidity/test/isms/ExternalBridgeTest.sol +++ b/solidity/test/isms/ExternalBridgeTest.sol @@ -50,7 +50,8 @@ abstract contract ExternalBridgeTest is Test { /* ============ Hook.postDispatch ============ */ function test_postDispatch() public { - bytes memory encodedHookData = _encodeHookData(messageId); + bytes memory hookMetadata = testMetadata; + bytes memory encodedHookData = _encodeHookData(messageId, 0); originMailbox.updateLatestDispatchedId(messageId); _expectOriginExternalBridgeCall(encodedHookData); @@ -98,7 +99,7 @@ abstract contract ExternalBridgeTest is Test { vm.deal(address(this), address(this).balance + extraValue); uint256 valueBefore = address(this).balance; - bytes memory encodedHookData = _encodeHookData(messageId); + bytes memory encodedHookData = _encodeHookData(messageId, 0); originMailbox.updateLatestDispatchedId(messageId); _expectOriginExternalBridgeCall(encodedHookData); @@ -112,7 +113,7 @@ abstract contract ExternalBridgeTest is Test { } function test_postDispatch_revertWhen_insufficientValue() public { - bytes memory encodedHookData = _encodeHookData(messageId); + bytes memory encodedHookData = _encodeHookData(messageId, 0); originMailbox.updateLatestDispatchedId(messageId); _expectOriginExternalBridgeCall(encodedHookData); @@ -122,19 +123,16 @@ abstract contract ExternalBridgeTest is Test { hook.postDispatch{value: quote - 1}(testMetadata, encodedMessage); } - /* ============ ISM.verifyMessageId ============ */ + /* ============ ISM.preVerifyMessage ============ */ - function test_verifyMessageId_asyncCall() public { - bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) - ); + function test_preVerifyMessage_asyncCall() public { + bytes memory encodedHookData = _encodeHookData(messageId, 0); _externalBridgeDestinationCall(encodedHookData, 0); assertTrue(ism.isVerified(encodedMessage)); } - function test_verifyMessageId_externalBridgeCall() public virtual { + function test_preVerifyMessage_externalBridgeCall() public virtual { bytes memory externalCalldata = _encodeExternalDestinationBridgeCall( address(hook), address(ism), @@ -154,7 +152,7 @@ abstract contract ExternalBridgeTest is Test { } function test_verify_msgValue_asyncCall() public virtual { - bytes memory encodedHookData = _encodeHookData(messageId); + bytes memory encodedHookData = _encodeHookData(messageId, MSG_VALUE); _externalBridgeDestinationCall(encodedHookData, MSG_VALUE); assertTrue(ism.verify(new bytes(0), encodedMessage)); @@ -222,7 +220,7 @@ abstract contract ExternalBridgeTest is Test { // async call - native bridges might have try catch block to prevent revert try this.externalBridgeDestinationCallWrapper( - _encodeHookData(incorrectMessageId), + _encodeHookData(incorrectMessageId, 0), 0 ) {} catch {} @@ -232,7 +230,10 @@ abstract contract ExternalBridgeTest is Test { /// forge-config: default.fuzz.runs = 10 function test_verify_valueAlreadyClaimed(uint256 _msgValue) public virtual { _msgValue = bound(_msgValue, 0, MAX_MSG_VALUE); - _externalBridgeDestinationCall(_encodeHookData(messageId), _msgValue); + _externalBridgeDestinationCall( + _encodeHookData(messageId, _msgValue), + _msgValue + ); bool verified = ism.verify(new bytes(0), encodedMessage); assertTrue(verified); @@ -250,6 +251,18 @@ abstract contract ExternalBridgeTest is Test { assertEq(address(testRecipient).balance, _msgValue); } + function test_verify_override_msgValue() public virtual { + bytes memory encodedHookData = _encodeHookData(messageId, MSG_VALUE); + + _externalBridgeDestinationCall(encodedHookData, MSG_VALUE); + + vm.expectRevert("AbstractMessageIdAuthorizedIsm: invalid msg.value"); + _externalBridgeDestinationCall(encodedHookData, 0); + + assertTrue(ism.verify(new bytes(0), encodedMessage)); + assertEq(address(testRecipient).balance, MSG_VALUE); + } + function test_verify_false_arbitraryCall() public virtual { bytes memory incorrectCalldata = _encodeExternalDestinationBridgeCall( address(hook), @@ -275,12 +288,13 @@ abstract contract ExternalBridgeTest is Test { } function _encodeHookData( - bytes32 _messageId + bytes32 _messageId, + uint256 _msgValue ) internal pure returns (bytes memory) { return abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (_messageId) + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (_messageId, _msgValue) ); } @@ -315,5 +329,5 @@ abstract contract ExternalBridgeTest is Test { receive() external payable {} // meant to be mock an arbitrary successful call made by the external bridge - function verifyMessageId(bytes32 /*messageId*/) public payable {} + function preVerifyMessage(bytes32 /*messageId*/) public payable {} } diff --git a/solidity/test/isms/OPL2ToL1Ism.t.sol b/solidity/test/isms/OPL2ToL1Ism.t.sol index 7287ba0e1..9322713d5 100644 --- a/solidity/test/isms/OPL2ToL1Ism.t.sol +++ b/solidity/test/isms/OPL2ToL1Ism.t.sol @@ -71,7 +71,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { } function test_postDispatch_childHook() public { - bytes memory encodedHookData = _encodeHookData(messageId); + bytes memory encodedHookData = _encodeHookData(messageId, 0); originMailbox.updateLatestDispatchedId(messageId); _expectOriginExternalBridgeCall(encodedHookData); @@ -117,8 +117,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { } function _externalBridgeDestinationCall( - bytes memory, - /*_encodedHookData*/ + bytes memory _encodedHookData, uint256 _msgValue ) internal override { vm.deal(address(portal), _msgValue); @@ -132,7 +131,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { data: _encodeMessengerCalldata( address(ism), _msgValue, - messageId + _encodedHookData ) }); portal.finalizeWithdrawalTransaction(withdrawal); @@ -141,10 +140,8 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { function _encodeMessengerCalldata( address _ism, uint256 _value, - bytes32 _messageId + bytes memory _encodedHookData ) internal view returns (bytes memory) { - bytes memory encodedHookData = _encodeHookData(_messageId); - return abi.encodeCall( ICrossDomainMessenger.relayMessage, @@ -154,7 +151,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { _ism, _value, uint256(GAS_QUOTE), - encodedHookData + _encodedHookData ) ); } @@ -164,6 +161,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { uint256 _value, bytes32 _messageId ) internal view returns (bytes memory) { + bytes memory encodedHookData = _encodeHookData(_messageId, _value); return abi.encode( MOCK_NONCE, @@ -171,7 +169,7 @@ contract OPL2ToL1IsmTest is ExternalBridgeTest { l1Messenger, _value, uint256(GAS_QUOTE), - _encodeMessengerCalldata(_ism, _value, _messageId) + _encodeMessengerCalldata(_ism, _value, encodedHookData) ); } } diff --git a/solidity/test/isms/OPStackIsm.t.sol b/solidity/test/isms/OPStackIsm.t.sol index 3230e59b8..8371c3b68 100644 --- a/solidity/test/isms/OPStackIsm.t.sol +++ b/solidity/test/isms/OPStackIsm.t.sol @@ -99,7 +99,10 @@ contract OPStackIsmTest is ExternalBridgeTest { function test_verify_revertsWhen_incorrectMessageId() public override { bytes32 incorrectMessageId = keccak256("incorrect message id"); - _externalBridgeDestinationCall(_encodeHookData(incorrectMessageId), 0); + _externalBridgeDestinationCall( + _encodeHookData(incorrectMessageId, 0), + 0 + ); assertFalse(ism.isVerified(testMessage)); } @@ -142,7 +145,7 @@ contract OPStackIsmTest is ExternalBridgeTest { } // SKIP - no external bridge call - function test_verifyMessageId_externalBridgeCall() public override {} + function test_preVerifyMessage_externalBridgeCall() public override {} function test_verify_msgValue_externalBridgeCall() public override {} @@ -150,12 +153,12 @@ contract OPStackIsmTest is ExternalBridgeTest { function test_verify_false_arbitraryCall() public override {} - /* ============ ISM.verifyMessageId ============ */ + /* ============ ISM.preVerifyMessage ============ */ function test_verify_revertsWhen_notAuthorizedHook() public override { // needs to be called by the canonical messenger on Optimism vm.expectRevert(NotCrossChainCall.selector); - ism.verifyMessageId(messageId); + ism.preVerifyMessage(messageId, 0); vm.startPrank(L2_MESSENGER_ADDRESS); _setExternalOriginSender(address(this)); @@ -164,7 +167,7 @@ contract OPStackIsmTest is ExternalBridgeTest { vm.expectRevert( "AbstractMessageIdAuthorizedIsm: sender is not the hook" ); - ism.verifyMessageId(messageId); + ism.preVerifyMessage(messageId, 0); } function _setExternalOriginSender( @@ -179,10 +182,11 @@ contract OPStackIsmTest is ExternalBridgeTest { function test_verify_tooMuchValue() public { uint256 _msgValue = 2 ** 255 + 1; - vm.expectRevert( - "AbstractMessageIdAuthorizedIsm: msg.value must be less than 2^255" + vm.expectRevert("AbstractMessageIdAuthorizedIsm: invalid msg.value"); + _externalBridgeDestinationCall( + _encodeHookData(messageId, _msgValue), + _msgValue ); - _externalBridgeDestinationCall(_encodeHookData(messageId), _msgValue); assertFalse(ism.isVerified(encodedMessage)); diff --git a/solidity/test/isms/PolygonPosIsm.t.sol b/solidity/test/isms/PolygonPosIsm.t.sol index fd26afea2..7d30dca4f 100644 --- a/solidity/test/isms/PolygonPosIsm.t.sol +++ b/solidity/test/isms/PolygonPosIsm.t.sol @@ -78,7 +78,7 @@ contract PolygonPosIsmTest is Test { bytes data ); - event ReceivedMessage(bytes32 indexed messageId); + event ReceivedMessage(bytes32 indexed messageId, uint256 msgValue); function setUp() public { // block numbers to fork from, chain data is cached to ../../forge-cache/ @@ -155,8 +155,8 @@ contract PolygonPosIsmTest is Test { vm.selectFork(mainnetFork); bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (messageId, 0) ); l1Mailbox.updateLatestDispatchedId(messageId); @@ -228,22 +228,22 @@ contract PolygonPosIsmTest is Test { polygonPosHook.postDispatch(testMetadata, encodedMessage); } - /* ============ ISM.verifyMessageId ============ */ + /* ============ ISM.preVerifyMessage ============ */ - function testFork_verifyMessageId() public { + function testFork_preVerifyMessage() public { deployAll(); vm.selectFork(polygonPosFork); bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (messageId) + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (messageId, 0) ); vm.startPrank(POLYGON_CROSSCHAIN_SYSTEM_ADDR); vm.expectEmit(true, false, false, false, address(polygonPosISM)); - emit ReceivedMessage(messageId); + emit ReceivedMessage(messageId, 0); // FIX: expect other events fxChild.onStateReceive( @@ -259,14 +259,14 @@ contract PolygonPosIsmTest is Test { vm.stopPrank(); } - function testFork_verifyMessageId_RevertWhen_NotAuthorized() public { + function testFork_preVerifyMessage_RevertWhen_NotAuthorized() public { deployAll(); vm.selectFork(polygonPosFork); // needs to be called by the fxchild on Polygon vm.expectRevert(NotCrossChainCall.selector); - polygonPosISM.verifyMessageId(messageId); + polygonPosISM.preVerifyMessage(messageId, 0); vm.startPrank(MAINNET_FX_CHILD); @@ -274,7 +274,7 @@ contract PolygonPosIsmTest is Test { vm.expectRevert( "AbstractMessageIdAuthorizedIsm: sender is not the hook" ); - polygonPosISM.verifyMessageId(messageId); + polygonPosISM.preVerifyMessage(messageId, 0); } /* ============ ISM.verify ============ */ @@ -349,8 +349,8 @@ contract PolygonPosIsmTest is Test { vm.selectFork(polygonPosFork); bytes memory encodedHookData = abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (_messageId) + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (_messageId, 0) ); vm.prank(POLYGON_CROSSCHAIN_SYSTEM_ADDR); diff --git a/solidity/test/isms/layer-zero/LayerZeroV2Ism.t.sol b/solidity/test/isms/layer-zero/LayerZeroV2Ism.t.sol index 0d778a4d9..ac3ff38cf 100644 --- a/solidity/test/isms/layer-zero/LayerZeroV2Ism.t.sol +++ b/solidity/test/isms/layer-zero/LayerZeroV2Ism.t.sol @@ -23,8 +23,8 @@ contract LayerZeroV2IsmTest is Test { ) internal pure returns (bytes memory) { return abi.encodeCall( - AbstractMessageIdAuthorizedIsm.verifyMessageId, - (_messageId) + AbstractMessageIdAuthorizedIsm.preVerifyMessage, + (_messageId, 0) ); } @@ -133,7 +133,7 @@ contract LayerZeroV2IsmTest is Test { vm.stopPrank(); } - function testLzV2Ism_verifyMessageId_SetsCorrectMessageId( + function testLzV2Ism_preVerifyMessage_SetsCorrectMessageId( bytes32 messageId ) public { lZIsm.setAuthorizedHook(hook.addressToBytes32());