Skip to content

Commit 64ee4bf

Browse files
authored
Merge pull request #163 from AbstractSDK/0.26
Abstract 0.26 with Polytone prediction
2 parents b85f459 + ae1f6d5 commit 64ee4bf

File tree

7 files changed

+144
-5
lines changed

7 files changed

+144
-5
lines changed

.changeset/many-beers-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@abstract-money/core": minor
3+
---
4+
5+
Abstract 0.26

.changeset/warm-laws-wink.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@abstract-money/core": patch
3+
---
4+
5+
Add polytone proxy address prediction functions

packages/core/abstract.config.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@ import { registry, vanilla } from '@abstract-money/cli/plugins'
44
const contractsConfig = [
55
{
66
name: 'account',
7-
version: '0.25.0',
7+
version: '0.26.0',
88
},
99
{
1010
name: 'registry',
11-
version: '0.25.0',
11+
version: '0.26.0',
1212
},
1313
{
1414
name: 'ans-host',
15-
version: '0.25.0',
15+
version: '0.26.0',
1616
},
1717
{
1818
name: 'ibc-client',
19-
version: '0.25.0',
19+
version: '0.26.0',
2020
},
2121
{
2222
name: 'ica-client',
23-
version: '0.25.0',
23+
version: '0.26.0',
2424
},
2525
]
2626

packages/core/src/utils/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ export * from './events'
1212
export * from './authz'
1313
export * from './cosmwasm'
1414
export * from './modules'
15+
export * from './polytone'
16+
1517
export { ABSTRACT_NAMESPACE } from './modules/abstract-module-id'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './predict-proxy-address'
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { getInstantiate2Address } from '../module-factory'
3+
import {
4+
generateSha512Salt,
5+
predictPolytoneProxyAddress,
6+
} from './predict-proxy-address'
7+
8+
describe('predictPolytoneProxyAddress', () => {
9+
// https://github.com/DA0-DA0/polytone/blob/f70440a35f12f97a9018849ca7e6d241a53582ce/cw-orch-state.json
10+
const neutronNoteAddress =
11+
'neutron1767kfqeglqyctuqsmvyzgjecs60lpqju2f590smxevk9duq5fhaqgk5eca'
12+
const neutronToOsmosisVoiceAddress =
13+
'osmo1vw02frqejfw2v2w7dy6ws35jp9743dwkxy0laalwsuvzzvkszz7s8d93yw'
14+
// https://celatone.osmosis.zone/osmosis-1/codes/127
15+
const osmosisProxyChecksum =
16+
'5094551145BCD256538775A0611CE9E88F8D7A182A06F082F901FFED9184BB5A'
17+
// The sender from the source chain
18+
const neutronSenderAddress =
19+
'neutron13vzaav9pdsnuccy9wjzauv205q4e70t8lwtvngsqhyqs3xdjlu0sglylyv'
20+
// From state of Voice contract
21+
const connectionIdFromVoice = 'connection-2338'
22+
// https://celatone.osmosis.zone/osmosis-1/contracts/osmo1fgdp4k54nmhuydwmgfzygm0fjyvaz0thz8rglctpl5lehe57tcyqqfy698
23+
const expectedAddress =
24+
'osmo1fgdp4k54nmhuydwmgfzygm0fjyvaz0thz8rglctpl5lehe57tcyqqfy698'
25+
26+
it('returns the correct address with raw functions', async () => {
27+
const salt = generateSha512Salt(
28+
connectionIdFromVoice,
29+
`wasm.${neutronNoteAddress}`,
30+
neutronSenderAddress,
31+
)
32+
33+
const result = await getInstantiate2Address(
34+
neutronToOsmosisVoiceAddress,
35+
osmosisProxyChecksum,
36+
salt,
37+
)
38+
39+
// https://celatone.osmosis.zone/osmosis-1/contracts/osmo1fgdp4k54nmhuydwmgfzygm0fjyvaz0thz8rglctpl5lehe57tcyqqfy698
40+
expect(result).toBe(expectedAddress)
41+
})
42+
43+
it('returns the correct address with full function', async () => {
44+
const result = await predictPolytoneProxyAddress({
45+
hostVoiceAddress: neutronToOsmosisVoiceAddress,
46+
hostProxyChecksum: osmosisProxyChecksum,
47+
hostVoiceConnectionId: connectionIdFromVoice,
48+
controllerNoteAddress: neutronNoteAddress,
49+
controllerSender: neutronSenderAddress,
50+
})
51+
52+
expect(result).toBe(expectedAddress)
53+
})
54+
})
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { createHash } from 'node:crypto'
2+
import { fromBech32 } from '@cosmjs/encoding'
3+
import { getInstantiate2Address } from '../module-factory'
4+
5+
/**
6+
* Generates a salt by hashing the provided inputs with SHA-512.
7+
*
8+
* @param inputs - An array of strings to hash. Each input will be concatenated in the order provided.
9+
* @returns A Uint8Array containing the 64-byte (512-bit) hash.
10+
*/
11+
export const generateSha512Salt = (...inputs: string[]): Uint8Array => {
12+
const hash = createHash('sha512')
13+
for (const input of inputs) {
14+
hash.update(input)
15+
}
16+
return Uint8Array.from(hash.digest())
17+
}
18+
19+
/**
20+
* Generate the salt for a new Polytone proxy.
21+
* @param connectionId
22+
* @param counterpartyPort
23+
* @param sender
24+
*/
25+
export const generatePolytoneProxySalt = ({
26+
connectionId,
27+
counterpartyPort,
28+
sender,
29+
}: {
30+
connectionId: `connection-${string}`
31+
counterpartyPort: `wasm.${string}`
32+
sender: string
33+
}) => generateSha512Salt(connectionId, counterpartyPort, sender)
34+
35+
/**
36+
* Predicts the address of a Polytone proxy contract.
37+
* @param controllerNoteAddress - The address of the controller chain's Note contract.
38+
* @param controllerSender - The sending address on the controller chain.
39+
* @param hostVoiceAddress - The address of the host chain's Voice contract.
40+
* @param hostProxyChecksum - The checksum of the host chain's proxy contract.
41+
* @param hostVoiceConnectionId - The connection ID of the Voice contract to the Note.
42+
*/
43+
export const predictPolytoneProxyAddress = async ({
44+
controllerNoteAddress,
45+
controllerSender,
46+
hostVoiceAddress,
47+
hostVoiceConnectionId,
48+
hostProxyChecksum,
49+
}: {
50+
controllerNoteAddress: string
51+
controllerSender: string
52+
hostVoiceAddress: string
53+
hostVoiceConnectionId: `connection-${string}`
54+
hostProxyChecksum: string
55+
}) => {
56+
// Sanity check
57+
const notePrefix = fromBech32(controllerNoteAddress).prefix
58+
const senderPrefix = fromBech32(controllerSender).prefix
59+
if (notePrefix !== senderPrefix) {
60+
throw new Error(
61+
`Sender and note address prefixes do not match: ${senderPrefix} !== ${notePrefix}`,
62+
)
63+
}
64+
65+
const salt = generatePolytoneProxySalt({
66+
connectionId: hostVoiceConnectionId,
67+
counterpartyPort: `wasm.${controllerNoteAddress}`,
68+
sender: controllerSender,
69+
})
70+
71+
return await getInstantiate2Address(hostVoiceAddress, hostProxyChecksum, salt)
72+
}

0 commit comments

Comments
 (0)