Merge branch 'pastedCodeSafety' of https://github.com/ethereum/remix-project into pastedCodeSafety

pull/5344/head
STetsing 1 month ago
commit 6b0bec0f31
  1. 2
      apps/circuit-compiler/src/app/actions/constant.ts
  2. 4
      apps/remix-dapp/src/locales/en/udapp.json
  3. 50
      apps/remix-ide/src/app/providers/environment-explorer.tsx
  4. 8
      apps/remix-ide/src/app/providers/vm-provider.tsx
  5. 4
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  6. 76
      apps/remix-ide/src/app/udapp/run-tab.tsx
  7. 36
      apps/remix-ide/src/blockchain/blockchain.tsx
  8. 57
      libs/remix-ui/run-tab/src/lib/components/environment.tsx
  9. 10
      libs/remix-ui/run-tab/src/lib/components/settingsUI.tsx
  10. 2
      libs/remix-ui/run-tab/src/lib/types/index.ts
  11. 4
      libs/remix-ws-templates/src/templates/hashchecker/templates/plonk_verifier.sol.ejs
  12. 4
      libs/remix-ws-templates/src/templates/rln/templates/plonk_verifier.sol.ejs
  13. 4
      libs/remix-ws-templates/src/templates/semaphore/templates/plonk_verifier.sol.ejs

