diff --git a/.github/workflows/check-branch-name.yml b/.github/workflows/check-branch-name.yml index 028a190ec..0e70cf56c 100644 --- a/.github/workflows/check-branch-name.yml +++ b/.github/workflows/check-branch-name.yml @@ -18,8 +18,8 @@ jobs: switch(base) { case 'main': case 'alpha': { - if (!/^hotfix\/[A-Za-z0-9-_\.]+$/.test(branch)) { - console.error(`::error::Branch name must start with 'hotfix/*' for PRs to ${base}`) + if (!/^(hotfix|release)\/[A-Za-z0-9-_\.]+$/.test(branch)) { + console.error(`::error::Branch name must start with 'hotfix/*' or 'release/*' for PRs to ${base}`) process.exit(1) } break; diff --git a/.github/workflows/commitlint-pr.yml b/.github/workflows/commitlint-pr.yml index e18a3d9c0..be2e8ec25 100644 --- a/.github/workflows/commitlint-pr.yml +++ b/.github/workflows/commitlint-pr.yml @@ -26,6 +26,7 @@ jobs: validateSingleCommit: false types: | hotfix + release feat fix chore diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 726ae3152..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,15 +0,0 @@ -# Security Policy - -## Supported Versions - -Use this section to tell people about which versions of your project are -currently being supported with security updates. - -| Version | Supported | -| ------- | ------------------ | -| 2.4.x | :white_check_mark: | -| < 2.4 | :x: | - -## Reporting a Vulnerability - -Please send a message to db#1770 on Discord. diff --git a/lerna.json b/lerna.json index 4b4570b19..ed51fac3b 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "npmClient": "pnpm", "packages": ["packages/*"], "exact": true, - "version": "2.18.2" + "version": "2.18.4" } diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index ff1c05088..000000000 --- a/netlify.toml +++ /dev/null @@ -1,4 +0,0 @@ -[[redirects]] - from = "/*" - to = "/index.html" - status = 200 \ No newline at end of file diff --git a/package.json b/package.json index 5fc1c2509..f113306a8 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint:fix:js": "prettier --write '{packages,examples}/**/*.{js,ts}' && eslint --fix '{packages,examples}/**/*.{js,ts}'", "lint:fix:sol": "prettier --write '{packages,examples}/*/{contracts,src}/**/*.sol'", "lint:fix": "pnpm run '/^lint:fix:(js|sol)/'", - "build": "pnpm -r --if-present run clean && pnpm -r --filter @usecannon/builder --filter @usecannon/cli --filter hardhat-cannon --filter @usecannon/api run build", + "build": "pnpm -r --if-present --filter @usecannon/builder --filter @usecannon/cli --filter hardhat-cannon --filter @usecannon/api run clean && pnpm -r --filter @usecannon/builder --filter @usecannon/cli --filter hardhat-cannon --filter @usecannon/api run build", "watch": "pnpm -r --parallel --filter @usecannon/builder --filter @usecannon/cli run watch", "version-alpha": "lerna version prerelease --no-private", "version-patch": "lerna version patch --no-private", diff --git a/packages/builder/package.json b/packages/builder/package.json index 875fbe010..d984eef4c 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@usecannon/builder", - "version": "2.18.2", + "version": "2.18.4", "description": "Assembles cannonfile.toml manifests into cannon packages.", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -43,7 +43,8 @@ "typedoc-plugin-zod": "^1.2.0" }, "dependencies": { - "@synthetixio/router": "^3.4.0", + "@usecannon/router": "^4.0.1", + "@usecannon/web-solc": "0.5.1", "axios": "^1.7.2", "axios-retry": "^4.4.2", "buffer": "^6.0.3", diff --git a/packages/builder/src/schemas.ts b/packages/builder/src/schemas.ts index 6a1578d8e..bbfa9863c 100644 --- a/packages/builder/src/schemas.ts +++ b/packages/builder/src/schemas.ts @@ -877,32 +877,32 @@ export const chainDefinitionSchema = z privateSourceCode: z .boolean() .describe( - 'Turns off inclusion of source code in packages. When set to true, Cannon cannot verify contracts on Etherscan.' + 'Turns off inclusion of source code in packages. When set to true, Cannon cannot verify contracts on Etherscan. Defaults to false.' ) .optional(), + /** + * Description for the package + */ + description: z.string().describe('Description for the package').optional(), + /** + * Keywords for search indexing + */ + keywords: z.array(z.string()).describe('Keywords for search indexing').optional(), + /** + * Any deployers that could publish this package. Will be used for automatic version management. + */ + deployers: z + .array( + z.string().refine((val) => !!val.match(RegExp(/^0x[a-fA-F0-9]{40}$/, 'gm')), { + message: 'Invalid Ethereum address', + }) + ) + .describe('Any deployers that could publish this package. Will be used for automatic version management.') + .optional(), }) .merge( z .object({ - /** - * Description for the package - */ - description: z.string().describe('Description for the package'), - /** - * Keywords for search indexing - */ - keywords: z.array(z.string()).describe('Keywords for search indexing'), - /** - * Any deployers that could publish this package. Will be used for automatic version management. - */ - deployers: z - .array( - z.string().refine((val) => !!val.match(RegExp(/^0x[a-fA-F0-9]{40}$/, 'gm')), { - message: 'Invalid Ethereum address', - }) - ) - .optional() - .describe('Any deployers that could publish this package. Will be used for automatic version management.'), /** * Object that allows the definition of values for use in next operations * ```toml diff --git a/packages/builder/src/steps/router.ts b/packages/builder/src/steps/router.ts index 3783dc5c6..d5f1c1113 100644 --- a/packages/builder/src/steps/router.ts +++ b/packages/builder/src/steps/router.ts @@ -2,6 +2,7 @@ import Debug from 'debug'; import _ from 'lodash'; import * as viem from 'viem'; import { z } from 'zod'; +import { generateRouter } from '@usecannon/router'; import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; import { ChainBuilderRuntime } from '../runtime'; import { routerSchema } from '../schemas'; @@ -13,6 +14,7 @@ import { getMergedAbiFromContractPaths, } from '../util'; import { template } from '../utils/template'; +import { compileContract } from '../utils/compile'; const debug = Debug('cannon:builder:router'); @@ -101,8 +103,6 @@ const routerStep = { config: Config, packageState: PackageState ): Promise { - const { generateRouter, getCompileInput, compileContract } = await import('@synthetixio/router'); - debug('exec', config); const contracts = config.contracts.map((n) => { @@ -111,6 +111,8 @@ const routerStep = { throw new Error(`contract not found: ${n}`); } + const contractName = n.replace('.', '_'); // Use step name, and replace '.' in case is pointing to an import. + return { constructorArgs: contract.constructorArgs, abi: contract.abi, @@ -118,9 +120,9 @@ const routerStep = { deployTxnHash: contract.deployTxnHash, deployTxnBlockNumber: '', deployTimestamp: '', - contractName: contract.contractName, + contractName: contractName, sourceName: contract.sourceName, - contractFullyQualifiedName: `${contract.sourceName}:${contract.contractName}`, + contractFullyQualifiedName: `${contract.sourceName}:${contractName}`, }; }); @@ -134,11 +136,7 @@ const routerStep = { debug('router source code', sourceCode); - // On Mainnet, use default local solc evmVersion, for everything else, 'paris' - const evmVersion = [1, 5, 11155111].includes(runtime.chainId) ? undefined : 'paris'; - - const inputData = getCompileInput(contractName, sourceCode, evmVersion); - const solidityInfo = await compileContract(contractName, sourceCode, evmVersion); + const { input: inputData, output: solidityInfo } = await compileContract(contractName, sourceCode); // the ABI is entirely based on the fallback call so we have to generate ABI here const routableAbi = getMergedAbiFromContractPaths(ctx, config.contracts); diff --git a/packages/builder/src/utils/compile.ts b/packages/builder/src/utils/compile.ts new file mode 100644 index 000000000..632ecc409 --- /dev/null +++ b/packages/builder/src/utils/compile.ts @@ -0,0 +1,81 @@ +import * as viem from 'viem'; +import { fetchSolc } from '@usecannon/web-solc'; + +interface CompileResult { + sourceName: string; + contractName: string; + abi: viem.Abi; + metadata: string; + solcVersion: string; + assembly: string; + bytecode: string; + deployedBytecode: string; + gasEstimates: { + creation: { + codeDepositCost: string; + executionCost: string; + totalCost: string; + }; + external: { + '': string; + }; + }; +} + +export async function compileContract( + contractName: string, + sourceCode: string, + evmVersion = 'paris', + compilerVersion = '0.8.27' +) { + const { compile, stopWorker } = await fetchSolc(compilerVersion); + + const sourceName = `${contractName}.sol`; + + const input = { + language: 'Solidity', + sources: { + [sourceName]: { + content: sourceCode, + }, + }, + settings: { + outputSelection: { + '*': { '*': ['*'] }, + }, + evmVersion, + }, + }; + + try { + const output = await compile(input); + + if (output.errors) { + throw new Error( + [ + `There was an error when compiling "${contractName}".`, + ...output.errors.map((err: { message: string }) => err.message), + ].join(' ') + ); + } + + const info = (output.contracts as any)[sourceName][contractName]; + const metadata = JSON.parse(info.metadata); + + const result = { + contractName, + sourceName, + abi: info.abi, + metadata: info.metadata, + solcVersion: metadata.compiler.version, + assembly: info.evm.assembly, + bytecode: info.evm.bytecode.object, + deployedBytecode: info.evm.deployedBytecode.object, + gasEstimates: info.evm.gasEstimates, + } satisfies CompileResult; + + return { input, output: result }; + } finally { + stopWorker(); + } +} diff --git a/packages/cli/package.json b/packages/cli/package.json index b118cccc9..580bf564a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@usecannon/cli", - "version": "2.18.2", + "version": "2.18.4", "description": "Utility for instantly loading cannon packages in standalone contexts", "main": "dist/src/index.js", "scripts": { diff --git a/packages/cli/src/commands/build.test.ts b/packages/cli/src/commands/build.test.ts index e798c5478..4389dfa90 100644 --- a/packages/cli/src/commands/build.test.ts +++ b/packages/cli/src/commands/build.test.ts @@ -79,9 +79,9 @@ describe('build', () => { let provider: viem.PublicClient & viem.WalletClient & viem.TestClient; beforeEach(() => { - jest - .spyOn(helpers, 'loadCannonfile') - .mockResolvedValue({ def: { danglingDependencies: {}, getDeployers: () => [] } } as any); + jest.spyOn(helpers, 'loadCannonfile').mockResolvedValue({ + def: { danglingDependencies: {}, getDeployers: () => [], isPublicSourceCode: () => false }, + } as any); provider = makeFakeProvider(); jest.spyOn(buildCommand, 'build').mockResolvedValue({ outputs: {}, provider, runtime: {} as any }); jest.spyOn(utilProvider, 'resolveProvider').mockResolvedValue({ provider: provider as any, signers: [] }); diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts index 9e3546a81..f4fbfaae3 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/commands/build.ts @@ -49,7 +49,7 @@ interface Params { wipe?: boolean; dryRun?: boolean; plugins?: boolean; - publicSourceCode?: boolean; + privateSourceCode?: boolean; rpcUrl?: string; registryPriority?: 'local' | 'onchain' | 'offline'; gasPrice?: bigint; @@ -72,7 +72,7 @@ export async function build({ wipe = false, dryRun, plugins = true, - publicSourceCode = false, + privateSourceCode = false, rpcUrl, registryPriority, gasPrice, @@ -123,7 +123,9 @@ export async function build({ getDefaultSigner, snapshots: chainId === CANNON_CHAIN_ID, allowPartialDeploy: chainId !== CANNON_CHAIN_ID, - publicSourceCode, + // ChainBuilderRuntime uses publicSourceCode to determine if source code should be included in the package + publicSourceCode: !privateSourceCode, + gasPrice, gasFee, priorityGasFee, @@ -198,7 +200,7 @@ export async function build({ log('Version: ' + cyanBright(`${pkgVersion}`)); log('Preset: ' + cyanBright(`${preset}`) + (preset == 'main' ? gray(' (default)') : '')); log('Chain ID: ' + cyanBright(`${chainId}`)); - if (publicSourceCode) { + if (!privateSourceCode) { log(`Private Source Code: ${cyanBright('false')} ${gray('(source code will be included in the package)')}`); } else { log(`Private Source Code: ${cyanBright('true')} ${gray('(source code will not be included in the resulting package)')}`); diff --git a/packages/cli/src/util/build.ts b/packages/cli/src/util/build.ts index 9bb2e139c..267f3567e 100644 --- a/packages/cli/src/util/build.ts +++ b/packages/cli/src/util/build.ts @@ -335,6 +335,7 @@ async function prepareBuildConfig( getSigner, getDefaultSigner, upgradeFrom: options.upgradeFrom, + privateSourceCode: !def.isPublicSourceCode(), wipe: options.wipe, dryRun: options.dryRun, overrideResolver, diff --git a/packages/cli/src/write-script/render-ethers.ts b/packages/cli/src/write-script/render-ethers.ts index 532bc25d7..aeadb9644 100644 --- a/packages/cli/src/write-script/render-ethers.ts +++ b/packages/cli/src/write-script/render-ethers.ts @@ -1,6 +1,12 @@ import { EOL } from 'node:os'; import { Transform } from 'node:stream'; +/** + * This script is used to deploy contracts using Ethers.js. + * It outputs a JS script that can be used to deploy contracts and execute transactions. + * Note: Make sure you add `.js` extension to the output file. + */ + import type { DumpLine, DumpRenderer } from './types'; const header = `/* eslint-disable */ diff --git a/packages/cli/src/write-script/render-foundry.ts b/packages/cli/src/write-script/render-foundry.ts new file mode 100644 index 000000000..cd750560d --- /dev/null +++ b/packages/cli/src/write-script/render-foundry.ts @@ -0,0 +1,75 @@ +import { EOL } from 'node:os'; +import { Transform } from 'node:stream'; + +/** + * This script is used to deploy contracts using Foundry Cast. + * It outputs a bash script that can be used to deploy contracts and execute transactions. + * Note: Make sure you add `.sh` extension to the output file. + */ + +const header = `#!/bin/bash + +# Set your environment variables +# Set your environment variables +# export PRIVATE_KEY= +# export RPC_URL= + +# Start processing transactions +`; + +const footer = ` +echo "Transactions complete." +`; + +export const createRenderer = () => + new Transform({ + objectMode: true, + construct(cb) { + this.push(header); // Bash script header + return cb(); + }, + transform(line, _, cb) { + const title = `[${line.type}.${line.label}]`; + + if (!line.result) { + // Logging non-transaction steps + this.push(`# ${' '.repeat(line.depth)}${title}${EOL}`); + } + + for (const { to, input, value } of line.txns) { + // Start building the `cast send` command + let command = 'cast send'; + + // Add `--to` if present (for non-deployment transactions) + if (to) { + command += `--to ${to}`; + } + + // Add `--value` if a value is specified + if (value) { + command += ` --value ${value}`; + } + + // Add private key and RPC URL from environment variables + command += ' --private-key $PRIVATE_KEY --rpc-url $RPC_URL'; + + if (!to) { + command += ' --create'; + } + + // Add calldata + command += ` ${input}`; + + // Log the title and command + const indent = ' '.repeat(line.depth); + this.push(`${indent}echo "Executing: ${title}"${EOL}`); + this.push(`${indent}${command}${EOL}${EOL}`); + } + + return cb(); + }, + flush(cb) { + this.push(footer); // Bash script footer + return cb(); + }, + }); diff --git a/packages/cli/src/write-script/write.ts b/packages/cli/src/write-script/write.ts index 88605f72e..4ba1c34da 100644 --- a/packages/cli/src/write-script/write.ts +++ b/packages/cli/src/write-script/write.ts @@ -6,7 +6,7 @@ import * as viem from 'viem'; import { createStepsStream } from './stream-steps'; import { DumpRenderer } from './types'; -export const WRITE_SCRIPT_FORMATS = ['json', 'ethers'] as const; +export const WRITE_SCRIPT_FORMATS = ['json', 'ethers', 'foundry'] as const; export type WriteScriptFormat = (typeof WRITE_SCRIPT_FORMATS)[number]; diff --git a/packages/hardhat-cannon/package.json b/packages/hardhat-cannon/package.json index ab0eafbb9..4b790304f 100644 --- a/packages/hardhat-cannon/package.json +++ b/packages/hardhat-cannon/package.json @@ -1,6 +1,6 @@ { "name": "hardhat-cannon", - "version": "2.18.2", + "version": "2.18.4", "description": "Agnostic chain construction. Select the protocols and configuration you need to quickly and easily verify your project", "author": "Synthetix", "license": "MIT", diff --git a/packages/hardhat-cannon/src/internal/cannon.ts b/packages/hardhat-cannon/src/internal/cannon.ts index 1f3dc6a99..30691156e 100644 --- a/packages/hardhat-cannon/src/internal/cannon.ts +++ b/packages/hardhat-cannon/src/internal/cannon.ts @@ -58,7 +58,7 @@ export async function cannonBuild(options: BuildOptions) { pkgInfo: loadPackageJson(path.join(hre.config.paths.root, 'package.json')), projectDirectory: hre.config.paths.root, registryPriority: options.registryPriority, - publicSourceCode: false, + privateSourceCode: true, }); return { outputs }; diff --git a/packages/hardhat-cannon/src/tasks/build.ts b/packages/hardhat-cannon/src/tasks/build.ts index 3cf978b19..219e995c0 100644 --- a/packages/hardhat-cannon/src/tasks/build.ts +++ b/packages/hardhat-cannon/src/tasks/build.ts @@ -195,7 +195,7 @@ task(TASK_BUILD, 'Assemble a defined chain and save it to to a state which can b persist: !dryRun && hre.network.name !== 'hardhat', overrideResolver: dryRun ? await createDryRunRegistry(resolveCliSettings()) : undefined, plugins: !!usePlugins, - publicSourceCode: hre.config.cannon.publicSourceCode, + privateSourceCode: !hre.config.cannon.publicSourceCode, writeScript, writeScriptFormat, } as const; diff --git a/packages/website/src/abi/Safe.ts b/packages/website/src/abi/Safe.ts new file mode 100644 index 000000000..a08d4cae3 --- /dev/null +++ b/packages/website/src/abi/Safe.ts @@ -0,0 +1,930 @@ +export const SafeABI = [ + { + type: 'constructor', + payable: false, + inputs: [], + }, + { + type: 'event', + anonymous: false, + name: 'AddedOwner', + inputs: [ + { + type: 'address', + name: 'owner', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ApproveHash', + inputs: [ + { + type: 'bytes32', + name: 'approvedHash', + indexed: true, + }, + { + type: 'address', + name: 'owner', + indexed: true, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ChangedFallbackHandler', + inputs: [ + { + type: 'address', + name: 'handler', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ChangedGuard', + inputs: [ + { + type: 'address', + name: 'guard', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ChangedThreshold', + inputs: [ + { + type: 'uint256', + name: 'threshold', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'DisabledModule', + inputs: [ + { + type: 'address', + name: 'module', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'EnabledModule', + inputs: [ + { + type: 'address', + name: 'module', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ExecutionFailure', + inputs: [ + { + type: 'bytes32', + name: 'txHash', + indexed: false, + }, + { + type: 'uint256', + name: 'payment', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ExecutionFromModuleFailure', + inputs: [ + { + type: 'address', + name: 'module', + indexed: true, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ExecutionFromModuleSuccess', + inputs: [ + { + type: 'address', + name: 'module', + indexed: true, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'ExecutionSuccess', + inputs: [ + { + type: 'bytes32', + name: 'txHash', + indexed: false, + }, + { + type: 'uint256', + name: 'payment', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'RemovedOwner', + inputs: [ + { + type: 'address', + name: 'owner', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'SafeReceived', + inputs: [ + { + type: 'address', + name: 'sender', + indexed: true, + }, + { + type: 'uint256', + name: 'value', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'SafeSetup', + inputs: [ + { + type: 'address', + name: 'initiator', + indexed: true, + }, + { + type: 'address[]', + name: 'owners', + indexed: false, + }, + { + type: 'uint256', + name: 'threshold', + indexed: false, + }, + { + type: 'address', + name: 'initializer', + indexed: false, + }, + { + type: 'address', + name: 'fallbackHandler', + indexed: false, + }, + ], + }, + { + type: 'event', + anonymous: false, + name: 'SignMsg', + inputs: [ + { + type: 'bytes32', + name: 'msgHash', + indexed: true, + }, + ], + }, + { + type: 'function', + name: 'VERSION', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [], + outputs: [ + { + type: 'string', + }, + ], + }, + { + type: 'function', + name: 'addOwnerWithThreshold', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'owner', + }, + { + type: 'uint256', + name: '_threshold', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'approveHash', + constant: false, + payable: false, + inputs: [ + { + type: 'bytes32', + name: 'hashToApprove', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'approvedHashes', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'address', + }, + { + type: 'bytes32', + }, + ], + outputs: [ + { + type: 'uint256', + }, + ], + }, + { + type: 'function', + name: 'changeThreshold', + constant: false, + payable: false, + inputs: [ + { + type: 'uint256', + name: '_threshold', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'checkNSignatures', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'bytes32', + name: 'dataHash', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'bytes', + name: 'signatures', + }, + { + type: 'uint256', + name: 'requiredSignatures', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'checkSignatures', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'bytes32', + name: 'dataHash', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'bytes', + name: 'signatures', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'disableModule', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'prevModule', + }, + { + type: 'address', + name: 'module', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'domainSeparator', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [], + outputs: [ + { + type: 'bytes32', + }, + ], + }, + { + type: 'function', + name: 'enableModule', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'module', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'encodeTransactionData', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'address', + name: 'to', + }, + { + type: 'uint256', + name: 'value', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'uint8', + name: 'operation', + }, + { + type: 'uint256', + name: 'safeTxGas', + }, + { + type: 'uint256', + name: 'baseGas', + }, + { + type: 'uint256', + name: 'gasPrice', + }, + { + type: 'address', + name: 'gasToken', + }, + { + type: 'address', + name: 'refundReceiver', + }, + { + type: 'uint256', + name: '_nonce', + }, + ], + outputs: [ + { + type: 'bytes', + }, + ], + }, + { + type: 'function', + name: 'execTransaction', + constant: false, + stateMutability: 'payable', + payable: true, + inputs: [ + { + type: 'address', + name: 'to', + }, + { + type: 'uint256', + name: 'value', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'uint8', + name: 'operation', + }, + { + type: 'uint256', + name: 'safeTxGas', + }, + { + type: 'uint256', + name: 'baseGas', + }, + { + type: 'uint256', + name: 'gasPrice', + }, + { + type: 'address', + name: 'gasToken', + }, + { + type: 'address', + name: 'refundReceiver', + }, + { + type: 'bytes', + name: 'signatures', + }, + ], + outputs: [ + { + type: 'bool', + name: 'success', + }, + ], + }, + { + type: 'function', + name: 'execTransactionFromModule', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'to', + }, + { + type: 'uint256', + name: 'value', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'uint8', + name: 'operation', + }, + ], + outputs: [ + { + type: 'bool', + name: 'success', + }, + ], + }, + { + type: 'function', + name: 'execTransactionFromModuleReturnData', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'to', + }, + { + type: 'uint256', + name: 'value', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'uint8', + name: 'operation', + }, + ], + outputs: [ + { + type: 'bool', + name: 'success', + }, + { + type: 'bytes', + name: 'returnData', + }, + ], + }, + { + type: 'function', + name: 'getChainId', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [], + outputs: [ + { + type: 'uint256', + }, + ], + }, + { + type: 'function', + name: 'getModulesPaginated', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'address', + name: 'start', + }, + { + type: 'uint256', + name: 'pageSize', + }, + ], + outputs: [ + { + type: 'address[]', + name: 'array', + }, + { + type: 'address', + name: 'next', + }, + ], + }, + { + type: 'function', + name: 'getOwners', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [], + outputs: [ + { + type: 'address[]', + }, + ], + }, + { + type: 'function', + name: 'getStorageAt', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'uint256', + name: 'offset', + }, + { + type: 'uint256', + name: 'length', + }, + ], + outputs: [ + { + type: 'bytes', + }, + ], + }, + { + type: 'function', + name: 'getThreshold', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [], + outputs: [ + { + type: 'uint256', + }, + ], + }, + { + type: 'function', + name: 'getTransactionHash', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'address', + name: 'to', + }, + { + type: 'uint256', + name: 'value', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'uint8', + name: 'operation', + }, + { + type: 'uint256', + name: 'safeTxGas', + }, + { + type: 'uint256', + name: 'baseGas', + }, + { + type: 'uint256', + name: 'gasPrice', + }, + { + type: 'address', + name: 'gasToken', + }, + { + type: 'address', + name: 'refundReceiver', + }, + { + type: 'uint256', + name: '_nonce', + }, + ], + outputs: [ + { + type: 'bytes32', + }, + ], + }, + { + type: 'function', + name: 'isModuleEnabled', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'address', + name: 'module', + }, + ], + outputs: [ + { + type: 'bool', + }, + ], + }, + { + type: 'function', + name: 'isOwner', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'address', + name: 'owner', + }, + ], + outputs: [ + { + type: 'bool', + }, + ], + }, + { + type: 'function', + name: 'nonce', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [], + outputs: [ + { + type: 'uint256', + }, + ], + }, + { + type: 'function', + name: 'removeOwner', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'prevOwner', + }, + { + type: 'address', + name: 'owner', + }, + { + type: 'uint256', + name: '_threshold', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'requiredTxGas', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'to', + }, + { + type: 'uint256', + name: 'value', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'uint8', + name: 'operation', + }, + ], + outputs: [ + { + type: 'uint256', + }, + ], + }, + { + type: 'function', + name: 'setFallbackHandler', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'handler', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'setGuard', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'guard', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'setup', + constant: false, + payable: false, + inputs: [ + { + type: 'address[]', + name: '_owners', + }, + { + type: 'uint256', + name: '_threshold', + }, + { + type: 'address', + name: 'to', + }, + { + type: 'bytes', + name: 'data', + }, + { + type: 'address', + name: 'fallbackHandler', + }, + { + type: 'address', + name: 'paymentToken', + }, + { + type: 'uint256', + name: 'payment', + }, + { + type: 'address', + name: 'paymentReceiver', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'signedMessages', + constant: true, + stateMutability: 'view', + payable: false, + inputs: [ + { + type: 'bytes32', + }, + ], + outputs: [ + { + type: 'uint256', + }, + ], + }, + { + type: 'function', + name: 'simulateAndRevert', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'targetContract', + }, + { + type: 'bytes', + name: 'calldataPayload', + }, + ], + outputs: [], + }, + { + type: 'function', + name: 'swapOwner', + constant: false, + payable: false, + inputs: [ + { + type: 'address', + name: 'prevOwner', + }, + { + type: 'address', + name: 'oldOwner', + }, + { + type: 'address', + name: 'newOwner', + }, + ], + outputs: [], + }, +] as const; diff --git a/packages/website/src/features/Deploy/QueueFromGitOpsPage.tsx b/packages/website/src/features/Deploy/QueueFromGitOpsPage.tsx index 6600a1335..52ce8c23d 100644 --- a/packages/website/src/features/Deploy/QueueFromGitOpsPage.tsx +++ b/packages/website/src/features/Deploy/QueueFromGitOpsPage.tsx @@ -563,7 +563,7 @@ export default function QueueFromGitOps() { !prevDeployLocation && tomlRequiresPrevPackage && !previousPackageInput) || - canTomlBeDeployedUsingWebsite; + !canTomlBeDeployedUsingWebsite; const PreviewButton = ({ message }: { message?: string }) => ( @@ -930,10 +930,18 @@ export default function QueueFromGitOps() { > {deployer.queuedTransactions.length === 0 ? ( - - Some transactions should be executed outside the safe - before staging. You can execute these now in your browser. - By clicking the button below. + + The following steps should be executed outside the safe + before staging. + {buildState.result?.deployerSteps.map((s) => ( + + - {s.name} + + ))} + + You can execute these now in your browser. By clicking + the button below. +