From 6c6d2bc04ff1b340aeb75653068228bd3d7d4543 Mon Sep 17 00:00:00 2001 From: Kunal Arora <55632507+aroralanuk@users.noreply.github.com> Date: Mon, 13 Jan 2025 22:03:40 +0530 Subject: [PATCH] fix(e2e): reenable gas enforcement check in e2e (non-cosmwasm) (#5105) ### Description - Move to valid 'gaspaymentenforcement' for e2e, which was earlier shortcircuiting to none (the default value for enforcement policy). This meant we were not checking if the relayer was enforcing a non-zero gas payment for either sealevel or EVM gas payments. - The igpHook set as part of the default hook for Kathy was not configured properly, hence was giving a quote of 0. Now, Kathy does set the IGP config (oracle and overhead). (Note: Kathy is soon to be deprecated, so this is more of a quick patch for e2e coverage). - Added a check for deserilization of 'gaspaymentenforcement' and panic if invalid to prevent this bug in the future. ### Drive-by changes <!-- Are there any minor or drive-by changes also included? --> ### Related issues <!-- - Fixes #[issue number here] --> ### Backward compatibility <!-- Are these changes backward compatible? Are there any infrastructure implications, e.g. changes that would prohibit deploying older commits using this infra tooling? Yes/No --> ### Testing <!-- What kind of testing have these changes undergone? None/Manual/Unit Tests --> --- rust/main/agents/relayer/src/settings/mod.rs | 44 ++++++++-- rust/main/utils/run-locally/src/main.rs | 2 +- .../infra/scripts/send-test-messages.ts | 81 +++++++++++++++++-- 3 files changed, 113 insertions(+), 14 deletions(-) diff --git a/rust/main/agents/relayer/src/settings/mod.rs b/rust/main/agents/relayer/src/settings/mod.rs index dc4c1e543e..df28d03dee 100644 --- a/rust/main/agents/relayer/src/settings/mod.rs +++ b/rust/main/agents/relayer/src/settings/mod.rs @@ -125,16 +125,50 @@ impl FromRawConf<RawRelayerSettings> for RelayerSettings { .parse_from_str("Expected database path") .unwrap_or_else(|| std::env::current_dir().unwrap().join("hyperlane_db")); - let (raw_gas_payment_enforcement_path, raw_gas_payment_enforcement) = p - .get_opt_key("gasPaymentEnforcement") - .take_config_err_flat(&mut err) - .and_then(parse_json_array) - .unwrap_or_else(|| (&p.cwp + "gas_payment_enforcement", Value::Array(vec![]))); + // is_gas_payment_enforcement_set determines if we should be checking if the correct gas payment enforcement policy has been provided with "gasPaymentEnforcement" key + let ( + raw_gas_payment_enforcement_path, + raw_gas_payment_enforcement, + is_gas_payment_enforcement_set, + ) = { + match p.get_opt_key("gasPaymentEnforcement") { + Ok(Some(parser)) => match parse_json_array(parser) { + Some((path, value)) => (path, value, true), + None => ( + &p.cwp + "gas_payment_enforcement", + Value::Array(vec![]), + true, + ), + }, + Ok(None) => ( + &p.cwp + "gas_payment_enforcement", + Value::Array(vec![]), + false, + ), + Err(_) => ( + &p.cwp + "gas_payment_enforcement", + Value::Array(vec![]), + false, + ), + } + }; let gas_payment_enforcement_parser = ValueParser::new( raw_gas_payment_enforcement_path, &raw_gas_payment_enforcement, ); + + if is_gas_payment_enforcement_set + && gas_payment_enforcement_parser + .val + .as_array() + .unwrap() + .is_empty() + { + Err::<(), eyre::Report>(eyre!("GASPAYMENTENFORCEMENT policy cannot be parsed")) + .take_err(&mut err, || cwp + "gas_payment_enforcement"); + } + let mut gas_payment_enforcement = gas_payment_enforcement_parser.into_array_iter().map(|itr| { itr.filter_map(|policy| { let policy_type = policy.chain(&mut err).get_opt_key("type").parse_string().end(); diff --git a/rust/main/utils/run-locally/src/main.rs b/rust/main/utils/run-locally/src/main.rs index 4686c15446..a7e03b4094 100644 --- a/rust/main/utils/run-locally/src/main.rs +++ b/rust/main/utils/run-locally/src/main.rs @@ -227,7 +227,7 @@ fn main() -> ExitCode { "GASPAYMENTENFORCEMENT", r#"[{ "type": "minimum", - "payment": "1", + "payment": "1" }]"#, ) .arg( diff --git a/typescript/infra/scripts/send-test-messages.ts b/typescript/infra/scripts/send-test-messages.ts index d028263982..6775ac5534 100644 --- a/typescript/infra/scripts/send-test-messages.ts +++ b/typescript/infra/scripts/send-test-messages.ts @@ -1,9 +1,16 @@ import { Provider } from '@ethersproject/providers'; -import { Wallet } from 'ethers'; +import { BigNumber, Wallet } from 'ethers'; import fs from 'fs'; import yargs from 'yargs'; -import { Mailbox, TestSendReceiver__factory } from '@hyperlane-xyz/core'; +import { + InterchainGasPaymaster, + InterchainGasPaymaster__factory, + Mailbox, + StorageGasOracle, + StorageGasOracle__factory, + TestSendReceiver__factory, +} from '@hyperlane-xyz/core'; import { ChainName, HookType, @@ -11,7 +18,7 @@ import { MultiProvider, TestChainName, } from '@hyperlane-xyz/sdk'; -import { addressToBytes32, sleep } from '@hyperlane-xyz/utils'; +import { addressToBytes32, formatMessage, sleep } from '@hyperlane-xyz/utils'; const ANVIL_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; @@ -47,6 +54,44 @@ async function setMailboxHook( console.log(`set the ${mailboxHookType} hook on ${local} to ${hook}`); } +async function setIgpConfig( + remoteId: number, + signer: Wallet, + provider: Provider, + mailbox: Mailbox, + addresses: any, + local: ChainName, +) { + const storageGasOracleF = new StorageGasOracle__factory( + signer.connect(provider), + ); + const storageGasOracle = await storageGasOracleF.deploy(); + await storageGasOracle.deployTransaction.wait(); + + const oracleConfigs: Array<StorageGasOracle.RemoteGasDataConfigStruct> = []; + oracleConfigs.push({ + remoteDomain: remoteId, + tokenExchangeRate: '10000000000', + gasPrice: '1000000000', + }); + await storageGasOracle.setRemoteGasDataConfigs(oracleConfigs); + + const gasParamsToSet: InterchainGasPaymaster.GasParamStruct[] = []; + gasParamsToSet.push({ + remoteDomain: remoteId, + config: { + gasOracle: storageGasOracle.address, + gasOverhead: 1000000, + }, + }); + + const igpHook = InterchainGasPaymaster__factory.connect( + addresses[local].interchainGasPaymaster, + signer.connect(provider), + ); + await igpHook.setDestinationGasConfigs(gasParamsToSet); +} + const chainSummary = async (core: HyperlaneCore, chain: ChainName) => { const coreContracts = core.getContracts(chain); const mailbox = coreContracts.mailbox; @@ -157,15 +202,33 @@ async function main() { MailboxHookType.REQUIRED, requiredHook, ); + + if ( + defaultHook === HookType.AGGREGATION || + defaultHook === HookType.INTERCHAIN_GAS_PAYMASTER + ) { + console.log('Setting IGP config for message ...'); + await setIgpConfig(remoteId, signer, provider, mailbox, addresses, local); + } + + const message = formatMessage( + 1, + 0, + multiProvider.getDomainId(local), + recipient.address, + multiProvider.getDomainId(remote), + recipient.address, + '0x1234', + ); const quote = await mailbox['quoteDispatch(uint32,bytes32,bytes)']( remoteId, addressToBytes32(recipient.address), - '0x1234', + message, ); - await recipient['dispatchToSelf(address,uint32,bytes)']( - mailbox.address, + await mailbox['dispatch(uint32,bytes32,bytes)']( remoteId, - '0x1234', + addressToBytes32(recipient.address), + message, { value: quote, }, @@ -173,7 +236,9 @@ async function main() { console.log( `send to ${recipient.address} on ${remote} via mailbox ${ mailbox.address - } on ${local} with nonce ${(await mailbox.nonce()) - 1}`, + } on ${local} with nonce ${ + (await mailbox.nonce()) - 1 + } and quote ${quote.toString()}`, ); console.log(await chainSummary(core, local)); console.log(await chainSummary(core, remote));