diff --git a/configs/envs/.env.zksync b/configs/envs/.env.zksync index 56e104488b..3ae765711d 100644 --- a/configs/envs/.env.zksync +++ b/configs/envs/.env.zksync @@ -10,6 +10,8 @@ NEXT_PUBLIC_APP_ENV=development NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws # Instance ENVs +NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS=none + NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com NEXT_PUBLIC_API_BASE_PATH=/ NEXT_PUBLIC_API_HOST=zksync.blockscout.com diff --git a/playwright/fixtures/mockEnvs.ts b/playwright/fixtures/mockEnvs.ts index b0a8b4881d..9bd117d86c 100644 --- a/playwright/fixtures/mockEnvs.ts +++ b/playwright/fixtures/mockEnvs.ts @@ -37,6 +37,7 @@ export const ENVS_MAP: Record> = { zkSyncRollup: [ [ 'NEXT_PUBLIC_ROLLUP_TYPE', 'zkSync' ], [ 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', 'https://localhost:3101' ], + [ 'NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS', 'none' ], ], bridgedTokens: [ [ 'NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS', '[{"id":"1","title":"Ethereum","short_title":"ETH","base_url":"https://eth.blockscout.com/token/"},{"id":"56","title":"Binance Smart Chain","short_title":"BSC","base_url":"https://bscscan.com/token/"},{"id":"99","title":"POA","short_title":"POA","base_url":"https://blockscout.com/poa/core/token/"}]' ], diff --git a/types/api/contract.ts b/types/api/contract.ts index ad9aa0f4b9..1d73681e30 100644 --- a/types/api/contract.ts +++ b/types/api/contract.ts @@ -87,6 +87,7 @@ export interface SmartContractVerificationConfigRaw { is_rust_verifier_microservice_enabled: boolean; license_types: Record; zk_compiler_versions?: Array; + zk_optimization_modes?: Array; } export type SmartContractVerificationResponse = { diff --git a/ui/contractVerification/ContractVerificationForm.pw.tsx b/ui/contractVerification/ContractVerificationForm.pw.tsx index 9aa07c10e5..245cb1df31 100644 --- a/ui/contractVerification/ContractVerificationForm.pw.tsx +++ b/ui/contractVerification/ContractVerificationForm.pw.tsx @@ -2,6 +2,7 @@ import React from 'react'; import type { SmartContractVerificationConfig } from 'types/client/contract'; +import { ENVS_MAP } from 'playwright/fixtures/mockEnvs'; import * as socketServer from 'playwright/fixtures/socketServer'; import { test, expect } from 'playwright/lib'; @@ -215,3 +216,17 @@ test('solidity-foundry method', async({ render, page }) => { await expect(component).toHaveScreenshot(); }); + +test('verification of zkSync contract', async({ render, mockEnvs }) => { + const zkSyncFormConfig: SmartContractVerificationConfig = { + ...formConfig, + verification_options: [ 'standard-input' ], + zk_compiler_versions: [ 'v1.4.1', 'v1.4.0', 'v1.3.23', 'v1.3.22' ], + zk_optimization_modes: [ '0', '1', '2', '3', 's', 'z' ], + }; + + await mockEnvs(ENVS_MAP.zkSyncRollup); + const component = await render(, { hooksConfig }); + + await expect(component).toHaveScreenshot(); +}); diff --git a/ui/contractVerification/ContractVerificationForm.tsx b/ui/contractVerification/ContractVerificationForm.tsx index c8e6a85057..4457b64280 100644 --- a/ui/contractVerification/ContractVerificationForm.tsx +++ b/ui/contractVerification/ContractVerificationForm.tsx @@ -41,7 +41,7 @@ interface Props { const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Props) => { const formApi = useForm({ mode: 'onBlur', - defaultValues: methodFromQuery ? getDefaultValues(methodFromQuery, config, hash, null) : undefined, + defaultValues: getDefaultValues(methodFromQuery, config, hash, null), }); const { control, handleSubmit, watch, formState, setError, reset, getFieldState } = formApi; const submitPromiseResolver = React.useRef<(value: unknown) => void>(); diff --git a/ui/contractVerification/ContractVerificationMethod.tsx b/ui/contractVerification/ContractVerificationMethod.tsx index 24bef17bf4..9e5a081f36 100644 --- a/ui/contractVerification/ContractVerificationMethod.tsx +++ b/ui/contractVerification/ContractVerificationMethod.tsx @@ -4,14 +4,15 @@ import React from 'react'; interface Props { title: string; children: React.ReactNode; + disableScroll?: boolean; } -const ContractVerificationMethod = ({ title, children }: Props) => { +const ContractVerificationMethod = ({ title, children, disableScroll }: Props) => { const ref = React.useRef(null); React.useEffect(() => { - ref.current?.scrollIntoView({ behavior: 'smooth' }); - }, []); + !disableScroll && ref.current?.scrollIntoView({ behavior: 'smooth' }); + }, [ disableScroll ]); return (
diff --git a/ui/contractVerification/__screenshots__/ContractVerificationForm.pw.tsx_default_verification-of-zkSync-contract-1.png b/ui/contractVerification/__screenshots__/ContractVerificationForm.pw.tsx_default_verification-of-zkSync-contract-1.png new file mode 100644 index 0000000000..8cb52d3594 Binary files /dev/null and b/ui/contractVerification/__screenshots__/ContractVerificationForm.pw.tsx_default_verification-of-zkSync-contract-1.png differ diff --git a/ui/contractVerification/fields/ContractVerificationFieldMethod.tsx b/ui/contractVerification/fields/ContractVerificationFieldMethod.tsx index d74d2a5504..5eebcd701a 100644 --- a/ui/contractVerification/fields/ContractVerificationFieldMethod.tsx +++ b/ui/contractVerification/fields/ContractVerificationFieldMethod.tsx @@ -51,6 +51,7 @@ const ContractVerificationFieldMethod = ({ control, isDisabled, methods }: Props isDisabled={ isDisabled } isRequired isAsync={ false } + isReadOnly={ options.length === 1 } /> ); }, [ isDisabled, isMobile, options ]); diff --git a/ui/contractVerification/fields/ContractVerificationFieldZkOptimization.tsx b/ui/contractVerification/fields/ContractVerificationFieldZkOptimization.tsx index c839e9e626..ac6b58cb88 100644 --- a/ui/contractVerification/fields/ContractVerificationFieldZkOptimization.tsx +++ b/ui/contractVerification/fields/ContractVerificationFieldZkOptimization.tsx @@ -4,12 +4,17 @@ import type { ControllerRenderProps } from 'react-hook-form'; import { Controller, useFormContext } from 'react-hook-form'; import type { FormFields } from '../types'; +import type { SmartContractVerificationConfig } from 'types/client/contract'; import CheckboxInput from 'ui/shared/CheckboxInput'; import ContractVerificationFormRow from '../ContractVerificationFormRow'; -const ContractVerificationFieldZkOptimization = () => { +interface Props { + config: SmartContractVerificationConfig; +} + +const ContractVerificationFieldZkOptimization = ({ config }: Props) => { const [ isEnabled, setIsEnabled ] = React.useState(false); const { formState, control } = useFormContext(); @@ -41,14 +46,14 @@ const ContractVerificationFieldZkOptimization = () => { placeholder="Optimization mode" isInvalid={ Boolean(error) } > - { [ '0', '1', '2', '3', 'z', 's' ].map((value) => ( + { config.zk_optimization_modes?.map((value) => ( )) } ); - }, [ error, formState.isSubmitting ]); + }, [ config.zk_optimization_modes, error, formState.isSubmitting ]); return ( @@ -63,7 +68,6 @@ const ContractVerificationFieldZkOptimization = () => { name="optimization_mode" control={ control } render={ renderInputControl } - rules={{ required: true }} /> ) } diff --git a/ui/contractVerification/methods/ContractVerificationStandardInput.tsx b/ui/contractVerification/methods/ContractVerificationStandardInput.tsx index f998cd4973..4cca7f95e6 100644 --- a/ui/contractVerification/methods/ContractVerificationStandardInput.tsx +++ b/ui/contractVerification/methods/ContractVerificationStandardInput.tsx @@ -17,7 +17,7 @@ const rollupFeature = config.features.rollup; const ContractVerificationStandardInput = ({ config }: { config: SmartContractVerificationConfig }) => { return ( - + { !config?.is_rust_verifier_microservice_enabled && } { rollupFeature.isEnabled && rollupFeature.type === 'zkSync' && } @@ -27,7 +27,7 @@ const ContractVerificationStandardInput = ({ config }: { config: SmartContractVe hint="Upload the standard input JSON file created during contract compilation." required /> - { rollupFeature.isEnabled && rollupFeature.type === 'zkSync' && } + { rollupFeature.isEnabled && rollupFeature.type === 'zkSync' && } { !config?.is_rust_verifier_microservice_enabled && } ); diff --git a/ui/contractVerification/utils.ts b/ui/contractVerification/utils.ts index 41116415a6..2c4a728fe0 100644 --- a/ui/contractVerification/utils.ts +++ b/ui/contractVerification/utils.ts @@ -156,11 +156,18 @@ export const DEFAULT_VALUES: Record }; export function getDefaultValues( - method: SmartContractVerificationMethod, + methodParam: SmartContractVerificationMethod | undefined, config: SmartContractVerificationConfig, hash: string | undefined, licenseType: FormFields['license_type'], ) { + const singleMethod = config.verification_options.length === 1 ? config.verification_options[0] : undefined; + const method = singleMethod || methodParam; + + if (!method) { + return; + } + const defaultValues: FormFields = { ...DEFAULT_VALUES[method], address: hash || '', license_type: licenseType }; if ('evm_version' in defaultValues) { @@ -180,6 +187,13 @@ export function getDefaultValues( } } + if (singleMethod) { + defaultValues.method = { + label: METHOD_LABELS[config.verification_options[0]], + value: config.verification_options[0], + }; + } + return defaultValues; }