mainnet vm fork

pull/3358/head
yann300 2 years ago committed by Aniket
parent 29707ba717
commit 0a55308830
  1. 3
      apps/remix-ide/src/app.js
  2. 17
      apps/remix-ide/src/app/providers/abstract-provider.tsx
  3. 1
      apps/remix-ide/src/app/providers/injected-L2-provider.tsx
  4. 12
      apps/remix-ide/src/app/providers/injected-provider.tsx
  5. 29
      apps/remix-ide/src/app/providers/vm-fork-provider.tsx
  6. 13
      apps/remix-ide/src/app/providers/vm-provider.tsx
  7. 8
      apps/remix-ide/src/app/udapp/run-tab.js
  8. 4
      apps/remix-ide/src/blockchain/blockchain.js
  9. 4
      apps/remix-ide/src/blockchain/execution-context.js
  10. 4
      apps/remix-ide/src/blockchain/providers/vm.js
  11. 2
      apps/remix-ide/src/blockchain/providers/worker-vm.ts
  12. 6
      libs/remix-simulator/src/provider.ts
  13. 28
      libs/remix-simulator/src/vm-context.ts
  14. 4
      yarn.lock

@ -28,6 +28,7 @@ import { Layout } from './app/panels/layout'
import { NotificationPlugin } from './app/plugins/notification'
import { Blockchain } from './blockchain/blockchain.js'
import { BerlinVMProvider, LondonVMProvider } from './app/providers/vm-provider'
import { MainnetForkVMProvider } from './app/providers/vm-fork-provider'
import { HardhatProvider } from './app/providers/hardhat-provider'
import { GanacheProvider } from './app/providers/ganache-provider'
import { FoundryProvider } from './app/providers/foundry-provider'
@ -203,6 +204,7 @@ class AppComponent {
const networkModule = new NetworkModule(blockchain)
// ----------------- represent the current selected web3 provider ----
const web3Provider = new Web3ProviderModule(blockchain)
const vmProviderMainnetFork = new MainnetForkVMProvider(blockchain)
const vmProviderBerlin = new BerlinVMProvider(blockchain)
const vmProviderLondon = new LondonVMProvider(blockchain)
const hardhatProvider = new HardhatProvider(blockchain)
@ -273,6 +275,7 @@ class AppComponent {
storagePlugin,
vmProviderBerlin,
vmProviderLondon,
vmProviderMainnetFork,
hardhatProvider,
ganacheProvider,
foundryProvider,

@ -19,12 +19,20 @@ export type JsonDataResult = {
export type RejectRequest = (error: Error) => void
export type SuccessRequest = (data: JsonDataResult) => void
export abstract class AbstractProvider extends Plugin {
export interface IProvider {
options: { [id: string] : any }
init(): Promise<{ [id: string] : any }>
body(): JSX.Element
sendAsync (data: JsonDataRequest): Promise<JsonDataResult>
}
export abstract class AbstractProvider extends Plugin implements IProvider {
provider: ethers.providers.JsonRpcProvider
blockchain: Blockchain
defaultUrl: string
connected: boolean
nodeUrl: string
options: { [id: string] : any } = {}
constructor (profile, blockchain, defaultUrl) {
super(profile)
@ -41,7 +49,7 @@ export abstract class AbstractProvider extends Plugin {
this.provider = null
}
async init () {
async init () {
this.nodeUrl = await ((): Promise<string> => {
return new Promise((resolve, reject) => {
const modalContent: AppModal = {
@ -80,9 +88,12 @@ export abstract class AbstractProvider extends Plugin {
})
})()
this.provider = new ethers.providers.JsonRpcProvider(this.nodeUrl)
return {
nodeUrl: this.nodeUrl
}
}
sendAsync (data: JsonDataRequest): Promise<any> {
sendAsync (data: JsonDataRequest): Promise<JsonDataResult> {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
if (!this.provider) return reject(new Error('provider node set'))

@ -17,6 +17,7 @@ export class InjectedL2Provider extends InjectedProvider {
if (this.chainName && this.rpcUrls && this.rpcUrls.length > 0) await addL2Network(this.chainName, this.chainId, this.rpcUrls)
else
throw new Error('Cannot add the L2 network to main injected provider')
return {}
}
}

@ -1,12 +1,15 @@
/* global ethereum */
import React from 'react' // eslint-disable-line
import { Plugin } from '@remixproject/engine'
import { JsonDataRequest, RejectRequest, SuccessRequest } from '../providers/abstract-provider'
import Web3 from 'web3'
import { IProvider } from './abstract-provider'
const noInjectedProviderMsg = 'No injected provider found. Make sure your provider (e.g. MetaMask) is active and running (when recently activated you may have to reload the page).'
export class InjectedProvider extends Plugin {
export class InjectedProvider extends Plugin implements IProvider {
provider: any
options: { [id: string] : any } = {}
constructor (profile) {
super(profile)
@ -23,6 +26,12 @@ export class InjectedProvider extends Plugin {
}
}
body (): JSX.Element {
return (
<div></div>
)
}
async init () {
const injectedProvider = (window as any).ethereum
if (injectedProvider === undefined) {
@ -33,6 +42,7 @@ export class InjectedProvider extends Plugin {
}
this.askPermission(true)
}
return {}
}
sendAsync (data: JsonDataRequest): Promise<any> {

@ -0,0 +1,29 @@
import * as packageJson from '../../../../../package.json'
import { BasicVMProvider } from './vm-provider'
export class MainnetForkVMProvider extends BasicVMProvider {
nodeUrl: string
blockNumber: number | 'latest'
constructor (blockchain) {
super({
name: 'vm-mainnet-fork',
displayName: 'Mainet fork -Remix VM (London)',
kind: 'provider',
description: 'Remix VM (London)',
methods: ['sendAsync', 'init'],
version: packageJson.version
}, blockchain)
this.blockchain = blockchain
this.fork = 'london'
this.nodeUrl = 'https://rpc.archivenode.io/e50zmkroshle2e2e50zm0044i7ao04ym'
this.blockNumber = 'latest'
}
async init () {
return {
'fork': this.fork,
'nodeUrl': this.nodeUrl,
'blockNumber': this.blockNumber
}
}
}

@ -1,17 +1,26 @@
import React from 'react' // eslint-disable-line
import * as packageJson from '../../../../../package.json'
import { JsonDataRequest, RejectRequest, SuccessRequest } from '../providers/abstract-provider'
import { Plugin } from '@remixproject/engine'
import { IProvider } from './abstract-provider'
export class BasicVMProvider extends Plugin {
export class BasicVMProvider extends Plugin implements IProvider {
blockchain
fork: string
options: { [id: string] : any } = {}
constructor (profile, blockchain) {
super(profile)
this.blockchain = blockchain
this.fork = null
}
init () {}
async init (): Promise<{ [id: string] : any }> { return {} }
body (): JSX.Element {
return (
<div></div>
)
}
sendAsync (data: JsonDataRequest): Promise<any> {
return new Promise((resolve, reject) => {

@ -101,8 +101,10 @@ export class RunTab extends ViewPlugin {
async onInitDone () {
const udapp = this // eslint-disable-line
const self = this
const addProvider = async (name, displayName, isInjected, isVM, fork = '', dataId = '', title = '') => {
await this.call('blockchain', 'addProvider', {
options: {},
dataId,
name,
displayName,
@ -110,7 +112,10 @@ export class RunTab extends ViewPlugin {
isInjected,
isVM,
title,
init: () => { return this.call(name, 'init') },
init: async function () {
const options = await self.call(name, 'init')
if (options) { this.options = options }
},
provider: {
async sendAsync (payload, callback) {
try {
@ -128,6 +133,7 @@ export class RunTab extends ViewPlugin {
const titleVM = 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.'
await addProvider('vm-london', 'Remix VM (London)', false, true, 'london', 'settingsVMLondonMode', titleVM)
await addProvider('vm-berlin', 'Remix VM (Berlin)', false, true, 'berlin', 'settingsVMBerlinMode', titleVM)
await addProvider('vm-mainnet-fork', 'Remix VM - Mainnet fork', false, true, 'london', 'settingsVMMainnetMode', titleVM)
// external provider
await addProvider('hardhat-provider', 'Hardhat Provider', false, false)

@ -84,8 +84,6 @@ export class Blockchain extends Plugin {
setupProviders () {
const vmProvider = new VMProvider(this.executionContext)
this.providers = {}
this.providers['vm-berlin'] = vmProvider
this.providers['vm-london'] = vmProvider
this.providers['vm'] = vmProvider
this.providers.injected = new InjectedProvider(this.executionContext)
this.providers.web3 = new NodeProvider(this.executionContext, this.config)
@ -93,7 +91,7 @@ export class Blockchain extends Plugin {
getCurrentProvider () {
const provider = this.getProvider()
if (provider && provider.startsWith('vm')) return this.providers['vm']
if (this.providers[provider]) return this.providers[provider]
return this.providers.web3 // default to the common type of provider
}

@ -43,6 +43,10 @@ export class ExecutionContext {
return this.executionContext
}
getProviderObject () {
return this.customNetWorks[this.executionContext]
}
getSelectedAddress () {
return injectedProvider ? injectedProvider.selectedAddress : null
}

@ -22,7 +22,9 @@ class VMProvider {
if (this.worker) this.worker.terminate()
this.accounts = {}
this.worker = new Worker(new URL('./worker-vm', import.meta.url))
this.worker.postMessage({ cmd: 'init', fork: this.executionContext.getCurrentFork() })
const provider = this.executionContext.getProviderObject()
this.worker.postMessage({ cmd: 'init', fork: this.executionContext.getCurrentFork(), nodeUrl: provider?.options['nodeUrl'], blockNumber: provider?.options['blockNumber']})
let incr = 0
const stamps = {}

@ -6,7 +6,7 @@ self.onmessage = (e: MessageEvent) => {
switch (data.cmd) {
case 'init':
{
provider = new Provider({ fork: data.fork })
provider = new Provider({ fork: data.fork, nodeUrl: data.nodeUrl, blockNumber: data.blockNumber })
if (provider) provider.init()
break
}

@ -13,17 +13,17 @@ import { generateBlock } from './genesis'
import { VMContext } from './vm-context'
export class Provider {
options: Record<string, unknown>
options: Record<string, string | number>
vmContext
Accounts
Transactions
methods
connected: boolean;
constructor (options: Record<string, unknown> = {}) {
constructor (options: Record<string, string | number> = {}) {
this.options = options
this.connected = true
this.vmContext = new VMContext(options['fork'])
this.vmContext = new VMContext(options['fork'] as string, options['nodeUrl'] as string, options['blockNumber'] as number)
this.Accounts = new Web3Accounts(this.vmContext)
this.Transactions = new Transactions(this.vmContext)

@ -3,13 +3,14 @@
import { hash } from '@remix-project/remix-lib'
import { bufferToHex } from '@ethereumjs/util'
import { decode } from 'rlp'
import { ethers } from 'ethers'
import { execution } from '@remix-project/remix-lib'
const { LogsManager } = execution
import { VmProxy } from './VmProxy'
import { VM } from '@ethereumjs/vm'
import { Common } from '@ethereumjs/common'
import { Trie } from '@ethereumjs/trie'
import { DefaultStateManager } from '@ethereumjs/statemanager'
import { DefaultStateManager, StateManager, EthersStateManager } from '@ethereumjs/statemanager'
import { StorageDump } from '@ethereumjs/statemanager/dist/interface'
import { EVM } from '@ethereumjs/evm'
import { EEI } from '@ethereumjs/vm'
@ -86,7 +87,7 @@ class StateManagerCommonStorageDump extends DefaultStateManager {
export type CurrentVm = {
vm: VM,
web3vm: VmProxy,
stateManager: StateManagerCommonStorageDump,
stateManager: StateManager,
common: Common
}
@ -105,12 +106,15 @@ export class VMContext {
web3vm: VmProxy
logsManager: any // LogsManager
exeResults: Record<string, Transaction>
nodeUrl: string
blockNumber: number | 'latest'
constructor (fork?) {
constructor (fork?: string, nodeUrl?: string, blockNumber?: number | 'latest') {
this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault
this.currentFork = fork || 'london'
this.nodeUrl = nodeUrl
this.blockNumber = blockNumber
this.blocks = {}
this.latestBlockNumber = "0x0"
this.blockByTxHash = {}
@ -124,7 +128,21 @@ export class VMContext {
}
async createVm (hardfork) {
const stateManager = new StateManagerCommonStorageDump()
let stateManager: StateManager
if (this.nodeUrl) {
let block = this.blockNumber
if (this.blockNumber === 'latest') {
const provider = new ethers.providers.StaticJsonRpcProvider(this.nodeUrl)
block = await provider.getBlockNumber()
}
stateManager = new EthersStateManager({
provider: this.nodeUrl,
blockTag: BigInt(block)
})
} else
stateManager = new StateManagerCommonStorageDump()
const common = new Common({ chain: 'mainnet', hardfork })
const blockchain = new (Blockchain as any)({ common })
const eei = new EEI(stateManager, common, blockchain)

@ -2883,7 +2883,7 @@
bech32 "1.1.4"
ws "7.4.6"
"@ethersproject/providers@5.7.2":
"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.1":
version "5.7.2"
resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb"
integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==
@ -12293,7 +12293,7 @@ ethers@^5.4.2:
"@ethersproject/web" "5.5.0"
"@ethersproject/wordlists" "5.5.0"
ethers@^5.7.2:
ethers@^5.7.1, ethers@^5.7.2:
version "5.7.2"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==

Loading…
Cancel
Save