UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

98 lines 4.98 kB
import { expect } from 'chai'; import { ethers } from 'ethers'; import hre from 'hardhat'; import sinon from 'sinon'; import { TestCcipReadIsm__factory } from '@hyperlane-xyz/core'; import { TestCoreDeployer } from '../../core/TestCoreDeployer.js'; import { TestRecipientDeployer } from '../../core/TestRecipientDeployer.js'; import { HyperlaneProxyFactoryDeployer } from '../../deploy/HyperlaneProxyFactoryDeployer.js'; import { MultiProvider } from '../../providers/MultiProvider.js'; import { EvmIsmReader } from '../EvmIsmReader.js'; import { HyperlaneIsmFactory } from '../HyperlaneIsmFactory.js'; import { BaseMetadataBuilder } from './builder.js'; import { offchainLookupRequestMessageHash } from './ccipread.js'; const OFFCHAIN_LOOKUP_SERVER_URL = 'http://example.com/namespace'; describe('Offchain Lookup ISM Integration', () => { let core; let multiProvider; let testRecipient; let ccipReadIsm; let metadataBuilder; let ismFactory; let fetchStub; beforeEach(async () => { // Set up a local test multi-provider and Hyperlane core const signers = await hre.ethers.getSigners(); multiProvider = MultiProvider.createTestMultiProvider({ signer: signers[0], }); const ismFactoryDeployer = new HyperlaneProxyFactoryDeployer(multiProvider); const contractsMap = await ismFactoryDeployer.deploy(multiProvider.mapKnownChains(() => ({}))); ismFactory = new HyperlaneIsmFactory(contractsMap, multiProvider); core = await new TestCoreDeployer(multiProvider, ismFactory).deployApp(); // Deploy a TestRecipient on test1 const deployments = await new TestRecipientDeployer(multiProvider).deploy({ test2: {}, }); testRecipient = deployments.test2.testRecipient; // Deploy the TestCcipReadIsm on test1 domain const domain = multiProvider.getDomainId('test1'); ccipReadIsm = await multiProvider.handleDeploy(domain, new TestCcipReadIsm__factory(), // Pass in desired offchain URLs for the ISM constructor: [[OFFCHAIN_LOOKUP_SERVER_URL]]); // Configure the TestRecipient to use the CCIP-Read ISM await testRecipient.setInterchainSecurityModule(ccipReadIsm.address); // Prepare the metadata builder metadataBuilder = new BaseMetadataBuilder(core); fetchStub = sinon.stub(global, 'fetch').resolves({ ok: true, json: async () => ({ data: '0x0000000000000000000000000000000000000000000000000000000000000001', }), }); }); it('should process a message protected by CCIP-Read ISM', async () => { // Send a message from test1 to test2 const { dispatchTx, message } = await core.sendMessage('test1', 'test2', testRecipient.address, '0x1234'); // Derive the on-chain ISM config for CCIP-Read const derivedIsm = await new EvmIsmReader(multiProvider, 'test2').deriveOffchainLookupConfig(ccipReadIsm.address); // Build the metadata using the CCIP-Read builder const context = { ism: derivedIsm, message, dispatchTx, hook: {}, }; const metadata = await metadataBuilder.build(context); // Finally, call mailbox.process on test2 with the metadata and message const mailbox = core.getContracts('test2').mailbox; await expect(mailbox.process(metadata, message.message)).to.not.be.reverted; }); it('sends signature field in request when calling fetch', async () => { const { dispatchTx, message } = await core.sendMessage('test1', 'test2', testRecipient.address, '0x1234'); // Derive the on-chain ISM config for CCIP-Read const derivedIsm = (await new EvmIsmReader(multiProvider, 'test2').deriveIsmConfig(ccipReadIsm.address)); // Build the metadata using the CCIP-Read builder const context = { ism: derivedIsm, message, dispatchTx, hook: {}, }; await metadataBuilder.build(context); // Verify that fetch was called exactly once expect(fetchStub.calledOnce).to.be.true; const [url, options] = fetchStub.getCall(0).args; const payload = JSON.parse(options.body); expect(url).to.equal(OFFCHAIN_LOOKUP_SERVER_URL.replace('{data}', payload.data)); // Should include sender, data, and signature expect(payload).to.include.keys('sender', 'data', 'signature'); expect(payload.sender).to.equal(ccipReadIsm.address); const recovered = ethers.utils.verifyMessage(ethers.utils.arrayify(offchainLookupRequestMessageHash(payload.sender, payload.data, OFFCHAIN_LOOKUP_SERVER_URL)), payload.signature); expect(recovered).to.equal((await hre.ethers.getSigners())[0].address); }); afterEach(() => { fetchStub.restore(); }); }); //# sourceMappingURL=ccipread.hardhat-test.js.map