Skip to content

Commit 543fc54

Browse files
nazreenCopilot
authored andcommitted
DEVREL-126 feat: validate Solana admin address for delegate/owner when wiring (#1538)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 4f0415f commit 543fc54

10 files changed

Lines changed: 105 additions & 4 deletions

File tree

.changeset/bright-cows-destroy.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@layerzerolabs/ua-devtools-solana": minor
3+
"@layerzerolabs/devtools-solana": minor
4+
"@layerzerolabs/io-devtools": minor
5+
---
6+
7+
validate solana owner or delegate is valid before proceeding to set

.changeset/tall-poems-explain.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@layerzerolabs/ua-devtools": patch
3+
---
4+
5+
bump target version for tsconfig
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@solana-developers/helpers pinned to 2.8.0 due to this issue: https://solana.stackexchange.com/questions/21945/issue-with-solana-developers-helpers-package-in-browser-environments-anchors?utm_source=chatgpt.com

packages/devtools-solana/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"dependencies": {
4040
"@safe-global/api-kit": "^1.3.0",
4141
"@safe-global/protocol-kit": "^1.3.0",
42-
"@solana-developers/helpers": "^2.8.1",
42+
"@solana-developers/helpers": "2.8.0",
4343
"ethers": "^5.7.2",
4444
"p-memoize": "~4.0.4"
4545
},
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { DebugLogger, KnownErrors } from '@layerzerolabs/io-devtools'
2+
import { Connection, PublicKey, SystemProgram } from '@solana/web3.js'
3+
import { PROGRAM_ID as SQUADS_PROGRAM_ID } from '@sqds/multisig'
4+
5+
/**
6+
* Returns true if the provided address is a valid on-curve public key. This can mean the address is either a 'regular' Solana address or a Squads Vault PDA.
7+
*/
8+
export function isOnCurveAddress(address: string): boolean {
9+
try {
10+
return PublicKey.isOnCurve(new PublicKey(address).toBytes())
11+
} catch {
12+
return false
13+
}
14+
}
15+
16+
/**
17+
* Returns true if the provided address could be a Squads vault PDA.
18+
*/
19+
export async function isPossibleSquadsVault(connection: Connection, address: string): Promise<boolean> {
20+
try {
21+
const pubkey = new PublicKey(address)
22+
const accountInfo = await connection.getAccountInfo(pubkey)
23+
24+
return accountInfo != null && accountInfo.owner.equals(SystemProgram.programId)
25+
} catch (error) {
26+
return false
27+
}
28+
}
29+
30+
export async function assertValidSolanaAdmin(connection: Connection, address: string): Promise<void> {
31+
const pubkey = new PublicKey(address)
32+
33+
try {
34+
const accountInfo = await connection.getAccountInfo(pubkey)
35+
36+
if (accountInfo != null && accountInfo.owner.equals(SQUADS_PROGRAM_ID)) {
37+
DebugLogger.printErrorAndFixSuggestion(KnownErrors.SOLANA_OWNER_OR_DELEGATE_CANNOT_BE_MULTISIG_ACCOUNT)
38+
throw new Error(
39+
`Invalid owner/delegate address ${address}. This is a Squads multisig account. Use the vault address instead.`
40+
)
41+
}
42+
43+
if (!isOnCurveAddress(address) && !(await isPossibleSquadsVault(connection, address))) {
44+
DebugLogger.printErrorAndFixSuggestion(KnownErrors.SOLANA_INVALID_OWNER_OR_DELEGATE)
45+
throw new Error(
46+
`Invalid owner/delegate address ${address}. Must be a valid on-curve address or a Squads Vault PDA.`
47+
)
48+
}
49+
} catch (error) {
50+
if (error instanceof Error) {
51+
throw error
52+
}
53+
throw new Error(String(error))
54+
}
55+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './accounts'
22
export * from './schema'
33
export * from './types'
4+
export * from './addresses'

packages/io-devtools/src/stdio/debugLogger.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export enum KnownErrors {
5454
ERROR_QUOTING_NATIVE_GAS_COST = 'ERROR_QUOTING_NATIVE_GAS_COST',
5555
ERROR_SENDING_TRANSACTION = 'ERROR_SENDING_TRANSACTION',
5656
ERROR_GETTING_HRE = 'ERROR_GETTING_HARDHAT_RUNTIME_ENVIRONMENT_FOR_NETWORK',
57+
SOLANA_INVALID_OWNER_OR_DELEGATE = 'SOLANA_INVALID_OWNER_OR_DELEGATE',
58+
SOLANA_OWNER_OR_DELEGATE_CANNOT_BE_MULTISIG_ACCOUNT = 'SOLANA_OWNER_OR_DELEGATE_MULTISIG_ACCOUNT',
5759
}
5860

5961
export enum KnownWarnings {
@@ -92,6 +94,14 @@ export const ERRORS_FIXES_MAP: Record<KnownErrors, ErrorFixInfo> = {
9294
tip: 'Have you added the srcEid network to your `./hardhat.config.ts` file?',
9395
info: 'If you loaded a custom OFT deployment from an EVM network, you must add the deployment srcEid to your `./hardhat.config.ts` file for the OFT to be found.',
9496
},
97+
[KnownErrors.SOLANA_INVALID_OWNER_OR_DELEGATE]: {
98+
tip: 'The owner or delegate of the Solana OApp must either be a regular on curve address or a Squads Vault Account.',
99+
info: 'Ensure that you are using a regular on-curve Solana address or a Squads Vault PDA as the owner or delegate of the OApp.',
100+
},
101+
[KnownErrors.SOLANA_OWNER_OR_DELEGATE_CANNOT_BE_MULTISIG_ACCOUNT]: {
102+
tip: 'The owner or delegate of the Solana OApp must not be the Squads multisig account address.',
103+
info: 'If you intend to use Squads Multisig, ensure that you are providing a Squads Vault address as the owner or delegate of the OApp. The Squads Multisig account address cannot be the owner or delegate.',
104+
},
95105
}
96106

97107
export const WARNINGS_FIXES_MAP: Record<KnownWarnings, ErrorFixInfo> = {

packages/ua-devtools-solana/src/oft/sdk.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { EndpointId } from '@layerzerolabs/lz-definitions'
1717
import { EndpointV2 } from '@layerzerolabs/protocol-devtools-solana'
1818
import { type Logger, printBoolean, printJson } from '@layerzerolabs/io-devtools'
1919
import { mapError, AsyncRetriable } from '@layerzerolabs/devtools'
20-
import { OmniSDK } from '@layerzerolabs/devtools-solana'
20+
import { assertValidSolanaAdmin, OmniSDK } from '@layerzerolabs/devtools-solana'
2121
import { Connection, PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'
2222
import { Options } from '@layerzerolabs/lz-v2-utilities'
2323
import assert from 'assert'
@@ -121,6 +121,7 @@ export class OFT extends OmniSDK implements IOApp {
121121
}
122122

123123
async setOwner(address: OmniAddress): Promise<OmniTransaction> {
124+
await assertValidSolanaAdmin(this.connection, address)
124125
this.logger.debug(`Setting owner to ${address}`)
125126

126127
return {
@@ -236,6 +237,7 @@ export class OFT extends OmniSDK implements IOApp {
236237
}
237238

238239
async setDelegate(delegate: OmniAddress): Promise<OmniTransaction> {
240+
await assertValidSolanaAdmin(this.connection, delegate)
239241
this.logger.debug(`Setting delegate to ${delegate}`)
240242
return {
241243
...(await this.createTransaction(this._umiToWeb3Tx([await this._setOFTDelegateIx(delegate)]))),

packages/ua-devtools/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"exclude": ["dist", "node_modules"],
44
"include": ["src", "test"],
55
"compilerOptions": {
6+
"target": "es2020",
67
"types": ["node", "jest"],
78
"paths": {
89
"@/*": ["./src/*"]

pnpm-lock.yaml

Lines changed: 21 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)