diff --git a/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts index e84ab52367..56616f1ac9 100644 --- a/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts +++ b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts @@ -12,6 +12,7 @@ class GoToVmTraceStep extends EventEmitter { function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number, done: VoidFunction) { browser.execute(function (step) { (document.getElementById('slider') as HTMLInputElement).value = (step - 1).toString() }, [step]) .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) + .pause(1000) .perform(() => { done() }) diff --git a/apps/remix-ide-e2e/src/tests/debugger.test.ts b/apps/remix-ide-e2e/src/tests/debugger.test.ts index cd3fafc3b3..56a1174521 100644 --- a/apps/remix-ide-e2e/src/tests/debugger.test.ts +++ b/apps/remix-ide-e2e/src/tests/debugger.test.ts @@ -39,12 +39,9 @@ module.exports = { 'Should debug transaction using slider #group1': function (browser: NightwatchBrowser) { browser.waitForElementVisible('*[data-id="verticalIconsKindudapp"]') .waitForElementVisible('*[data-id="slider"]') - // eslint-disable-next-line dot-notation - .execute(function () { document.getElementById('slider')['value'] = '50' }) // It only moves slider to 50 but vm traces are not updated - .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) - .pause(2000) - .click('*[data-id="dropdownPanelSolidityLocals"]') - .waitForElementContainsText('*[data-id="solidityLocals"]', 'no locals', 60000) + .goToVMTraceStep(51) + .waitForElementContainsText('*[data-id="solidityLocals"]', 'toast', 60000) + .waitForElementContainsText('*[data-id="solidityLocals"]', '999', 60000) .waitForElementContainsText('*[data-id="stepdetail"]', 'vm trace step:\n51', 60000) }, @@ -159,10 +156,7 @@ module.exports = { .pause(2000) .debugTransaction(0) .waitForElementVisible('*[data-id="slider"]').pause(2000) - // .setValue('*[data-id="slider"]', '5000') // Like this, setValue doesn't work properly for input type = range - // eslint-disable-next-line dot-notation - .execute(function () { document.getElementById('slider')['value'] = '7450' }).pause(10000) // It only moves slider to 7450 but vm traces are not updated - .setValue('*[data-id="slider"]', new Array(3).fill(browser.Keys.RIGHT_ARROW)) // This will press NEXT 3 times and will update the trace details + .goToVMTraceStep(7453) .waitForElementPresent('*[data-id="treeViewDivtreeViewItemarray"]') .click('*[data-id="treeViewDivtreeViewItemarray"]') .waitForElementPresent('*[data-id="treeViewDivtreeViewLoadMore"]') @@ -210,15 +204,7 @@ module.exports = { .pause(3000) .clickLaunchIcon('debugger') .waitForElementVisible('*[data-id="slider"]') - // eslint-disable-next-line dot-notation - .execute(function () { document.getElementById('slider')['value'] = '153' }) // It only moves slider to 153 but vm traces are not updated - .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) - .pause(1000) - /* - setting the slider to 5 leads to "vm trace step: 91" for chrome and "vm trace step: 92" for firefox - => There is something going wrong with the nightwatch API here. - As we are only testing if debugger is active, this is ok to keep that for now. - */ + .goToVMTraceStep(154) .waitForElementContainsText('*[data-id="stepdetail"]', 'vm trace step:\n154', 60000) }, @@ -241,8 +227,23 @@ module.exports = { .waitForElementVisible('*[data-id="solidityLocals"]', 60000) .pause(10000) .checkVariableDebug('soliditylocals', { num: { value: '2', type: 'uint256' } }) - .checkVariableDebug('soliditystate', { number: { value: '0', type: 'uint256', constant: false, immutable: false } }) - .end() + .checkVariableDebug('soliditystate', { number: { value: '0', type: 'uint256', constant: false, immutable: false } }) + }, + + 'Should debug reverted transactions #group5': function (browser: NightwatchBrowser) { + browser + .testContracts('reverted.sol', sources[6]['reverted.sol'], ['A', 'B', 'C']) + .clickLaunchIcon('udapp') + .selectContract('A') + .createContract('') + .pause(500) + .clickInstance(0) + .clickFunction('callA - transact (not payable)') + .debugTransaction(1) + .goToVMTraceStep(79) + .waitForElementVisible('*[data-id="debugGoToRevert"]', 60000) + .click('*[data-id="debugGoToRevert"]') + .waitForElementContainsText('*[data-id="asmitems"] div[selected="selected"]', '117 REVERT') } } @@ -366,6 +367,46 @@ const sources = [ } ` } + }, + { + 'reverted.sol': { + content: `contract A { + B b; + uint p; + constructor () { + b = new B(); + } + function callA() public { + p = 123; + try b.callB() { + + } + catch (bytes memory reason) { + + } + } + } + + contract B { + C c; + uint p; + constructor () { + c = new C(); + } + function callB() public { + p = 124; + revert("revert!"); + c.callC(); + } + } + + contract C { + uint p; + function callC() public { + p = 125; + } + }` + } } ] diff --git a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts index 30d1a2c83c..bc1bb12cd7 100644 --- a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts +++ b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts @@ -283,9 +283,7 @@ module.exports = { .waitForElementVisible('*[data-id="dropdownPanelSolidityLocals"]').pause(1000) .click('*[data-id="dropdownPanelSolidityLocals"]') .waitForElementContainsText('*[data-id="solidityLocals"]', 'no locals', 60000) - // eslint-disable-next-line dot-notation - .execute(function () { document.getElementById('slider')['value'] = '315' }) // It only moves slider to 315 but vm traces are not updated - .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) + .goToVMTraceStep(316) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalFailed()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'vote(proposal)', 60000) .pause(5000) @@ -295,9 +293,7 @@ module.exports = { .scrollAndClick('#Check_winning_proposal_passed') .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalPassed()', 60000) - // eslint-disable-next-line dot-notation - .execute(function () { document.getElementById('slider')['value'] = '1450' }) - .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) + .goToVMTraceStep(1451) .waitForElementContainsText('*[data-id="functionPanel"]', 'equal(a, b, message)', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalPassed()', 60000) // remix_test.sol should be opened in editor @@ -307,9 +303,7 @@ module.exports = { .scrollAndClick('#Check_winning_proposal_again') .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000) - // eslint-disable-next-line dot-notation - .execute(function () { document.getElementById('slider')['value'] = '1150' }) - .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) + .goToVMTraceStep(1151) .waitForElementContainsText('*[data-id="functionPanel"]', 'equal(a, b, message)', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000) .pause(5000) @@ -317,9 +311,7 @@ module.exports = { .scrollAndClick('#Check_winnin_proposal_with_return_value').pause(5000) .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinninProposalWithReturnValue()', 60000) - // eslint-disable-next-line dot-notation - .execute(function () { document.getElementById('slider')['value'] = '320' }) - .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) + .goToVMTraceStep(321) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinninProposalWithReturnValue()', 60000) .clickLaunchIcon('filePanel') .pause(2000) diff --git a/apps/remix-ide/src/remixEngine.js b/apps/remix-ide/src/remixEngine.js index cbdf6c86c6..63e94d8669 100644 --- a/apps/remix-ide/src/remixEngine.js +++ b/apps/remix-ide/src/remixEngine.js @@ -15,6 +15,8 @@ export class RemixEngine extends Engine { if (name === 'hardhat') return { queueTimeout: 60000 * 4 } if (name === 'localPlugin') return { queueTimeout: 60000 * 4 } if (name === 'notification') return { queueTimeout: 60000 * 4 } + if (name === 'sourcify') return { queueTimeout: 60000 * 4 } + if (name === 'fetchAndCompile') return { queueTimeout: 60000 * 4 } return { queueTimeout: 10000 } } diff --git a/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts b/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts index 63a7880382..c6a8a6156b 100644 --- a/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts +++ b/libs/remix-core-plugin/src/lib/compiler-fetch-and-compile.ts @@ -108,7 +108,7 @@ export class FetchAndCompile extends Plugin { language: data.metadata.language, evmVersion: data.metadata.settings.evmVersion, optimize: data.metadata.settings.optimizer.enabled, - runs: data.metadata.settings.runs + runs: data.metadata.settings.optimizer.runs } try { setTimeout(_ => this.emit('compiling', settings), 0) diff --git a/libs/remix-debug/src/Ethdebugger.ts b/libs/remix-debug/src/Ethdebugger.ts index 0026c97ee9..e0f1a92ab5 100644 --- a/libs/remix-debug/src/Ethdebugger.ts +++ b/libs/remix-debug/src/Ethdebugger.ts @@ -11,7 +11,6 @@ import { SolidityProxy, stateDecoder, localDecoder, InternalCallTree } from './s /** * Ethdebugger is a wrapper around a few classes that helps debugging a transaction * - * - Web3Providers - define which environment (web3) the transaction will be retrieved from * - TraceManager - Load / Analyze the trace and retrieve details of specific test * - CodeManager - Retrieve loaded byte code and help to resolve AST item from vmtrace index * - SolidityProxy - Basically used to extract state variable from AST diff --git a/libs/remix-debug/src/debugger/debugger.ts b/libs/remix-debug/src/debugger/debugger.ts index 231c2d57f2..b77963d302 100644 --- a/libs/remix-debug/src/debugger/debugger.ts +++ b/libs/remix-debug/src/debugger/debugger.ts @@ -68,7 +68,10 @@ export class Debugger { try { const address = this.debugger.traceManager.getCurrentCalledAddressAt(index) const compilationResultForAddress = await this.compilationResult(address) - if (!compilationResultForAddress) return + if (!compilationResultForAddress) { + this.event.trigger('newSourceLocation', [null]) + return + } this.debugger.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, index, compilationResultForAddress.data.contracts).then(async (rawLocation) => { if (compilationResultForAddress && compilationResultForAddress.data) { @@ -91,6 +94,7 @@ export class Debugger { }) // }) } catch (error) { + this.event.trigger('newSourceLocation', [null]) return console.log(error) } } diff --git a/libs/remix-debug/src/debugger/stepManager.ts b/libs/remix-debug/src/debugger/stepManager.ts index 1a64977e97..6fd2e5fa22 100644 --- a/libs/remix-debug/src/debugger/stepManager.ts +++ b/libs/remix-debug/src/debugger/stepManager.ts @@ -51,15 +51,18 @@ export class DebuggerStepManager { this.traceManager.buildCallPath(index).then((callsPath) => { this.currentCall = callsPath[callsPath.length - 1] if (this.currentCall.reverted) { - const revertedReason = this.currentCall.outofgas ? 'outofgas' : '' + const revertedReason = this.currentCall.outofgas ? 'outofgas' : 'reverted' this.revertionPoint = this.currentCall.return - return this.event.trigger('revertWarning', [revertedReason]) + this.event.trigger('revertWarning', [revertedReason]) + return } for (let k = callsPath.length - 2; k >= 0; k--) { const parent = callsPath[k] - if (!parent.reverted) continue - this.revertionPoint = parent.return - this.event.trigger('revertWarning', ['parenthasthrown']) + if (parent.reverted) { + this.revertionPoint = parent.return + this.event.trigger('revertWarning', ['parenthasthrown']) + return + } } this.event.trigger('revertWarning', ['']) }).catch((error) => { diff --git a/libs/remix-debug/src/storage/storageResolver.ts b/libs/remix-debug/src/storage/storageResolver.ts index 62a9f7df32..c5522f37f9 100644 --- a/libs/remix-debug/src/storage/storageResolver.ts +++ b/libs/remix-debug/src/storage/storageResolver.ts @@ -133,7 +133,7 @@ export class StorageResolver { resolve([{}, null]) } else { this.web3.debug.storageRangeAt( - tx.blockHash, tx.hash, + tx.blockHash, tx.transactionIndex, address, start, maxSize, diff --git a/libs/remix-lib/README.md b/libs/remix-lib/README.md index 35be57053c..31075ad154 100644 --- a/libs/remix-lib/README.md +++ b/libs/remix-lib/README.md @@ -23,11 +23,6 @@ ui: uiHelper, compiler: compilerHelper }, - vm: { - Web3Providers: Web3Providers, - DummyProvider: DummyProvider, - Web3VMProvider: Web3VmProvider - }, Storage: Storage, util: util, execution: { diff --git a/libs/remix-lib/src/index.ts b/libs/remix-lib/src/index.ts index 54646e326e..1f2cdb6676 100644 --- a/libs/remix-lib/src/index.ts +++ b/libs/remix-lib/src/index.ts @@ -2,9 +2,6 @@ import { EventManager } from './eventManager' import * as uiHelper from './helpers/uiHelper' import * as compilerHelper from './helpers/compilerHelper' import * as util from './util' -import { Web3Providers } from './web3Provider/web3Providers' -import { DummyProvider } from './web3Provider/dummyProvider' -import { Web3VmProvider } from './web3Provider/web3VmProvider' import { Storage } from './storage' import { EventsDecoder } from './execution/eventsDecoder' import * as txExecution from './execution/txExecution' @@ -18,6 +15,7 @@ import * as typeConversion from './execution/typeConversion' import { TxRunnerVM } from './execution/txRunnerVM' import { TxRunnerWeb3 } from './execution/txRunnerWeb3' import * as txResultHelper from './helpers/txResultHelper' +export { ConsoleLogs } from './helpers/hhconsoleSigs' export { ICompilerApi, ConfigurationSettings } from './types/ICompilerApi' export { QueryParams } from './query-params' @@ -26,11 +24,6 @@ const helpers = { compiler: compilerHelper, txResultHelper } -const vm = { - Web3Providers: Web3Providers, - DummyProvider: DummyProvider, - Web3VMProvider: Web3VmProvider -} const execution = { EventsDecoder: EventsDecoder, txExecution: txExecution, @@ -44,4 +37,4 @@ const execution = { LogsManager, forkAt } -export { EventManager, helpers, vm, Storage, util, execution } +export { EventManager, helpers, Storage, util, execution } diff --git a/libs/remix-lib/src/web3Provider/dummyProvider.ts b/libs/remix-lib/src/web3Provider/dummyProvider.ts deleted file mode 100644 index c6e4ec8d82..0000000000 --- a/libs/remix-lib/src/web3Provider/dummyProvider.ts +++ /dev/null @@ -1,55 +0,0 @@ -export class DummyProvider { - eth - debug - providers - currentProvider - - constructor () { - this.eth = {} - this.debug = {} - this.eth.getCode = (address, cb) => { return this.getCode(address, cb) } - this.eth.getTransaction = (hash, cb) => { return this.getTransaction(hash, cb) } - this.eth.getTransactionFromBlock = (blockNumber, txIndex, cb) => { return this.getTransactionFromBlock(blockNumber, txIndex, cb) } - this.eth.getBlockNumber = (cb) => { return this.getBlockNumber(cb) } - this.debug.traceTransaction = (hash, options, cb) => { return this.traceTransaction(hash, options, cb) } - this.debug.storageRangeAt = (blockNumber, txIndex, address, start, end, maxLength, cb) => { return this.storageRangeAt(blockNumber, txIndex, address, start, end, maxLength, cb) } - this.providers = { HttpProvider: function (url) {} } - this.currentProvider = { host: '' } - } - - getCode (address, cb) { - cb(null, '') - } - - setProvider (provider) {} - - traceTransaction (txHash, options, cb) { - if (cb) { - cb(null, {}) - } - return {} - } - - storageRangeAt (blockNumber, txIndex, address, start, end, maxLength, cb) { - if (cb) { - cb(null, {}) - } - return {} - } - - getBlockNumber (cb) { cb(null, '') } - - getTransaction (txHash, cb) { - if (cb) { - cb(null, {}) - } - return {} - } - - getTransactionFromBlock (blockNumber, txIndex, cb) { - if (cb) { - cb(null, {}) - } - return {} - } -} diff --git a/libs/remix-lib/src/web3Provider/web3Providers.ts b/libs/remix-lib/src/web3Provider/web3Providers.ts deleted file mode 100644 index dc68edb434..0000000000 --- a/libs/remix-lib/src/web3Provider/web3Providers.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Web3VmProvider } from './web3VmProvider' -import { loadWeb3, extendWeb3 } from '../init' - -export class Web3Providers { - modes - constructor () { - this.modes = {} - } - - addProvider (type, obj) { - if (type === 'INTERNAL') { - const web3 = loadWeb3() - this.addWeb3(type, web3) - } else if (type === 'vm') { - this.addVM(type, obj) - } else { - extendWeb3(obj) - this.addWeb3(type, obj) - } - } - - get (type, cb) { - if (this.modes[type]) { - return cb(null, this.modes[type]) - } - cb('error: this provider has not been setup (' + type + ')', null) - } - - addWeb3 (type, web3) { - this.modes[type] = web3 - } - - addVM (type, vm) { - const vmProvider = new Web3VmProvider() - vmProvider.setVM(vm) - this.modes[type] = vmProvider - } -} diff --git a/libs/remix-lib/src/web3Provider/web3VmProvider.ts b/libs/remix-simulator/src/VmProxy.ts similarity index 89% rename from libs/remix-lib/src/web3Provider/web3VmProvider.ts rename to libs/remix-simulator/src/VmProxy.ts index ecc006da9e..f7090d8b1d 100644 --- a/libs/remix-lib/src/web3Provider/web3VmProvider.ts +++ b/libs/remix-simulator/src/VmProxy.ts @@ -1,12 +1,16 @@ -import { hexListFromBNs, formatMemory } from '../util' -import { normalizeHexAddress } from '../helpers/uiHelper' -import { ConsoleLogs } from '../helpers/hhconsoleSigs' +import { util } from '@remix-project/remix-lib' +const { hexListFromBNs, formatMemory } = util +import { helpers } from '@remix-project/remix-lib' +const { normalizeHexAddress } = helpers.ui +import { ConsoleLogs } from '@remix-project/remix-lib' import { toChecksumAddress, BN, bufferToHex, Address } from 'ethereumjs-util' import Web3 from 'web3' import { ethers } from 'ethers' +import { VMContext } from './vm-context' -export class Web3VmProvider { - web3 +export class VmProxy { + vmContext: VMContext + web3: Web3 vm vmTraces txs @@ -38,7 +42,8 @@ export class Web3VmProvider { blocks latestBlockNumber - constructor () { + constructor (vmContext: VMContext) { + this.vmContext = vmContext this.web3 = new Web3() this.vm = null this.vmTraces = {} @@ -66,15 +71,15 @@ export class Web3VmProvider { this.lastProcessedStorageTxHash = {} this.sha3Preimages = {} // util - this.sha3 = (...args) => this.web3.utils.sha3(...args) - this.toHex = (...args) => this.web3.utils.toHex(...args) - this.toAscii = (...args) => this.web3.utils.hexToAscii(...args) - this.fromAscii = (...args) => this.web3.utils.asciiToHex(...args) - this.fromDecimal = (...args) => this.web3.utils.numberToHex(...args) - this.fromWei = (...args) => this.web3.utils.fromWei(...args) - this.toWei = (...args) => this.web3.utils.toWei(...args) - this.toBigNumber = (...args) => this.web3.utils.toBN(...args) - this.isAddress = (...args) => this.web3.utils.isAddress(...args) + this.sha3 = (...args) => this.web3.utils.sha3.apply(this, args) + this.toHex = (...args) => this.web3.utils.toHex.apply(this, args) + this.toAscii = (...args) => this.web3.utils.toAscii.apply(this, args) + this.fromAscii = (...args) => this.web3.utils.fromAscii.apply(this, args) + this.fromDecimal = (...args) => this.web3.utils.fromDecimal.apply(this, args) + this.fromWei = (...args) => this.web3.utils.fromWei.apply(this, args) + this.toWei = (...args) => this.web3.utils.toWei.apply(this, args) + this.toBigNumber = (...args) => this.web3.utils.toBN.apply(this, args) + this.isAddress = (...args) => this.web3.utils.isAddress.apply(this, args) this.utils = Web3.utils || [] this.txsMapBlock = {} this.blocks = {} @@ -289,16 +294,22 @@ export class Web3VmProvider { } } - storageRangeAt (blockNumber, txIndex, address, start, maxLength, cb) { // txIndex is the hash in the case of the VM + storageRangeAt (blockNumber, txIndex, address, start, maxLength, cb) { // we don't use the range params here address = toChecksumAddress(address) + let txHash if (txIndex === 'latest') { - txIndex = this.lastProcessedStorageTxHash[address] + txHash = this.lastProcessedStorageTxHash[address] + } else { + const block = this.vmContext.blocks[blockNumber] + txHash = '0x' + block.transactions[txIndex].hash().toString('hex') } + + - if (this.storageCache[txIndex] && this.storageCache[txIndex][address]) { - const storage = this.storageCache[txIndex][address] + if (this.storageCache[txHash] && this.storageCache[txHash][address]) { + const storage = this.storageCache[txHash][address] return cb(null, { storage: JSON.parse(JSON.stringify(storage)), nextKey: null diff --git a/libs/remix-simulator/src/vm-context.ts b/libs/remix-simulator/src/vm-context.ts index e862fd0e3f..9e9afdef0a 100644 --- a/libs/remix-simulator/src/vm-context.ts +++ b/libs/remix-simulator/src/vm-context.ts @@ -2,11 +2,15 @@ 'use strict' import Web3 from 'web3' import { rlp, keccak, bufferToHex } from 'ethereumjs-util' -import { vm as remixLibVm, execution } from '@remix-project/remix-lib' +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 StateManager from '@ethereumjs/vm/dist/state/stateManager' import { StorageDump } from '@ethereumjs/vm/dist/state/interface' +import { Block } from '@ethereumjs/block' +import { Transaction } from '@ethereumjs/tx' /* extend vm state manager and instanciate VM @@ -75,6 +79,13 @@ class StateManagerCommonStorageDump extends StateManager { } } +export type CurrentVm = { + vm: VM, + web3vm: VmProxy, + stateManager: StateManagerCommonStorageDump, + common: Common +} + /* trigger contextChanged, web3EndpointChanged */ @@ -82,15 +93,14 @@ export class VMContext { currentFork: string blockGasLimitDefault: number blockGasLimit: number - customNetWorks - blocks - latestBlockNumber - blockByTxHash - txByHash - currentVm - web3vm - logsManager - exeResults + blocks: Record + latestBlockNumber: string + blockByTxHash: Record + txByHash: Record + currentVm: CurrentVm + web3vm: VmProxy + logsManager: any // LogsManager + exeResults: Record constructor (fork?) { this.blockGasLimitDefault = 4300000 @@ -98,11 +108,11 @@ export class VMContext { this.currentFork = fork || 'london' this.currentVm = this.createVm(this.currentFork) this.blocks = {} - this.latestBlockNumber = 0 + this.latestBlockNumber = "0x0" this.blockByTxHash = {} this.txByHash = {} this.exeResults = {} - this.logsManager = new execution.LogsManager() + this.logsManager = new LogsManager() } createVm (hardfork) { @@ -115,7 +125,9 @@ export class VMContext { allowUnlimitedContractSize: true }) - const web3vm = new remixLibVm.Web3VMProvider() + // VmProxy and VMContext are very intricated. + // VmProxy is used to track the EVM execution (to listen on opcode execution, in order for instance to generate the VM trace) + const web3vm = new VmProxy(this) web3vm.setVM(vm) return { vm, web3vm, stateManager, common } } @@ -140,7 +152,7 @@ export class VMContext { return this.currentVm } - addBlock (block) { + addBlock (block: Block) { let blockNumber = '0x' + block.header.number.toString('hex') if (blockNumber === '0x') { blockNumber = '0x0' diff --git a/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.css b/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.css index 8990810a9e..835b54615b 100644 --- a/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.css +++ b/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.css @@ -19,4 +19,8 @@ .navigator { } .navigator:hover { +} + +.cursorPointerRemixDebugger { + cursor: pointer; } \ No newline at end of file diff --git a/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.tsx b/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.tsx index 680c3b9ef8..2db94f72cc 100644 --- a/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.tsx @@ -65,11 +65,10 @@ export const ButtonNavigation = ({ stepOverBack, stepIntoBack, stepIntoForward,
- - State changes made during this call will be reverted. - This call will run out of gas. - The parent call will throw an exception + This call has reverted, state changes made during the call will be reverted. + This call will run out of gas. + The parent call will throw an exception +
Click { jumpToException && jumpToException() }}>here to jump where the call reverted.
) diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx index a9a8200e9b..de26b84af9 100644 --- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx @@ -32,7 +32,8 @@ export const DebuggerUI = (props: DebuggerUIProps) => { toastMessage: '', validationError: '', txNumberIsEmpty: true, - isLocalNodeUsed: false + isLocalNodeUsed: false, + sourceLocationStatus: '' }) useEffect(() => { @@ -87,7 +88,13 @@ export const DebuggerUI = (props: DebuggerUIProps) => { }) debuggerInstance.event.register('newSourceLocation', async (lineColumnPos, rawLocation, generatedSources, address) => { - if (!lineColumnPos) return + if (!lineColumnPos) { + await debuggerModule.discardHighlight() + setState(prevState => { + return { ...prevState, sourceLocationStatus: 'Source location not available.' } + }) + return + } const contracts = await debuggerModule.fetchContractAndCompile( address || currentReceipt.contractAddress || currentReceipt.to, currentReceipt) @@ -113,6 +120,9 @@ export const DebuggerUI = (props: DebuggerUIProps) => { } } if (path) { + setState(prevState => { + return { ...prevState, sourceLocationStatus: '' } + }) await debuggerModule.discardHighlight() await debuggerModule.highlight(lineColumnPos, path) } @@ -138,6 +148,12 @@ export const DebuggerUI = (props: DebuggerUIProps) => { const unloadRequested = (blockNumber, txIndex, tx) => { unLoad() + setState(prevState => { + return { + ...prevState, + sourceLocationStatus: '' + } + }) } const unLoad = () => { @@ -168,7 +184,8 @@ export const DebuggerUI = (props: DebuggerUIProps) => { setState(prevState => { return { ...prevState, - txNumber: txNumber + txNumber: txNumber, + sourceLocationStatus: '' } }) if (!isValidHash(txNumber)) { @@ -266,7 +283,8 @@ export const DebuggerUI = (props: DebuggerUIProps) => { return { ...prevState, validationError: '', - txNumber: txHash + txNumber: txHash, + sourceLocationStatus: '' } }) startDebugging(null, txHash, null, web3) @@ -315,6 +333,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => { { state.validationError && {state.validationError} } + { state.debugging && state.sourceLocationStatus &&
{state.sourceLocationStatus}
} { state.debugging && } { state.debugging && } diff --git a/libs/remix-ui/debugger-ui/src/lib/slider/slider.tsx b/libs/remix-ui/debugger-ui/src/lib/slider/slider.tsx index 81e036a8b8..06fe05e949 100644 --- a/libs/remix-ui/debugger-ui/src/lib/slider/slider.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/slider/slider.tsx @@ -1,10 +1,12 @@ -import React, { useState, useEffect } from 'react' // eslint-disable-line +import React, { useState, useEffect, useRef } from 'react' // eslint-disable-line export const Slider = ({ jumpTo, sliderValue, traceLength }) => { const [state, setState] = useState({ currentValue: 0 }) + const onChangeId = useRef(null) + useEffect(() => { setValue(sliderValue) }, [sliderValue]) @@ -18,9 +20,16 @@ export const Slider = ({ jumpTo, sliderValue, traceLength }) => { } const handleChange = (e) => { - const value = parseInt(e.target.value) - - setValue(value) + if (onChangeId.current) { + window.clearTimeout(onChangeId.current) + } + ((value) => { + onChangeId.current = setTimeout(() => { + console.log(value) + value = parseInt(value) + setValue(value) + }, 100) + })(e.target.value) } return ( diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx index eb57159048..b32b229f0b 100644 --- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx +++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx @@ -125,7 +125,7 @@ export const AssemblyItems = ({ registerEvent }) => {
-
+
{ assemblyItems.display.map((item, i) => { return
{ refs.current[i] = ref }}>{item}