@ -318,7 +318,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {

@ -49,6 +49,9 @@
"udapp.enterAMessageToSign": "Enter a message to sign",
"udapp.hash": "hash",
"udapp.signature": "signature",
"udapp.saveVmStateTitle": "Save VM state",
"udapp.saveVmStateLabel": "State Name",
"udapp.saveVmStateTip": "Saved VM states can be pinned as environment using Environment Explorer",
"udapp.injectedTitle": "Unfortunately it's not possible to create an account using injected provider. Please create the account directly from your provider (i.e metamask or other of the same type).",
"udapp.createNewAccount": "Create a new account",
"udapp.web3Title": "Creating an account is possible only in Personal mode. Please go to Settings to enable it.",
@ -63,6 +66,7 @@
"udapp._comment_environment.tsx": "libs/remix-ui/run-tab/src/lib/components/environment.tsx",
"udapp.environment": "Environment",
"udapp.environmentDocs": "Click for docs about Environment",
"udapp.saveVmState": "Save VM state",
"udapp.tooltipText2": "Open chainlist.org and get the connection specs of the chain you want to interact with.",
"udapp.tooltipText3": "Click to open a bridge for converting L1 mainnet ETH to the selected network currency.",

@ -1,6 +1,6 @@
import React from 'react' // eslint-disable-line
import { ViewPlugin } from '@remixproject/engine-web'
import { PluginViewWrapper } from '@remix-ui/helper'
import { CustomTooltip, PluginViewWrapper } from '@remix-ui/helper'
import { RemixUIGridView } from '@remix-ui/remix-ui-grid-view'
import { RemixUIGridSection } from '@remix-ui/remix-ui-grid-section'
import { RemixUIGridCell } from '@remix-ui/remix-ui-grid-cell'
@ -25,7 +25,7 @@ const profile = {
methods: []
}
type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked VMs'
type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' | 'Remix forked VMs' | 'Saved VM States'
export class EnvironmentExplorer extends ViewPlugin {
providers: { [key in ProvidersSection]: Provider[] }
@ -39,6 +39,7 @@ export class EnvironmentExplorer extends ViewPlugin {
this.providers = {
'Injected': [],
'Remix VMs': [],
'Saved VM States': [],
'Remix forked VMs': [],
'Externals': []
}
@ -57,6 +58,8 @@ export class EnvironmentExplorer extends ViewPlugin {
this.providers['Remix forked VMs'].push(provider)
} else if (provider.isVM) {
this.providers['Remix VMs'].push(provider)
} else if (provider.isSavedState) {
this.providers['Saved VM States'].push(provider)
} else {
this.providers['Externals'].push(provider)
}
@ -84,6 +87,7 @@ export class EnvironmentExplorer extends ViewPlugin {
this.providers = {
'Injected': [],
'Remix VMs': [],
'Saved VM States': [],
'Externals': [],
'Remix forked VMs': []
}
@ -171,6 +175,48 @@ export class EnvironmentExplorer extends ViewPlugin {
<div>{provider.description}</div>
</RemixUIGridCell>
})}</RemixUIGridSection>
<RemixUIGridSection
plugin={this}
title='Deploy to an In-browser Saved VM State.'
hScrollable={false}
>{this.providers['Saved VM States'].map(provider => {
const { latestBlock, timestamp } = JSON.parse(provider.description)
return <RemixUIGridCell
plugin={this}
title={provider.displayName}
logos={provider.logos}
classList='EECellStyle'
searchKeywords={['Saved VM States', provider.name, provider.displayName, provider.title, provider.description]}
pinned={this.pinnedProviders.includes(provider.name)}
key={provider.name}
id={provider.name}
pinStateCallback={async (pinned: boolean) => {
if (pinned) {
this.emit('providerPinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been added to the Environment list of the Deploy & Run Transactions plugin.`)
return true
}
const providerName = await this.call('blockchain', 'getProvider')
if (providerName !== provider.name) {
this.emit('providerUnpinned', provider.name, provider)
this.call('notification', 'toast', `"${provider.displayName}" has been removed from the Environment list of the Deploy & Run Transactions plugin.`)
return true
} else {
this.call('notification', 'toast', 'Cannot unpin the current selected provider')
return false
}
}}
>
<div><b>Latest Block: </b>{parseInt(latestBlock)}</div>
<CustomTooltip
placement="auto"
tooltipId="overlay-tooltip-compile"
tooltipText={`Saved at: ${(new Date(timestamp)).toLocaleString()}`}
>
<div><b>Saved at: </b>{(new Date(timestamp)).toDateString()}</div>
</CustomTooltip>
</RemixUIGridCell>
})}</RemixUIGridSection>
<RemixUIGridSection
plugin={this}
title='Deploy to an In-browser forked Virtual Machine.'

@ -131,3 +131,11 @@ export class CancunVMProvider extends BasicVMProvider {
this.fork = 'cancun'
}
}
export class SavedVMStateProvider extends BasicVMProvider {
constructor(profile, blockchain, fork) {
super(profile, blockchain)
this.blockchain = blockchain
this.fork = fork
}
}

@ -49,6 +49,9 @@
"udapp.enterAMessageToSign": "Enter a message to sign and click `Sign`",
"udapp.hash": "hash",
"udapp.signature": "signature",
"udapp.saveVmStateTitle": "Save VM state",
"udapp.saveVmStateLabel": "State Name",
"udapp.saveVmStateTip": "Saved VM states can be pinned as environment using Environment Explorer",
"udapp.injectedTitle": "Unfortunately it's not possible to create an account using injected provider. Please create the account directly from your provider (i.e metamask or other of the same type).",
"udapp.createNewAccount": "Create new account",
"udapp.web3Title": "Creating an account is possible only in Personal mode. Please go to Settings to enable it.",
@ -63,6 +66,7 @@
"udapp._comment_environment.tsx": "libs/remix-ui/run-tab/src/lib/components/environment.tsx",
"udapp.environment": "Environment",
"udapp.environmentDocs": "Click for docs about Environment",
"udapp.saveVmState": "Save VM state",
"udapp.tooltipText2": "Open chainlist.org and get the connection specs of the chain you want to interact with.",
"udapp.tooltipText3": "Click to open a bridge for converting L1 mainnet ETH to the selected network currency.",

@ -9,8 +9,7 @@ import * as packageJson from '../../../../../package.json'
import { EventManager } from '@remix-project/remix-lib'
import type { Blockchain } from '../../blockchain/blockchain'
import type { CompilerArtefacts } from '@remix-project/core-plugin'
// import type { NetworkModule } from '../tabs/network-module'
// import type FileProvider from '../files/fileProvider'
import { SavedVMStateProvider } from '../providers/vm-provider'
import { Recorder } from '../tabs/runTab/model/recorder'
const _paq = (window._paq = window._paq || [])
@ -178,7 +177,7 @@ export class RunTab extends ViewPlugin {
'foundry-provider': ['assets/img/foundry.png']
}
const addProvider = async (position, name, displayName, isInjected, isVM, fork = '', dataId = '', title = '', forkedVM = false) => {
const addProvider = async (position, name, displayName, isInjected, isVM, isSavedState, fork = '', dataId = '', title = '', forkedVM = false) => {
await this.call('blockchain', 'addProvider', {
position,
options: {},
@ -191,6 +190,7 @@ export class RunTab extends ViewPlugin {
isInjected,
isForkedVM: forkedVM,
isVM,
isSavedState,
title,
init: async function () {
const options = await udapp.call(name, 'init')
@ -206,13 +206,13 @@ export class RunTab extends ViewPlugin {
const addCustomInjectedProvider = async (position, event, name, displayName, networkId, urls, nativeCurrency?) => {
// name = `${name} through ${event.detail.info.name}`
await this.engine.register([new InjectedCustomProvider(event.detail.provider, name, displayName, networkId, urls, nativeCurrency)])
await addProvider(position, name, displayName + ' - ' + event.detail.info.name, true, false)
await addProvider(position, name, displayName + ' - ' + event.detail.info.name, true, false, false)
}
const registerInjectedProvider = async (event) => {
const name = 'injected-' + event.detail.info.name
const displayName = 'Injected Provider - ' + event.detail.info.name
await this.engine.register([new InjectedProviderDefault(event.detail.provider, name)])
await addProvider(0, name, displayName, true, false)
await addProvider(0, name, displayName, true, false, false)
if (event.detail.info.name === 'MetaMask') {
await addCustomInjectedProvider(7, event, 'injected-metamask-optimism', 'L2 - Optimism', '0xa', ['https://mainnet.optimism.io'])
@ -248,23 +248,63 @@ export class RunTab extends ViewPlugin {
// VM
const titleVM = 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.'
await addProvider(1, 'vm-cancun', 'Remix VM (Cancun)', false, true, 'cancun', 'settingsVMCancunMode', titleVM)
await addProvider(50, 'vm-shanghai', 'Remix VM (Shanghai)', false, true, 'shanghai', 'settingsVMShanghaiMode', titleVM)
await addProvider(51, 'vm-paris', 'Remix VM (Paris)', false, true, 'paris', 'settingsVMParisMode', titleVM)
await addProvider(52, 'vm-london', 'Remix VM (London)', false, true, 'london', 'settingsVMLondonMode', titleVM)
await addProvider(53, 'vm-berlin', 'Remix VM (Berlin)', false, true, 'berlin', 'settingsVMBerlinMode', titleVM)
await addProvider(2, 'vm-mainnet-fork', 'Remix VM - Mainnet fork', false, true, 'cancun', 'settingsVMMainnetMode', titleVM, true)
await addProvider(3, 'vm-sepolia-fork', 'Remix VM - Sepolia fork', false, true, 'cancun', 'settingsVMSepoliaMode', titleVM, true)
await addProvider(4, 'vm-custom-fork', 'Remix VM - Custom fork', false, true, '', 'settingsVMCustomMode', titleVM, true)
await addProvider(1, 'vm-cancun', 'Remix VM (Cancun)', false, true, false, 'cancun', 'settingsVMCancunMode', titleVM)
await addProvider(50, 'vm-shanghai', 'Remix VM (Shanghai)', false, true, false, 'shanghai', 'settingsVMShanghaiMode', titleVM)
await addProvider(51, 'vm-paris', 'Remix VM (Paris)', false, true, false, 'paris', 'settingsVMParisMode', titleVM)
await addProvider(52, 'vm-london', 'Remix VM (London)', false, true, false, 'london', 'settingsVMLondonMode', titleVM)
await addProvider(53, 'vm-berlin', 'Remix VM (Berlin)', false, true, false, 'berlin', 'settingsVMBerlinMode', titleVM)
await addProvider(2, 'vm-mainnet-fork', 'Remix VM - Mainnet fork', false, true, false, 'cancun', 'settingsVMMainnetMode', titleVM, true)
await addProvider(3, 'vm-sepolia-fork', 'Remix VM - Sepolia fork', false, true, false, 'cancun', 'settingsVMSepoliaMode', titleVM, true)
await addProvider(4, 'vm-custom-fork', 'Remix VM - Custom fork', false, true, false, '', 'settingsVMCustomMode', titleVM, true)
// Saved VM States
const addSVSProvider = async(stateFilePath, pos) => {
let stateDetail = await this.call('fileManager', 'readFile', stateFilePath)
stateDetail = JSON.parse(stateDetail)
const providerName = 'vm-svs-' + stateDetail.stateName
descriptions[providerName] = JSON.stringify({
name: providerName,
latestBlock: stateDetail.latestBlockNumber,
timestamp: stateDetail.savingTimestamp
})
// Create and register provider plugin for saved states
const svsProvider = new SavedVMStateProvider({
name: providerName,
displayName: stateDetail.stateName,
kind: 'provider',
description: descriptions[providerName],
methods: ['sendAsync', 'init'],
version: packageJson.version
}, this.blockchain, stateDetail.forkName)
this.engine.register(svsProvider)
await addProvider(pos, providerName, stateDetail.stateName, false, false, true, stateDetail.forkName)
}
this.on('filePanel', 'workspaceInitializationCompleted', async () => {
const ssExists = await this.call('fileManager', 'exists', '.states/saved_states')
if (ssExists) {
const savedStatesDetails = await this.call('fileManager', 'readdir', '.states/saved_states')
const savedStatesFiles = Object.keys(savedStatesDetails)
let pos = 10
for (const filePath of savedStatesFiles) {
pos += 1
await addSVSProvider(filePath, pos)
}
}
})
this.on('udapp', 'vmStateSaved', async (stateName) => {
await addSVSProvider(`.states/saved_states/${stateName}.json`, 20)
})
// wallet connect
await addProvider(6, 'walletconnect', 'WalletConnect', false, false)
await addProvider(6, 'walletconnect', 'WalletConnect', false, false, false)
// external provider
await addProvider(10, 'basic-http-provider', 'Custom - External Http Provider', false, false)
await addProvider(20, 'hardhat-provider', 'Dev - Hardhat Provider', false, false)
await addProvider(21, 'ganache-provider', 'Dev - Ganache Provider', false, false)
await addProvider(22, 'foundry-provider', 'Dev - Foundry Provider', false, false)
await addProvider(10, 'basic-http-provider', 'Custom - External Http Provider', false, false, false)
await addProvider(20, 'hardhat-provider', 'Dev - Hardhat Provider', false, false, false)
await addProvider(21, 'ganache-provider', 'Dev - Ganache Provider', false, false, false)
await addProvider(22, 'foundry-provider', 'Dev - Foundry Provider', false, false, false)
// register injected providers

@ -55,6 +55,7 @@ export type Provider = {
description?: string
isInjected: boolean
isVM: boolean
isSavedState: boolean
isForkedVM: boolean
title: string
init: () => Promise<void>
@ -78,7 +79,7 @@ export class Blockchain extends Plugin {
}
error?: string
}
providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider}
providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider }
transactionContextAPI: TransactionContextAPI
registeredPluginEvents: string[]
defaultPinnedProviders: string[]
@ -204,9 +205,8 @@ export class Blockchain extends Plugin {
}
setupProviders() {
const vmProvider = new VMProvider(this.executionContext)
this.providers = {}
this.providers['vm'] = vmProvider
this.providers['vm'] = new VMProvider(this.executionContext)
this.providers.injected = new InjectedProvider(this.executionContext)
this.providers.web3 = new NodeProvider(this.executionContext, this.config)
}
@ -692,13 +692,17 @@ export class Blockchain extends Plugin {
if (saveEvmState) {
const contextExists = await this.call('fileManager', 'exists', `.states/${context}/state.json`)
if (contextExists) {
const stateDb = await this.call('fileManager', 'readFile', `.states/${context}/state.json`)
await this.getCurrentProvider().resetEnvironment(stateDb)
} else {
await this.getCurrentProvider().resetEnvironment()
// check if saved VM state is used as provider
const stateName = context.replace('vm-svs-', '')
const contextExists = await this.call('fileManager', 'exists', `.states/saved_states/${stateName}.json`)
if (contextExists) {
const stateDb = await this.call('fileManager', 'readFile', `.states/saved_states/${stateName}.json`)
await this.getCurrentProvider().resetEnvironment(stateDb)
} else await this.getCurrentProvider().resetEnvironment()
}
} else {
await this.getCurrentProvider().resetEnvironment()
@ -952,8 +956,23 @@ export class Blockchain extends Plugin {
if (isVM) {
if (!tx.useCall && this.config.get('settings/save-evm-state')) {
try {
const state = await this.executionContext.getStateDetails()
this.call('fileManager', 'writeFile', `.states/${this.executionContext.getProvider()}/state.json`, state)
let state = await this.executionContext.getStateDetails()
const provider = this.executionContext.getProvider()
if (provider.startsWith('vm-svs-')) {
const stateName = provider.replace('vm-svs-', '')
const stateFileExists = this.call('fileManager', 'exists', `.states/saved_states/${stateName}.json`)
if (stateFileExists) {
let stateDetails = await this.call('fileManager', 'readFile', `.states/saved_states/${stateName}.json`)
stateDetails = JSON.parse(stateDetails)
state = JSON.parse(state)
state['stateName'] = stateDetails.stateName
state['forkName'] = stateDetails.forkName
state['savingTimestamp'] = stateDetails.savingTimestamp
state = JSON.stringify(state, null, 2)
}
this.call('fileManager', 'writeFile', `.states/saved_states/${stateName}.json`, state)
}
else this.call('fileManager', 'writeFile', `.states/${provider}/state.json`, state)
} catch (e) {
console.error(e)
}
@ -985,7 +1004,6 @@ export class Blockchain extends Plugin {
this.call('terminal', 'logHtml', finalLogs)
}
execResult = await this.web3().remix.getExecutionResultFromSimulator(txResult.transactionHash)
if (execResult) {
// if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value.
returnValue = execResult

@ -1,11 +1,12 @@
// eslint-disable-next-line no-use-before-define
import React, { useEffect } from 'react'
import { FormattedMessage } from 'react-intl'
import React, { useEffect, useRef } from 'react'
import { FormattedMessage, useIntl } from 'react-intl'
import { EnvironmentProps, Provider } from '../types'
import { Dropdown } from 'react-bootstrap'
import { CustomMenu, CustomToggle, CustomTooltip } from '@remix-ui/helper'
export function EnvironmentUI(props: EnvironmentProps) {
const vmStateName = useRef('')
Object.entries(props.providers.providerList.filter((provider) => { return provider.isVM }))
Object.entries(props.providers.providerList.filter((provider) => { return provider.isInjected }))
@ -23,6 +24,55 @@ export function EnvironmentUI(props: EnvironmentProps) {
'L2 - Arbitrum': 'https://bridge.arbitrum.io/'
}
const intl = useIntl()
const isSaveEvmStateChecked = props.config.get('settings/save-evm-state')
const saveVmStatePrompt = (defaultName: string) => {
return (
<div>
<label id="wsName" className="form-check-label" style={{ fontWeight: 'bolder' }}>
<FormattedMessage id="udapp.saveVmStateLabel" />
</label>
<input
type="text"
data-id="modalDialogSaveVmState"
defaultValue={defaultName}
className="form-control"
onChange={(e) => vmStateName.current = e.target.value}
/>
<br/>
<div className='text-secondary'>
<b>Tip: </b><FormattedMessage id="udapp.saveVmStateTip" />
</div>
</div>
)
}
const saveVmState = () => {
const context = currentProvider.name
vmStateName.current = `${context}_${Date.now()}`
props.modal(
intl.formatMessage({ id: 'udapp.saveVmStateTitle' }),
saveVmStatePrompt(vmStateName.current),
intl.formatMessage({ id: 'udapp.save' }),
async () => {
const contextExists = await props.runTabPlugin.call('fileManager', 'exists', `.states/${context}/state.json`)
if (contextExists) {
let currentStateDb = await props.runTabPlugin.call('fileManager', 'readFile', `.states/${context}/state.json`)
currentStateDb = JSON.parse(currentStateDb)
currentStateDb.stateName = vmStateName.current
currentStateDb.forkName = currentProvider.fork
currentStateDb.savingTimestamp = Date.now()
await props.runTabPlugin.call('fileManager', 'writeFile', `.states/saved_states/${vmStateName.current}.json`, JSON.stringify(currentStateDb, null, 2))
props.runTabPlugin.emit('vmStateSaved', vmStateName.current)
props.runTabPlugin.call('notification', 'toast', `VM state ${vmStateName.current} saved.`)
}
},
intl.formatMessage({ id: 'udapp.cancel' }),
null
)
}
const isL2 = (providerDisplayName: string) => providerDisplayName && (providerDisplayName.startsWith('L2 - Optimism') || providerDisplayName.startsWith('L2 - Arbitrum'))
return (
<div className="udapp_crow">
@ -38,6 +88,9 @@ export function EnvironmentUI(props: EnvironmentProps) {
<i className="udapp_infoDeployAction ml-2 fas fa-info"></i>
</a>
</CustomTooltip>
{ currentProvider && currentProvider.isVM && isSaveEvmStateChecked && <CustomTooltip placement={'auto-end'} tooltipClasses="text-wrap" tooltipId="saveVMStatetooltip" tooltipText={<FormattedMessage id="udapp.saveVmState" />}>
<i className="udapp_infoDeployAction ml-2 fas fa-save" onClick={saveVmState}></i>
</CustomTooltip> }
</label>
<div className="udapp_environment" data-id={`selected-provider-${currentProvider && currentProvider.name}`}>
<Dropdown id="selectExEnvOptions" data-id="settingsSelectEnvOptions" className="udapp_selectExEnvOptions">

@ -12,7 +12,15 @@ export function SettingsUI(props: SettingsProps) {
return (
<div className="udapp_settings">
<EnvironmentUI runTabPlugin={props.runTabPlugin} selectedEnv={props.selectExEnv} providers={props.providers} setExecutionContext={props.setExecutionContext} checkSelectionCorrectness={props.EvaluateEnvironmentSelection} />
<EnvironmentUI
runTabPlugin={props.runTabPlugin}
selectedEnv={props.selectExEnv}
providers={props.providers}
setExecutionContext={props.setExecutionContext}
checkSelectionCorrectness={props.EvaluateEnvironmentSelection}
modal={props.modal}
config={props.runTabPlugin.config}
/>
<NetworkUI networkName={props.networkName} />
<AccountUI
addFile={props.addFile}

@ -171,6 +171,8 @@ export interface EnvironmentProps {
error: string
},
setExecutionContext: (executionContext: { context: string }) => void
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void, okBtnClass?: string, cancelBtnClass?: string) => void,
config: any
}
export interface NetworkProps {

@ -152,7 +152,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {
@ -707,4 +707,4 @@ contract PlonkVerifier {
}
}
}
}

@ -152,7 +152,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {
@ -707,4 +707,4 @@ contract PlonkVerifier {
}
}
}
}

@ -152,7 +152,7 @@ contract PlonkVerifier {
///////
// Computes the inverse of an array of values
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
// See https://vitalik.eth.limo/general/2018/07/21/starks_part_3.html in section where explain fields operations
//////
function inverseArray(pVals, n) {
@ -707,4 +707,4 @@ contract PlonkVerifier {
}
}
}
}

Loading…
Cancel
Save