Skip to content

Commit

Permalink
🪲squads multisig set send receive libs (#1150)
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Goulding <goulding@layerzerolabs.org>
  • Loading branch information
ryandgoulding authored Jan 7, 2025
1 parent a57ead7 commit 51c4086
Show file tree
Hide file tree
Showing 7 changed files with 593 additions and 103 deletions.
6 changes: 6 additions & 0 deletions .changeset/fast-flies-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@layerzerolabs/protocol-devtools-solana": patch
"@layerzerolabs/ua-devtools-solana": patch
---

Fix setSendConfig and setReceiveConfig for squads multisig
3 changes: 3 additions & 0 deletions packages/protocol-devtools-solana/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@
"@layerzerolabs/lz-definitions": "^3.0.27",
"@layerzerolabs/lz-solana-sdk-v2": "^3.0.0",
"@layerzerolabs/lz-v2-utilities": "^3.0.12",
"@layerzerolabs/oft-v2-solana-sdk": "^3.0.38",
"@layerzerolabs/protocol-devtools": "~1.1.2",
"@layerzerolabs/test-devtools": "~0.4.2",
"@layerzerolabs/test-devtools-solana": "~0.0.4",
"@layerzerolabs/ua-devtools": "~3.0.2",
"@metaplex-foundation/umi": "^0.9.2",
"@metaplex-foundation/umi-web3js-adapters": "^0.9.2",
"@solana/web3.js": "~1.95.8",
"@swc/core": "^1.4.0",
"@swc/jest": "^0.2.36",
Expand Down
88 changes: 54 additions & 34 deletions packages/protocol-devtools-solana/src/endpointv2/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { MessagingFee } from '@layerzerolabs/protocol-devtools'
import { oft } from '@layerzerolabs/oft-v2-solana-sdk'
import type {
IEndpointV2,
IUlnRead,
Expand Down Expand Up @@ -34,10 +35,12 @@ import {
SimpleMessageLibProgram,
UlnProgram,
} from '@layerzerolabs/lz-solana-sdk-v2'
import { Connection, PublicKey, Transaction } from '@solana/web3.js'
import { Connection, PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'
import assert from 'assert'
import { Uln302 } from '@/uln302'
import { SetConfigSchema } from './schema'
import { createNoopSigner, publicKey, TransactionBuilder, WrappedInstruction } from '@metaplex-foundation/umi'
import { fromWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters'

/**
* Solana-specific SDK for EndpointV2 contracts
Expand Down Expand Up @@ -233,26 +236,46 @@ export class EndpointV2 extends OmniSDK implements IEndpointV2 {

this.logger.debug(`Setting send library for eid ${eid} (${eidLabel}) and OApp ${oapp} to ${uln}`)

const instruction = await mapError(
async () =>
this.program.setSendLibrary(
await this.safeGetDelegate(oapp),
new PublicKey(oapp),
new PublicKey(uln),
eid
),
(error) =>
new Error(`Failed to set the send library for ${this.label} and OApp ${oapp} for ${eidLabel}: ${error}`)
)

const transaction = new Transaction().add(instruction)

return {
...(await this.createTransaction(transaction)),
...(await this.createTransaction(
this._umiToWeb3Tx([
oft.setSendLibrary(
{
admin: createNoopSigner(fromWeb3JsPublicKey(await this.safeGetDelegate(oapp))),
oftStore: publicKey(oapp),
},
{
sendLibraryProgram: publicKey(uln),
remoteEid: eid,
}
),
])
)),
description: `Setting send library for eid ${eid} (${eidLabel}) and OApp ${oapp} to ${uln}`,
}
}

// Convert Umi instructions to Web3JS Transaction
protected _umiToWeb3Tx(ixs: WrappedInstruction[]): Transaction {
const web3Transaction = new Transaction()
const txBuilder = new TransactionBuilder(ixs)
txBuilder.getInstructions().forEach((umiInstruction) => {
const web3Instruction = new TransactionInstruction({
programId: new PublicKey(umiInstruction.programId),
keys: umiInstruction.keys.map((key) => ({
pubkey: new PublicKey(key.pubkey),
isSigner: key.isSigner,
isWritable: key.isWritable,
})),
data: Buffer.from(umiInstruction.data),
})

// Add the instruction to the Web3.js transaction
web3Transaction.add(web3Instruction)
})
return web3Transaction
}

async setReceiveLibrary(
oapp: OmniAddress,
eid: EndpointId,
Expand All @@ -271,25 +294,22 @@ export class EndpointV2 extends OmniSDK implements IEndpointV2 {

this.logger.debug(`Setting receive library for eid ${eid} (${eidLabel}) and OApp ${oapp} to ${uln}`)

const instruction = await mapError(
async () =>
this.program.setReceiveLibrary(
await this.safeGetDelegate(oapp),
new PublicKey(oapp),
new PublicKey(uln),
eid,
Number(gracePeriod)
),
(error) =>
new Error(
`Failed to set the receive library for ${this.label} and OApp ${oapp} for ${eidLabel}: ${error}`
)
)

const transaction = new Transaction().add(instruction)

return {
...(await this.createTransaction(transaction)),
...(await this.createTransaction(
this._umiToWeb3Tx([
oft.setReceiveLibrary(
{
admin: createNoopSigner(fromWeb3JsPublicKey(await this.safeGetDelegate(oapp))),
oftStore: publicKey(oapp),
},
{
receiveLibraryProgram: publicKey(uln),
remoteEid: eid,
gracePeriod,
}
),
])
)),
description: `Setting receive library for eid ${eid} (${eidLabel}) and OApp ${oapp} to ${uln}`,
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/protocol-devtools-solana/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"exclude": ["dist", "node_modules"],
"include": ["src", "test", "*.config.ts"],
"compilerOptions": {
"target": "es2020",
"experimentalDecorators": true,
"types": ["node", "jest"],
"paths": {
Expand Down
2 changes: 1 addition & 1 deletion packages/ua-devtools-solana/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"@layerzerolabs/lz-v2-utilities": "^3.0.12",
"@layerzerolabs/oft-v2-solana-sdk": "^3.0.0",
"@layerzerolabs/protocol-devtools": "~1.1.2",
"@layerzerolabs/protocol-devtools-solana": "~4.0.3",
"@layerzerolabs/protocol-devtools-solana": "~4.0.4",
"@layerzerolabs/test-devtools": "~0.4.2",
"@layerzerolabs/test-devtools-solana": "~0.0.4",
"@layerzerolabs/ua-devtools": "~3.0.2",
Expand Down
89 changes: 23 additions & 66 deletions packages/ua-devtools-solana/src/oft/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,23 +176,24 @@ export class OFT extends OmniSDK implements IOApp {
new Error(`Failed to convert peer ${address} for ${eidLabel} for ${this.label} to bytes: ${error}`)
)
const peerAsBytes32 = makeBytes32(normalizedPeer)
const admin = createNoopSigner(this.umiUserAccount)
const delegate = await this.safeGetDelegate()

const oftStore = this.umiPublicKey

this.logger.debug(`Setting peer for eid ${eid} (${eidLabel}) to address ${peerAsBytes32}`)
return {
...(await this.createTransaction(
this._umiToWeb3Tx([
await this._createSetPeerAddressIx(normalizedPeer, eid),
oft.initSendLibrary({ admin, oftStore }, eid),
oft.initReceiveLibrary({ admin, oftStore }, eid),
await this._setPeerEnforcedOptionsIx(new Uint8Array([0, 3]), new Uint8Array([0, 3]), eid),
await this._setPeerFeeBpsIx(eid),
oft.initOAppNonce({ admin, oftStore }, eid, normalizedPeer),
await this._createSetPeerAddressIx(normalizedPeer, eid),
await this._createSetPeerAddressIx(normalizedPeer, eid), // admin
oft.initSendLibrary({ admin: delegate, oftStore }, eid), // delegate
oft.initReceiveLibrary({ admin: delegate, oftStore }, eid), // delegate
await this._setPeerEnforcedOptionsIx(new Uint8Array([0, 3]), new Uint8Array([0, 3]), eid), // admin
await this._setPeerFeeBpsIx(eid), // admin
oft.initOAppNonce({ admin: delegate, oftStore }, eid, normalizedPeer), // delegate
await this._createSetPeerAddressIx(normalizedPeer, eid), // admin but is this needed? set twice...
])
)),
description: `Setting peer for eid ${eid} (${eidLabel}) to address ${peerAsBytes32}`,
description: `Setting peer for eid ${eid} (${eidLabel}) to address ${peerAsBytes32} ${delegate.publicKey} ${(await this._getAdmin()).publicKey}`,
}
}

Expand Down Expand Up @@ -292,18 +293,6 @@ export class OFT extends OmniSDK implements IOApp {
}
}

async isNonceInitialized(eid: EndpointId, peer: OmniAddress): Promise<boolean> {
const endpointSdk = await this.getEndpointSDK()
return endpointSdk.isOAppNonceInitialized(this.point.address, eid, peer)
}

async initializeNonce(eid: EndpointId, peer: OmniAddress): Promise<[OmniTransaction] | []> {
this.logger.verbose(`Initializing OApp nonce for peer ${peer} on ${formatEid(eid)}`)

const endpointSdk = await this.getEndpointSDK()
return endpointSdk.initializeOAppNonce(this.point.address, eid, peer)
}

async isSendLibraryInitialized(eid: EndpointId): Promise<boolean> {
const endpointSdk = await this.getEndpointSDK()
return endpointSdk.isSendLibraryInitialized(this.point.address, eid)
Expand Down Expand Up @@ -416,14 +405,17 @@ export class OFT extends OmniSDK implements IOApp {
}

public async initConfig(eid: EndpointId): Promise<OmniTransaction | undefined> {
const delegateAddress = await this.getDelegate()
// delegate may be undefined if it has not yet been set. In this case, use admin, which must exist.
const delegate = delegateAddress ? createNoopSigner(publicKey(delegateAddress)) : await this._getAdmin()
return {
...(await this.createTransaction(
this._umiToWeb3Tx([
oft.initConfig(
{
admin: await this._getAdmin(),
admin: delegate,
oftStore: this.umiPublicKey,
payer: createNoopSigner(this.umiUserAccount),
payer: delegate,
},
eid,
{
Expand All @@ -436,49 +428,6 @@ export class OFT extends OmniSDK implements IOApp {
}
}

public async addRemote(eid: EndpointId): Promise<OmniTransaction | undefined> {
const admin = createNoopSigner(this.umiUserAccount)
const oftStore = this.umiPublicKey
const ixs: WrappedInstruction[] = [
oft.initSendLibrary({ admin, oftStore }, eid),
oft.initReceiveLibrary({ admin, oftStore }, eid),
oft.setSendLibrary(
{ admin, oftStore },
{
sendLibraryProgram: fromWeb3JsPublicKey(UlnProgram.PROGRAM_ID),
remoteEid: eid,
}
),
oft.setReceiveLibrary(
{ admin, oftStore },
{
receiveLibraryProgram: fromWeb3JsPublicKey(UlnProgram.PROGRAM_ID),
remoteEid: eid,
}
),
await this._setPeerEnforcedOptionsIx(new Uint8Array([0, 3]), new Uint8Array([0, 3]), eid),
await this._setPeerFeeBpsIx(eid),
]
return {
...(await this.createTransaction(this._umiToWeb3Tx(ixs))),
description: `oft.addRemote(${eid})`,
}
}

public async initPeer(eid: number, peer: OmniAddress): Promise<OmniTransaction | undefined> {
const admin = createNoopSigner(this.umiUserAccount)
const oftStore = this.umiPublicKey
const normalizedPeer = normalizePeer(peer, eid)
const web3Transaction = this._umiToWeb3Tx([
oft.initOAppNonce({ admin, oftStore }, eid, normalizedPeer),
await this._createSetPeerAddressIx(normalizedPeer, eid),
])
return {
...(await this.createTransaction(web3Transaction)),
description: `oft.initPeer(${eid}, ${peer})`,
}
}

protected async _setOFTConfigIx(param: SetOFTConfigParams) {
return oft.setOFTConfig(
{
Expand Down Expand Up @@ -581,6 +530,14 @@ export class OFT extends OmniSDK implements IOApp {
return web3Transaction
}

protected async safeGetDelegate() {
const delegateAddress = await this.getDelegate()
if (!delegateAddress) {
throw new Error('No delegate found')
}
return createNoopSigner(publicKey(delegateAddress))
}

protected async _getAdmin(): Promise<Signer> {
const owner = await this.getOwner()
return createNoopSigner(publicKey(owner))
Expand Down
Loading

0 comments on commit 51c4086

Please sign in to comment.