Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/gorgeous-cobras-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@layerzerolabs/ua-devtools-evm-hardhat": patch
"@layerzerolabs/lzapp-migration-example": patch
"@layerzerolabs/oapp-solana-example": patch
"@layerzerolabs/oft-solana-example": patch
"@layerzerolabs/devtools": patch
---

fix misleading message after running init-config
4 changes: 4 additions & 0 deletions docs/EXAMPLES_SPECS.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ Currently, this document will only detail the structure for the READMEs of the e
- Goal: Resolve errors and setup issues
- Contents: Link to general troubleshooting + local fixes

16.7. **Audits** _(include only if audits exist)_
- Goal: Link to audit reports for transparency
- Contents: Commit hash audited + links to audit report PDFs

Any sections that don't appear in the above list should be considered for removal. Before removing, ask the user for confirmation.


Expand Down
14 changes: 8 additions & 6 deletions examples/lzapp-migration/tasks/solana/initConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ interface Args {
// This task will use the `initOFTAccounts` configurator that initializes the Solana accounts
const initConfigTask = wireLikeTask('lz:oft:solana:init-config') as ConfigurableTaskDefinition

// This task will use the `initOFTAccounts` configurator that initializes the Solana accounts
initConfigTask
.setDescription('Initialize OFT accounts for Solana')
.setAction(async (args: Args, hre) =>
hre.run(TASK_LZ_OAPP_WIRE, { ...args, isSolanaInitConfig: true, internalConfigurator: initOFTAccounts })
)
initConfigTask.setDescription('Initialize OFT accounts for Solana').setAction(async (args: Args, hre) =>
hre.run(TASK_LZ_OAPP_WIRE, {
...args,
isSolanaInitConfig: true,
internalConfigurator: initOFTAccounts,
noActionMessage: 'Pathway config already initialized',
})
)
7 changes: 0 additions & 7 deletions examples/oapp-solana/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
// Force ts-node to use CommonJS mode
// This must be set before any imports
process.env.TS_NODE_COMPILER_OPTIONS = JSON.stringify({
module: 'commonjs',
esModuleInterop: true,
})

// Get the environment configuration from .env file
//
// To make use of automatic environment setup:
Expand Down
14 changes: 8 additions & 6 deletions examples/oapp-solana/tasks/solana/initConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ interface Args {
// This task will use the `initOFTAccounts` configurator that initializes the Solana accounts
const initConfigTask = wireLikeTask('lz:oapp:solana:init-config') as ConfigurableTaskDefinition

// TODO: currently the message for 'already done' state is "OApp is already wired." which is misleading -> should be changed to "Pathway Config already initialized"
initConfigTask
.setDescription('Initialize OApp accounts for Solana')
.setAction(async (args: Args, hre) =>
hre.run(TASK_LZ_OAPP_WIRE, { ...args, internalConfigurator: initOAppAccounts, isSolanaInitConfig: true })
)
initConfigTask.setDescription('Initialize OApp accounts for Solana').setAction(async (args: Args, hre) =>
hre.run(TASK_LZ_OAPP_WIRE, {
...args,
internalConfigurator: initOAppAccounts,
isSolanaInitConfig: true,
noActionMessage: 'Pathway config already initialized',
})
)
14 changes: 14 additions & 0 deletions examples/oft-solana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,17 @@ Refer to [Verify the OFT Program](https://docs.layerzero.network/v2/developers/s
### Troubleshooting

Refer to the [Solana Troubleshooting page on the LayerZero Docs](https://docs.layerzero.network/v2/developers/solana/troubleshooting/common-errors) to see how to solve common error when deploying Solana OFTs.

### Audits

For the Solana OFT program, the last change was via commit [6a07bb7](https://github.com/LayerZero-Labs/devtools/commit/6a07bb7e089349995ce4b30978512aff001cc131)

The `6a07bb7` commit hash audited in the following 2 reports:

1. SolanaOFTandDevTools-Ottersec-24SEPT2024.pdf

- https://github.com/LayerZero-Labs/Audits/blob/main/audits/SolanaOFTandDevTools-Ottersec-24SEPT2024.pdf

2. SolanaOFTandDevTools-Pashov-17SEPT2024.pdf

- https://github.com/LayerZero-Labs/Audits/blob/main/audits/SolanaOFTandDevTools-Pashov-17SEPT2024.pdf
7 changes: 0 additions & 7 deletions examples/oft-solana/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
// Force ts-node to use CommonJS mode
// This must be set before any imports
process.env.TS_NODE_COMPILER_OPTIONS = JSON.stringify({
module: 'commonjs',
esModuleInterop: true,
})

// Get the environment configuration from .env file
//
// To make use of automatic environment setup:
Expand Down
14 changes: 8 additions & 6 deletions examples/oft-solana/tasks/solana/initConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ interface Args {
// This task will use the `initOFTAccounts` configurator that initializes the Solana accounts
const initConfigTask = wireLikeTask('lz:oft:solana:init-config') as ConfigurableTaskDefinition

// TODO: currently the message for 'already done' state is "OApp is already wired." which is misleading -> should be changed to "Pathway Config already initialized"
initConfigTask
.setDescription('Initialize OFT accounts for Solana')
.setAction(async (args: Args, hre) =>
hre.run(TASK_LZ_OAPP_WIRE, { ...args, internalConfigurator: initOFTAccounts, isSolanaInitConfig: true })
)
initConfigTask.setDescription('Initialize OFT accounts for Solana').setAction(async (args: Args, hre) =>
hre.run(TASK_LZ_OAPP_WIRE, {
...args,
internalConfigurator: initOFTAccounts,
isSolanaInitConfig: true,
noActionMessage: 'Pathway config already initialized',
})
)
77 changes: 74 additions & 3 deletions packages/devtools-evm-hardhat/src/tasks/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { task } from 'hardhat/config'
import type { ActionType } from 'hardhat/types'
import type { ActionType, HardhatRuntimeEnvironment } from 'hardhat/types'
import { TASK_COMPILE } from 'hardhat/builtin-tasks/task-names'
import { TASK_LZ_DEPLOY } from '@/constants/tasks'
import {
Expand All @@ -17,11 +17,57 @@ import { formatEid } from '@layerzerolabs/devtools'
import { getEidsByNetworkName, getHreByNetworkName } from '@/runtime'
import { types } from '@/cli'
import { promptForText } from '@layerzerolabs/io-devtools'
import { Deployment } from 'hardhat-deploy/dist/types'
import { Deployment, DeployFunction } from 'hardhat-deploy/dist/types'
import { assertDefinedNetworks, assertHardhatDeploy } from '@/internal/assertions'
import { splitCommaSeparated } from '@layerzerolabs/devtools'
import { isDeepEqual } from '@layerzerolabs/devtools'
import { Stage, endpointIdToStage } from '@layerzerolabs/lz-definitions'
import { readdirSync, statSync } from 'fs'
import { join, extname } from 'path'

/**
* Get all available tags from deploy scripts in the given deploy paths.
* Uses require() with ts-node/esm loader to handle TypeScript files.
*/
const getAvailableTagsFromDeployScripts = async (hre: HardhatRuntimeEnvironment): Promise<Set<string>> => {
const tags = new Set<string>()
const deployPaths = hre.config.paths.deploy

for (const deployPath of deployPaths) {
try {
const files = readdirSync(deployPath)
for (const file of files) {
const filePath = join(deployPath, file)
// Skip directories and non-script files
if (statSync(filePath).isDirectory()) {
continue
}
const ext = extname(file)
if (!['.js', '.ts'].includes(ext)) {
continue
}

try {
// Use require which works with ts-node/register in hardhat context
// eslint-disable-next-line @typescript-eslint/no-var-requires
const deployScript = require(filePath)
const deployFunc: DeployFunction = deployScript.default ?? deployScript
if (deployFunc?.tags) {
for (const tag of deployFunc.tags) {
tags.add(tag)
}
}
} catch {
// Skip files that can't be imported
}
}
} catch {
// Skip paths that don't exist
}
}

return tags
}

interface TaskArgs {
networks?: string[]
Expand Down Expand Up @@ -166,6 +212,16 @@ const action: ActionType<TaskArgs> = async (
logger.warn(`Will use all deployment scripts`)
} else {
logger.info(`Will use deploy scripts tagged with ${selectedTags.join(', ')}`)

// Check if selected tags match any available deploy script tags
const availableTags = await getAvailableTagsFromDeployScripts(hre)
const unmatchedTags = selectedTags.filter((tag) => !availableTags.has(tag))

if (unmatchedTags.length > 0) {
logger.warn(
`The following tags do not match any deploy scripts: ${unmatchedTags.join(', ')}. Available tags: ${[...availableTags].join(', ') || 'none'}`
)
}
}

// Now we confirm with the user that they want to continue
Expand Down Expand Up @@ -261,8 +317,23 @@ const action: ActionType<TaskArgs> = async (
error == null ? [] : [{ networkName, error }]
)

// If nothing went wrong we just exit
// We check whether any contracts were actually deployed
const totalContractsDeployed = Object.values(results).reduce(
(sum, { contracts }) => sum + Object.keys(contracts ?? {}).length,
0
)

// If nothing went wrong we check if any contracts were deployed
if (errors.length === 0) {
if (totalContractsDeployed === 0) {
return (
logger.warn(
`${printBoolean(false)} No contracts were deployed. This could mean the deploy script tags don't match any scripts, or all contracts were already deployed.`
),
results
)
}

return logger.info(`${printBoolean(true)} Your contracts are now deployed`), results
}

Expand Down
8 changes: 7 additions & 1 deletion packages/devtools/src/flows/wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export interface CreateWireFlowArgs<TOmniGraph extends OmniGraph> {
logger?: Logger
executeConfig: ConfigExecuteFlow<TOmniGraph>
signAndSend: SignAndSendFlow
/**
* Custom message to display when no transactions are needed.
* Defaults to "The OApp is wired, no action is necessary"
*/
noActionMessage?: string
}

export interface WireFlowArgs<TOmniGraph extends OmniGraph> {
Expand All @@ -25,6 +30,7 @@ export const createWireFlow =
logger = createLogger(),
executeConfig,
signAndSend,
noActionMessage = 'The OApp is wired, no action is necessary',
}: CreateWireFlowArgs<TOmniGraph>) =>
async ({
graph,
Expand Down Expand Up @@ -55,7 +61,7 @@ export const createWireFlow =

// If there are no transactions that need to be executed, we'll just exit
if (transactions.length === 0) {
logger.info(`The OApp is wired, no action is necessary`)
logger.info(noActionMessage)

return [[], [], []]
}
Expand Down
7 changes: 7 additions & 0 deletions packages/ua-devtools-evm-hardhat/src/tasks/oapp/wire/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ interface TaskArgs {
* Exclude connections that originate from the specified EndpointIds.
*/
skipConnectionsFromEids?: string[]
/**
* Custom message to display when no transactions are needed.
* Defaults to "The OApp is wired, no action is necessary"
*/
noActionMessage?: string
}

const action: ActionType<TaskArgs> = async (
Expand All @@ -74,6 +79,7 @@ const action: ActionType<TaskArgs> = async (
signAndSendSubtask = SUBTASK_LZ_SIGN_AND_SEND,
outputFilename,
skipConnectionsFromEids,
noActionMessage,
},
hre
): Promise<SignAndSendResult> => {
Expand Down Expand Up @@ -105,6 +111,7 @@ const action: ActionType<TaskArgs> = async (
// Then create the wire flow
const wireFlow = createWireFlow({
logger,
noActionMessage,
// We use hardhat subtasks to provide the option to override certain behaviors on a more granular level
executeConfig: ({ graph }) => hre.run(configureSubtask, { graph } satisfies SubtaskConfigureTaskArgs),
signAndSend: ({ transactions }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ send -- "\r"

expect "Will deploy 3 networks: britney, tango, vengaboys"
expect "Will use deploy scripts tagged with MeNoExist"
expect "do not match any deploy scripts"
expect "Do you want to continue?"
send -- "\r"

expect "Deploying..."
expect "Your contracts are now deployed"
expect "No contracts were deployed"

expect eof
2 changes: 2 additions & 0 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
"globalDependencies": ["tsconfig.json"],
"globalEnv": ["NODE_ENV"],
"globalPassThroughEnv": [
"TS_NODE_FILES",
"TS_NODE_PROJECT",
"LZ_DEVTOOLS_ENABLE_DEPLOY_LOGGING",
"LZ_DEVTOOLS_ENABLE_SOLANA_TESTS",
"LZ_ENABLE_EXPERIMENTAL_BATCHED_SEND",
Expand Down