From 65dd46df7050a71da6408af219db83283fb70820 Mon Sep 17 00:00:00 2001 From: adairrr <32375605+adairrr@users.noreply.github.com> Date: Sun, 22 Dec 2024 19:08:24 -0500 Subject: [PATCH 1/3] Update to abstract 0.26 --- packages/core/abstract.config.ts | 10 +++++----- packages/core/src/utils/index.ts | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/core/abstract.config.ts b/packages/core/abstract.config.ts index b849b099..5d33e906 100644 --- a/packages/core/abstract.config.ts +++ b/packages/core/abstract.config.ts @@ -4,23 +4,23 @@ import { registry, vanilla } from '@abstract-money/cli/plugins' const contractsConfig = [ { name: 'account', - version: '0.25.0', + version: '0.26.0', }, { name: 'registry', - version: '0.25.0', + version: '0.26.0', }, { name: 'ans-host', - version: '0.25.0', + version: '0.26.0', }, { name: 'ibc-client', - version: '0.25.0', + version: '0.26.0', }, { name: 'ica-client', - version: '0.25.0', + version: '0.26.0', }, ] diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts index 4e68e709..4a780a42 100644 --- a/packages/core/src/utils/index.ts +++ b/packages/core/src/utils/index.ts @@ -12,4 +12,6 @@ export * from './events' export * from './authz' export * from './cosmwasm' export * from './modules' +export * from './polytone' + export { ABSTRACT_NAMESPACE } from './modules/abstract-module-id' From eafab000987e70f00892d4659568bd2a3c6b5aaf Mon Sep 17 00:00:00 2001 From: adairrr <32375605+adairrr@users.noreply.github.com> Date: Sun, 22 Dec 2024 19:08:37 -0500 Subject: [PATCH 2/3] Add polytone prediction functions --- .changeset/many-beers-camp.md | 5 ++ .changeset/warm-laws-wink.md | 5 ++ packages/core/src/utils/polytone/index.ts | 1 + .../polytone/predict-proxy-address.test.ts | 54 ++++++++++++++ .../utils/polytone/predict-proxy-address.ts | 72 +++++++++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 .changeset/many-beers-camp.md create mode 100644 .changeset/warm-laws-wink.md create mode 100644 packages/core/src/utils/polytone/index.ts create mode 100644 packages/core/src/utils/polytone/predict-proxy-address.test.ts create mode 100644 packages/core/src/utils/polytone/predict-proxy-address.ts diff --git a/.changeset/many-beers-camp.md b/.changeset/many-beers-camp.md new file mode 100644 index 00000000..f93dd167 --- /dev/null +++ b/.changeset/many-beers-camp.md @@ -0,0 +1,5 @@ +--- +"@abstract-money/core": minor +--- + +Abstract 0.26 diff --git a/.changeset/warm-laws-wink.md b/.changeset/warm-laws-wink.md new file mode 100644 index 00000000..a411722e --- /dev/null +++ b/.changeset/warm-laws-wink.md @@ -0,0 +1,5 @@ +--- +"@abstract-money/core": patch +--- + +Add polytone proxy address prediction functions diff --git a/packages/core/src/utils/polytone/index.ts b/packages/core/src/utils/polytone/index.ts new file mode 100644 index 00000000..8a220863 --- /dev/null +++ b/packages/core/src/utils/polytone/index.ts @@ -0,0 +1 @@ +export * from './predict-proxy-address' diff --git a/packages/core/src/utils/polytone/predict-proxy-address.test.ts b/packages/core/src/utils/polytone/predict-proxy-address.test.ts new file mode 100644 index 00000000..d04f4f13 --- /dev/null +++ b/packages/core/src/utils/polytone/predict-proxy-address.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it } from 'vitest' +import { getInstantiate2Address } from '../module-factory' +import { + generateSha512Salt, + predictPolytoneProxyAddress, +} from './predict-proxy-address' + +describe('predictPolytoneProxyAddress', () => { + // https://github.com/DA0-DA0/polytone/blob/f70440a35f12f97a9018849ca7e6d241a53582ce/cw-orch-state.json + const neutronNoteAddress = + 'neutron1767kfqeglqyctuqsmvyzgjecs60lpqju2f590smxevk9duq5fhaqgk5eca' + const neutronToOsmosisVoiceAddress = + 'osmo1vw02frqejfw2v2w7dy6ws35jp9743dwkxy0laalwsuvzzvkszz7s8d93yw' + // https://celatone.osmosis.zone/osmosis-1/codes/127 + const osmosisProxyChecksum = + '5094551145BCD256538775A0611CE9E88F8D7A182A06F082F901FFED9184BB5A' + // The sender from the source chain + const neutronSenderAddress = + 'neutron13vzaav9pdsnuccy9wjzauv205q4e70t8lwtvngsqhyqs3xdjlu0sglylyv' + // From state of Voice contract + const connectionIdFromVoice = 'connection-2338' + // https://celatone.osmosis.zone/osmosis-1/contracts/osmo1fgdp4k54nmhuydwmgfzygm0fjyvaz0thz8rglctpl5lehe57tcyqqfy698 + const expectedAddress = + 'osmo1fgdp4k54nmhuydwmgfzygm0fjyvaz0thz8rglctpl5lehe57tcyqqfy698' + + it('returns the correct address with raw functions', async () => { + const salt = generateSha512Salt( + connectionIdFromVoice, + `wasm.${neutronNoteAddress}`, + neutronSenderAddress, + ) + + const result = await getInstantiate2Address( + neutronToOsmosisVoiceAddress, + osmosisProxyChecksum, + salt, + ) + + // https://celatone.osmosis.zone/osmosis-1/contracts/osmo1fgdp4k54nmhuydwmgfzygm0fjyvaz0thz8rglctpl5lehe57tcyqqfy698 + expect(result).toBe(expectedAddress) + }) + + it('returns the correct address with full function', async () => { + const result = await predictPolytoneProxyAddress({ + hostVoiceAddress: neutronToOsmosisVoiceAddress, + hostProxyChecksum: osmosisProxyChecksum, + hostVoiceConnectionId: connectionIdFromVoice, + controllerNoteAddress: neutronNoteAddress, + controllerSender: neutronSenderAddress, + }) + + expect(result).toBe(expectedAddress) + }) +}) diff --git a/packages/core/src/utils/polytone/predict-proxy-address.ts b/packages/core/src/utils/polytone/predict-proxy-address.ts new file mode 100644 index 00000000..d3aa82b1 --- /dev/null +++ b/packages/core/src/utils/polytone/predict-proxy-address.ts @@ -0,0 +1,72 @@ +import { createHash } from 'node:crypto' +import { fromBech32 } from '@cosmjs/encoding' +import { getInstantiate2Address } from '../module-factory' + +/** + * Generates a salt by hashing the provided inputs with SHA-512. + * + * @param inputs - An array of strings to hash. Each input will be concatenated in the order provided. + * @returns A Uint8Array containing the 64-byte (512-bit) hash. + */ +export const generateSha512Salt = (...inputs: string[]): Uint8Array => { + const hash = createHash('sha512') + for (const input of inputs) { + hash.update(input) + } + return Uint8Array.from(hash.digest()) +} + +/** + * Generate the salt for a new Polytone proxy. + * @param connectionId + * @param counterpartyPort + * @param sender + */ +export const generatePolytoneProxySalt = ({ + connectionId, + counterpartyPort, + sender, +}: { + connectionId: `connection-${string}` + counterpartyPort: `wasm.${string}` + sender: string +}) => generateSha512Salt(connectionId, counterpartyPort, sender) + +/** + * Predicts the address of a Polytone proxy contract. + * @param controllerNoteAddress - The address of the controller chain's Note contract. + * @param controllerSender - The sending address on the controller chain. + * @param hostVoiceAddress - The address of the host chain's Voice contract. + * @param hostProxyChecksum - The checksum of the host chain's proxy contract. + * @param voiceConnectionId - The connection ID of the Voice contract to the Note. + */ +export const predictPolytoneProxyAddress = async ({ + controllerNoteAddress, + controllerSender, + hostVoiceAddress, + hostVoiceConnectionId, + hostProxyChecksum, +}: { + controllerNoteAddress: string + controllerSender: string + hostVoiceAddress: string + hostProxyChecksum: string + hostVoiceConnectionId: `connection-${string}` +}) => { + // Sanity check + const notePrefix = fromBech32(controllerNoteAddress).prefix + const senderPrefix = fromBech32(controllerSender).prefix + if (notePrefix !== senderPrefix) { + throw new Error( + `Sender and note address prefixes do not match: ${senderPrefix} !== ${notePrefix}`, + ) + } + + const salt = generatePolytoneProxySalt({ + connectionId: hostVoiceConnectionId, + counterpartyPort: `wasm.${controllerNoteAddress}`, + sender: controllerSender, + }) + + return await getInstantiate2Address(hostVoiceAddress, hostProxyChecksum, salt) +} From ae1f6d53bcd7f6a3b2e6b0c5fac2c51b12fc9461 Mon Sep 17 00:00:00 2001 From: adairrr <32375605+adairrr@users.noreply.github.com> Date: Sun, 22 Dec 2024 21:54:46 -0500 Subject: [PATCH 3/3] Move around polytone fn order --- packages/core/src/utils/polytone/predict-proxy-address.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/utils/polytone/predict-proxy-address.ts b/packages/core/src/utils/polytone/predict-proxy-address.ts index d3aa82b1..6070deb6 100644 --- a/packages/core/src/utils/polytone/predict-proxy-address.ts +++ b/packages/core/src/utils/polytone/predict-proxy-address.ts @@ -38,7 +38,7 @@ export const generatePolytoneProxySalt = ({ * @param controllerSender - The sending address on the controller chain. * @param hostVoiceAddress - The address of the host chain's Voice contract. * @param hostProxyChecksum - The checksum of the host chain's proxy contract. - * @param voiceConnectionId - The connection ID of the Voice contract to the Note. + * @param hostVoiceConnectionId - The connection ID of the Voice contract to the Note. */ export const predictPolytoneProxyAddress = async ({ controllerNoteAddress, @@ -50,8 +50,8 @@ export const predictPolytoneProxyAddress = async ({ controllerNoteAddress: string controllerSender: string hostVoiceAddress: string - hostProxyChecksum: string hostVoiceConnectionId: `connection-${string}` + hostProxyChecksum: string }) => { // Sanity check const notePrefix = fromBech32(controllerNoteAddress).prefix