Skip to content

Commit

Permalink
Merge branch 'pastedCodeSafety' of https://github.com/ethereum/remix-…
Browse files Browse the repository at this point in the history
…project into pastedCodeSafety
  • Loading branch information
STetsing committed Dec 18, 2024
2 parents 7693972 + 47305f7 commit 6b0bec0
Show file tree
Hide file tree
Showing 13 changed files with 222 additions and 39 deletions.
2 changes: 1 addition & 1 deletion apps/circuit-compiler/src/app/actions/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions apps/remix-dapp/src/locales/en/udapp.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand All @@ -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.",

Expand Down
50 changes: 48 additions & 2 deletions apps/remix-ide/src/app/providers/environment-explorer.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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[] }
Expand All @@ -39,6 +39,7 @@ export class EnvironmentExplorer extends ViewPlugin {
this.providers = {
'Injected': [],
'Remix VMs': [],
'Saved VM States': [],
'Remix forked VMs': [],
'Externals': []
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -84,6 +87,7 @@ export class EnvironmentExplorer extends ViewPlugin {
this.providers = {
'Injected': [],
'Remix VMs': [],
'Saved VM States': [],
'Externals': [],
'Remix forked VMs': []
}
Expand Down Expand Up @@ -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.'
Expand Down
8 changes: 8 additions & 0 deletions apps/remix-ide/src/app/providers/vm-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
4 changes: 4 additions & 0 deletions apps/remix-ide/src/app/tabs/locales/en/udapp.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand All @@ -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.",

Expand Down
76 changes: 58 additions & 18 deletions apps/remix-ide/src/app/udapp/run-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 || [])

Expand Down Expand Up @@ -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: {},
Expand All @@ -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')
Expand All @@ -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'])
Expand Down Expand Up @@ -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

Expand Down
36 changes: 27 additions & 9 deletions apps/remix-ide/src/blockchain/blockchain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export type Provider = {
description?: string
isInjected: boolean
isVM: boolean
isSavedState: boolean
isForkedVM: boolean
title: string
init: () => Promise<void>
Expand All @@ -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[]
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 6b0bec0

Please sign in to comment.