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

pull/1508/head
bunsenstraat 4 years ago
commit 0cccd02ec7
  1. 11
      apps/debugger/src/app/debugger-api.ts
  2. 3
      apps/debugger/src/app/debugger.ts
  3. 2
      apps/debugger/tsconfig.json
  4. 6
      apps/remix-ide-e2e/src/tests/debugger.spec.ts
  5. 2
      apps/remix-ide-e2e/src/tests/publishContract.test.ts
  6. 2
      apps/remix-ide-e2e/src/tests/solidityImport.spec.ts
  7. 2
      apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts
  8. 2
      apps/remix-ide-e2e/tsconfig.json
  9. 2
      apps/remix-ide/ci/makeMockCompiler.js
  10. 3
      apps/remix-ide/src/app.js
  11. 2
      apps/remix-ide/src/app/editor/editor.js
  12. 70
      apps/remix-ide/src/app/tabs/compile-tab.js
  13. 21
      apps/remix-ide/src/app/tabs/test-tab.js
  14. 2
      apps/remix-ide/src/app/ui/TreeView.js
  15. 4
      apps/remix-ide/src/app/ui/confirmDialog.js
  16. 1
      apps/remix-ide/src/app/ui/landing-page/landing-page.js
  17. 36
      apps/remix-ide/src/blockchain/blockchain.js
  18. 2
      apps/remix-ide/tsconfig.json
  19. 2
      libs/remix-analyzer/tsconfig.json
  20. 2
      libs/remix-astwalker/tsconfig.json
  21. 2
      libs/remix-core-plugin/tsconfig.json
  22. 20
      libs/remix-debug/src/Ethdebugger.ts
  23. 51
      libs/remix-debug/src/debugger/debugger.ts
  24. 2
      libs/remix-debug/src/solidity-decoder/localDecoder.ts
  25. 4
      libs/remix-debug/src/solidity-decoder/stateDecoder.ts
  26. 6
      libs/remix-debug/src/solidity-decoder/types/ArrayType.ts
  27. 6
      libs/remix-debug/src/solidity-decoder/types/DynamicByteArray.ts
  28. 8
      libs/remix-debug/src/solidity-decoder/types/StringType.ts
  29. 2
      libs/remix-debug/src/solidity-decoder/types/Struct.ts
  30. 4
      libs/remix-debug/src/solidity-decoder/types/ValueType.ts
  31. 3
      libs/remix-debug/src/trace/traceManager.ts
  32. 2
      libs/remix-debug/tsconfig.json
  33. 379
      libs/remix-lib/src/helpers/hhconsoleSigs.ts
  34. 27
      libs/remix-lib/src/web3Provider/web3VmProvider.ts
  35. 2
      libs/remix-lib/tsconfig.json
  36. 2
      libs/remix-simulator/src/methods/blocks.ts
  37. 9
      libs/remix-simulator/src/methods/transactions.ts
  38. 9
      libs/remix-simulator/src/provider.ts
  39. 1
      libs/remix-simulator/test/blocks.ts
  40. 2
      libs/remix-simulator/tsconfig.json
  41. 2
      libs/remix-solidity/tsconfig.json
  42. 5
      libs/remix-tests/src/runTestSources.ts
  43. 8
      libs/remix-tests/src/testRunner.ts
  44. 1
      libs/remix-tests/src/types.ts
  45. 5
      libs/remix-tests/tests/examples_0/assert_ok_test.sol
  46. 1532
      libs/remix-tests/tests/examples_0/hardhat/console.sol
  47. 0
      libs/remix-tests/tests/testRunner.cli.spec_disabled.ts
  48. 39
      libs/remix-tests/tests/testRunner.spec.ts
  49. 2
      libs/remix-tests/tsconfig.json
  50. 35
      libs/remix-ui/README.md
  51. 2
      libs/remix-ui/checkbox/tsconfig.json
  52. 2
      libs/remix-ui/clipboard/tsconfig.json
  53. 70
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  54. 3
      libs/remix-ui/debugger-ui/src/lib/idebugger-api.ts
  55. 27
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx
  56. 1
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
  57. 4
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger.tsx
  58. 2
      libs/remix-ui/debugger-ui/tsconfig.json
  59. 2
      libs/remix-ui/file-explorer/tsconfig.json
  60. 2
      libs/remix-ui/modal-dialog/tsconfig.json
  61. 10
      libs/remix-ui/publish-to-storage/src/lib/publish-to-storage.tsx
  62. 20
      libs/remix-ui/publish-to-storage/src/lib/publishOnSwarm.tsx
  63. 20
      libs/remix-ui/publish-to-storage/src/lib/publishToIPFS.tsx
  64. 3
      libs/remix-ui/publish-to-storage/src/lib/types/index.ts
  65. 2
      libs/remix-ui/publish-to-storage/tsconfig.json
  66. 19
      libs/remix-ui/renderer/src/lib/renderer.tsx
  67. 2
      libs/remix-ui/renderer/tsconfig.json
  68. 2
      libs/remix-ui/settings/tsconfig.json
  69. 6
      libs/remix-ui/solidity-compiler/src/lib/actions/compiler.ts
  70. 43
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  71. 8
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  72. 34
      libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts
  73. 15
      libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx
  74. 21
      libs/remix-ui/solidity-compiler/src/lib/types/index.ts
  75. 2
      libs/remix-ui/solidity-compiler/tsconfig.json
  76. 2
      libs/remix-ui/static-analyser/tsconfig.json
  77. 2
      libs/remix-ui/toaster/tsconfig.json
  78. 2
      libs/remix-ui/tree-view/src/lib/remix-ui-tree-view.css
  79. 2
      libs/remix-ui/tree-view/tsconfig.json
  80. 2
      libs/remix-ui/utils/tsconfig.json
  81. 2
      libs/remix-ui/workspace/tsconfig.json
  82. 2
      libs/remix-url-resolver/tsconfig.json
  83. 26
      libs/remixd/src/services/slitherClient.ts
  84. 2
      libs/remixd/tsconfig.json
  85. 3
      nx.json
  86. 2
      package.json
  87. 48
      tsconfig.base.json
  88. 33
      tsconfig.json

@ -16,6 +16,7 @@ export const DebuggerApiMixin = (Base) => class extends Base {
}
}
this._web3 = new Web3(this.web3Provider)
remixDebug.init.extendWeb3(this._web3)
this.offsetToLineColumnConverter = {
async offsetToLineColumn (rawLocation, file, sources, asts) {
@ -118,17 +119,17 @@ export const DebuggerApiMixin = (Base) => class extends Base {
debug (hash) {
this.debugHash = hash
this.onDebugRequestedListener(hash)
if (this.onDebugRequestedListener) this.onDebugRequestedListener(hash)
}
onActivation () {
this.on('editor', 'breakpointCleared', (fileName, row) => this.onBreakpointClearedListener(fileName, row))
this.on('editor', 'breakpointAdded', (fileName, row) => this.onBreakpointAddedListener(fileName, row))
this.on('editor', 'contentChanged', () => this.onEditorContentChangedListener())
this.on('editor', 'breakpointCleared', (fileName, row) => { if (this.onBreakpointClearedListener) this.onBreakpointClearedListener(fileName, row) })
this.on('editor', 'breakpointAdded', (fileName, row) => { if (this.onBreakpointAddedListener) this.onBreakpointAddedListener(fileName, row) })
this.on('editor', 'contentChanged', () => { if (this.onEditorContentChangedListener) this.onEditorContentChangedListener() })
}
onDeactivation () {
this.onRemoveHighlightsListener()
if (this.onRemoveHighlightsListener) this.onRemoveHighlightsListener()
this.off('editor', 'breakpointCleared')
this.off('editor', 'breakpointAdded')
this.off('editor', 'contentChanged')

@ -23,6 +23,7 @@ export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) {
fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilerAbstract>
getFile: (path: string) => Promise<string>
setFile: (path: string, content: string) => Promise<void>
getDebugWeb3: () => any // returns an instance of web3.js
getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available)
web3: () => any // returns an instance of web3.js
}

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -72,8 +72,8 @@ module.exports = {
.waitForElementContainsText('*[data-id="stepdetail"]', 'execution step:\n0', 60000)
.click('*[data-id="buttonNavigatorJumpNextBreakpoint"]')
.pause(10000)
.waitForElementContainsText('*[data-id="stepdetail"]', 'vm trace step:\n348', 60000)
.waitForElementContainsText('*[data-id="stepdetail"]', 'execution step:\n348', 60000)
.waitForElementContainsText('*[data-id="stepdetail"]', 'vm trace step:\n352', 60000)
.waitForElementContainsText('*[data-id="stepdetail"]', 'execution step:\n352', 60000)
},
'Should display solidity imported code while debugging github import': function (browser: NightwatchBrowser) {
@ -212,7 +212,7 @@ module.exports = {
'Should start debugging using remix debug nodes (rinkeby)': '' + function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.8.4+commit.c7e474f2.js')
.setSolidityCompilerVersion('soljson-v0.8.7+commit.e28d00a7.js')
.addFile('useDebugNodes.sol', sources[5]['useDebugNodes.sol']) // compile contract
.clickLaunchIcon('udapp')
.click('*[data-id="settingsWeb3Mode"]') // select web3 provider with debug nodes URL

@ -32,6 +32,7 @@ module.exports = {
.click('[data-id="publishToStorage-modal-footer-ok-react"]')
},
/* Disableing the test untill refactoring and the new swarm usage
'Publish on Swarm': '' + function (browser: NightwatchBrowser) {
browser
.click('#publishOnSwarm')
@ -47,6 +48,7 @@ module.exports = {
})
.click('[data-id="publishToStorage-modal-footer-ok-react"]')
},
*/
'Should publish contract metadata to ipfs on deploy': function (browser: NightwatchBrowser) {
browser

@ -80,7 +80,7 @@ module.exports = {
'Test NPM Import (with unpkg.com)': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.4+commit.c7e474f2.js')
.setSolidityCompilerVersion('soljson-v0.8.7+commit.e28d00a7.js')
.clickLaunchIcon('filePanel')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled9.sol', sources[8]['Untitled9.sol'])

@ -264,7 +264,7 @@ contract C {
'customError.sol': {
content: `// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;
pragma solidity ^0.8.7;
/// error description
/// @param a param1

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node", "nightwatch"],
"esModuleInterop": true

@ -3,7 +3,7 @@
var fs = require('fs')
var compiler = require('solc')
var compilerInput = require('@remix-project/remix-solidity').CompilerInput
var defaultVersion = 'soljson-v0.8.4+commit.c7e474f2.js'
var defaultVersion = 'soljson-v0.8.7+commit.e28d00a7.js'
const path = require('path')
compiler.loadRemoteVersion(defaultVersion, (error, solcSnapshot) => {

@ -306,6 +306,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const contextualListener = new ContextualListener({ editor })
engine.register([
blockchain,
contentImport,
themeModule,
editor,
@ -481,7 +482,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
await appManager.activatePlugin(['sidePanel']) // activating host plugin separately
await appManager.activatePlugin(['home'])
await appManager.activatePlugin(['settings'])
await appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'filePanel', 'contextualListener', 'terminal', 'fetchAndCompile', 'contentImport'])
await appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'filePanel', 'contextualListener', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport'])
// Set workspace after initial activation
if (Array.isArray(workspace)) {

@ -49,7 +49,7 @@ const profile = {
name: 'editor',
description: 'service - editor',
version: packageJson.version,
methods: ['highlight', 'discardHighlight', 'discardHighlightAt', 'clearAnnotations', 'addAnnotation']
methods: ['highlight', 'discardHighlight', 'discardHighlightAt', 'clearAnnotations', 'addAnnotation', 'gotoLine']
}
class Editor extends Plugin {

@ -52,15 +52,7 @@ class CompileTab extends ViewPlugin {
eventHandlers: {},
loading: false
}
this.compileTabLogic = new CompileTabLogic(
this.queryParams,
this.fileManager,
this.editor,
this.config,
this.fileProvider,
this.contentImport,
this.setCompileErrors.bind(this)
)
this.compileTabLogic = new CompileTabLogic(this, this.contentImport)
this.compiler = this.compileTabLogic.compiler
this.compileTabLogic.init()
this.contractMap = {}
@ -116,13 +108,21 @@ class CompileTab extends ViewPlugin {
this.call('editor', 'clearAnnotations')
}
this.on('filePanel', 'setWorkspace', (workspace) => {
const resetView = (isLocalhost) => {
this.compileTabLogic.isHardhatProject().then((result) => {
if (result && workspace.isLocalhost) this.isHardHatProject = true
if (result && isLocalhost) this.isHardHatProject = true
else this.isHardHatProject = false
this.renderComponent()
})
this.resetResults()
}
this.on('filePanel', 'setWorkspace', (workspace) => {
resetView(workspace.isLocalhost)
})
this.on('remixd', 'rootFolderChanged', () => {
resetView(true)
})
this.compileTabLogic.event.on('startingCompilation', this.data.eventHandlers.onStartingCompilation)
@ -203,6 +203,10 @@ class CompileTab extends ViewPlugin {
return this.compileTabLogic.compiler.state.lastCompilationResult
}
addExternalFile (fileName, content) {
this.fileProvider.addExternal(fileName, content)
}
/**
* compile using @arg fileName.
* The module UI will be updated accordingly to the new compilation result.
@ -278,6 +282,50 @@ class CompileTab extends ViewPlugin {
, this.el)
}
getParameters () {
return this.queryParams.get()
}
setParameters (params) {
this.queryParams.update(params)
}
getConfiguration (name) {
return this.config.get(name)
}
setConfiguration (name, value) {
this.config.set(name, value)
}
fileProviderOf (fileName) {
return this.fileManager.fileProviderOf(fileName)
}
getFileManagerMode () {
return this.fileManager.mode
}
fileExists (fileName) {
return this.call('fileManager', 'exists', fileName)
}
writeFile (fileName, content) {
return this.call('fileManager', 'writeFile', fileName, content)
}
readFile (fileName) {
return this.call('fileManager', 'readFile', fileName)
}
saveCurrentFile () {
return this.fileManager.saveCurrentFile()
}
open (fileName) {
return this.call('fileManager', 'open', fileName)
}
onActivation () {
this.call('manager', 'activatePlugin', 'solidity-logic')
this.listenToEvents()

@ -1,6 +1,7 @@
import { ViewPlugin } from '@remixproject/engine-web'
import { removeMultipleSlashes, removeTrailingSlashes } from '../../lib/helper'
import { canUseWorker, urlFromVersion } from '@remix-project/remix-solidity'
import { format } from 'util'
var yo = require('yo-yo')
var async = require('async')
var tooltip = require('../ui/tooltip')
@ -179,6 +180,24 @@ module.exports = class TestTab extends ViewPlugin {
}
}
printHHLogs (logsArr, testName) {
let finalLogs = `<b>${testName}:</b>\n`
for (const log of logsArr) {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
finalLogs = finalLogs + '&emsp;' + formattedLog + '\n'
}
this.call('terminal', 'log', { type: 'info', value: finalLogs })
}
testCallback (result, runningTests) {
this.testsOutput.hidden = false
if (result.type === 'contract') {
@ -197,6 +216,7 @@ module.exports = class TestTab extends ViewPlugin {
`
this.testsOutput.appendChild(this.outputHeader)
} else if (result.type === 'testPass') {
if (result.hhLogs && result.hhLogs.length) this.printHHLogs(result.hhLogs, result.value)
this.testsOutput.appendChild(yo`
<div
id="${this.runningTestFileName}"
@ -208,6 +228,7 @@ module.exports = class TestTab extends ViewPlugin {
</div>
`)
} else if (result.type === 'testFailure') {
if (result.hhLogs && result.hhLogs.length) this.printHHLogs(result.hhLogs, result.value)
if (!result.assertMethod) {
this.testsOutput.appendChild(yo`
<div

@ -27,7 +27,7 @@ var css = csjs`
word-break: break-all;
}
.label_key {
min-width: 15%;
min-width: max-content;
max-width: 80%;
word-break: break-word;
}

@ -113,8 +113,8 @@ function confirmDialog (tx, network, amount, gasEstimation, newGasPriceCb, initi
</div>
</div>
<div class="d-flex py-1 align-items-center custom-control custom-checkbox ${css.checkbox}">
<input class="form-check-input custom-control-input" id='confirmsetting' type="checkbox">
<label class="m-0 form-check-label custom-control-label">Do not show this warning again.</label>
<input class="form-check-input custom-control-input" id="confirmsetting" type="checkbox">
<label class="m-0 form-check-label custom-control-label" for="confirmsetting">Do not show this warning again.</label>
</div>
</div>
`

@ -538,7 +538,6 @@ export class LandingPage extends ViewPlugin {
<div class="btn-group">
<button class="btn mr-1 btn-secondary" data-id="landingPageImportFromGistButton" onclick="${() => importFromGist()}">Gist</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Github', 'github URL', ['https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol', 'https://github.com/OpenZeppelin/openzeppelin-solidity/blob/67bca857eedf99bf44a4b6a0fc5b5ed553135316/contracts/access/Roles.sol'])}">GitHub</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Swarm', 'bzz-raw URL', ['bzz-raw://<swarm-hash>'])}">Swarm</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Ipfs', 'ipfs URL', ['ipfs://<ipfs-hash>'])}">Ipfs</button>
<button class="btn mx-1 btn-secondary" onclick="${() => load('Https', 'http/https raw content', ['https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'])}">https</button>
</div><!-- end of btn-group -->

@ -1,7 +1,9 @@
import Web3 from 'web3'
import { Plugin } from '@remixproject/engine'
import { toBuffer, addHexPrefix } from 'ethereumjs-util'
import { waterfall } from 'async'
import { EventEmitter } from 'events'
import { format } from 'util'
import { ExecutionContext } from './execution-context'
import VMProvider from './providers/vm.js'
import InjectedProvider from './providers/injected.js'
@ -9,10 +11,20 @@ import NodeProvider from './providers/node.js'
import { execution, EventManager, helpers } from '@remix-project/remix-lib'
const { txFormat, txExecution, typeConversion, txListener: Txlistener, TxRunner, TxRunnerWeb3, txHelper } = execution
const { txResultHelper: resultToRemixTx } = helpers
const packageJson = require('../../../../package.json')
const profile = {
name: 'blockchain',
displayName: 'Blockchain',
description: 'Blockchain - Logic',
methods: [],
version: packageJson.version
}
class Blockchain {
class Blockchain extends Plugin {
// NOTE: the config object will need to be refactored out in remix-lib
constructor (config) {
super(profile)
this.event = new EventManager()
this.executionContext = new ExecutionContext()
@ -311,8 +323,8 @@ class Blockchain {
// TODO : event should be triggered by Udapp instead of TxListener
/** Listen on New Transaction. (Cannot be done inside constructor because txlistener doesn't exist yet) */
startListening (txlistener) {
txlistener.event.register('newTransaction', (tx) => {
this.events.emit('newTransaction', tx)
txlistener.event.register('newTransaction', (tx, receipt) => {
this.events.emit('newTransaction', tx, receipt)
})
}
@ -487,6 +499,24 @@ class Blockchain {
let execResult
let returnValue = null
if (isVM) {
const hhlogs = await this.web3().eth.getHHLogsForTx(txResult.transactionHash)
if (hhlogs && hhlogs.length) {
let finalLogs = '<b>console.log:</b>\n'
for (const log of hhlogs) {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
finalLogs = finalLogs + '&emsp;' + formattedLog + '\n'
}
this.call('terminal', 'log', { type: 'info', value: finalLogs })
}
execResult = await this.web3().eth.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.

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node"],
"module": "commonjs",

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node"],
"module": "commonjs",

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [

@ -33,7 +33,6 @@ export class Ethdebugger {
storageResolver
callTree
breakpointManager
statusMessage
constructor (opts) {
this.compilationResult = opts.compilationResult || function (contractAddress) { return null }
@ -151,22 +150,19 @@ export class Ethdebugger {
this.event.trigger('traceUnloaded')
}
debug (tx) {
async debug (tx) {
if (this.traceManager.isLoading) {
return
}
tx.to = tx.to || contractCreationToken('0')
this.tx = tx
this.traceManager.resolveTrace(tx).then(async (result) => {
this.setCompilationResult(await this.compilationResult(tx.to))
this.event.trigger('newTraceLoaded', [this.traceManager.trace])
if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) {
this.breakpointManager.jumpNextBreakpoint(false)
}
this.storageResolver = new StorageResolver({ web3: this.traceManager.web3 })
}).catch((error) => {
this.statusMessage = error ? error.message : 'Trace not loaded'
})
await this.traceManager.resolveTrace(tx)
this.setCompilationResult(await this.compilationResult(tx.to))
this.event.trigger('newTraceLoaded', [this.traceManager.trace])
if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) {
this.breakpointManager.jumpNextBreakpoint(false)
}
this.storageResolver = new StorageResolver({ web3: this.traceManager.web3 })
}
}

@ -99,44 +99,31 @@ export class Debugger {
this.debugger.web3 = web3
}
debug (blockNumber, txNumber, tx, loadingCb): Promise<void> {
async debug (blockNumber, txNumber, tx, loadingCb) {
const web3 = this.debugger.web3
return new Promise((resolve, reject) => {
if (this.debugger.traceManager.isLoading) {
return resolve()
}
if (this.debugger.traceManager.isLoading) {
return
}
if (tx) {
if (!tx.to) {
tx.to = contractCreationToken('0')
}
this.debugTx(tx, loadingCb)
return resolve()
if (tx) {
if (!tx.to) {
tx.to = contractCreationToken('0')
}
return await this.debugTx(tx, loadingCb)
}
try {
if (txNumber.indexOf('0x') !== -1) {
return web3.eth.getTransaction(txNumber, (_error, tx) => {
if (_error) return reject(_error)
if (!tx) return reject(new Error('cannot find transaction ' + txNumber))
this.debugTx(tx, loadingCb)
return resolve()
})
}
web3.eth.getTransactionFromBlock(blockNumber, txNumber, (_error, tx) => {
if (_error) return reject(_error)
if (!tx) return reject(new Error('cannot find transaction ' + blockNumber + ' ' + txNumber))
this.debugTx(tx, loadingCb)
return resolve()
})
} catch (e) {
return reject(e.message)
}
})
if (txNumber.indexOf('0x') !== -1) {
tx = await web3.eth.getTransaction(txNumber)
if (!tx) throw new Error('cannot find transaction ' + txNumber)
} else {
tx = await web3.eth.getTransactionFromBlock(blockNumber, txNumber)
if (!tx) throw new Error('cannot find transaction ' + blockNumber + ' ' + txNumber)
}
return await this.debugTx(tx, loadingCb)
}
debugTx (tx, loadingCb) {
async debugTx (tx, loadingCb) {
this.step_manager = new DebuggerStepManager(this.debugger, this.debugger.traceManager)
this.debugger.codeManager.event.register('changed', this, (code, address, instIndex) => {
@ -162,7 +149,7 @@ export class Debugger {
})
loadingCb()
this.debugger.debug(tx)
await this.debugger.debug(tx)
}
unload () {

@ -21,7 +21,7 @@ export async function solidityLocals (vmtraceIndex, internalTreeCall, stack, mem
locals[name] = await variable.type.decodeFromStack(variable.stackDepth, stack, memory, storageResolver, calldata, cursor, variable)
} catch (e) {
console.log(e)
locals[name] = '<decoding failed - ' + e.message + '>'
locals[name] = { error: '<decoding failed - ' + e.message + '>' }
}
}
}

@ -25,7 +25,7 @@ export async function decodeState (stateVars, storageResolver) {
ret[stateVar.name] = decoded
} catch (e) {
console.log(e)
ret[stateVar.name] = '<decoding failed - ' + e.message + '>'
ret[stateVar.name] = { error: '<decoding failed - ' + e.message + '>' }
}
}
return ret
@ -64,6 +64,6 @@ export async function solidityState (storageResolver, astList, contractName) {
try {
return await decodeState(stateVars, storageResolver)
} catch (e) {
return '<decoding failed - ' + e.message + '>'
return { error: '<decoding failed - ' + e.message + '>' }
}
}

@ -36,7 +36,7 @@ export class ArrayType extends RefType {
} catch (e) {
console.log(e)
return {
value: '<decoding failed - ' + e.message + '>',
error: '<decoding failed - ' + e.message + '>',
type: this.typeName
}
}
@ -56,7 +56,7 @@ export class ArrayType extends RefType {
ret.push(await this.underlyingType.decodeFromStorage(currentLocation, storageResolver))
} catch (e) {
return {
value: '<decoding failed - ' + e.message + '>',
error: '<decoding failed - ' + e.message + '>',
type: this.typeName
}
}
@ -84,7 +84,7 @@ export class ArrayType extends RefType {
}
if (isNaN(length)) {
return {
value: '<decoding failed - length is NaN>',
error: '<decoding failed - length is NaN>',
type: 'Error'
}
}

@ -16,7 +16,7 @@ export class DynamicByteArray extends RefType {
value = await extractHexValue(location, storageResolver, this.storageBytes)
} catch (e) {
console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName }
return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
}
const length = new BN(value, 16)
if (length.testn(0)) {
@ -27,7 +27,7 @@ export class DynamicByteArray extends RefType {
currentSlot = await readFromStorage(dataPos, storageResolver)
} catch (e) {
console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName }
return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
}
while (length.gt(new BN(ret.length)) && ret.length < 32000) {
currentSlot = currentSlot.replace('0x', '')
@ -37,7 +37,7 @@ export class DynamicByteArray extends RefType {
currentSlot = await readFromStorage(dataPos, storageResolver)
} catch (e) {
console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName }
return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
}
}
return { value: '0x' + ret.replace(/(00)+$/, ''), length: '0x' + length.toString(16), type: this.typeName }

@ -15,17 +15,17 @@ export class StringType extends DynamicByteArray {
decoded = await super.decodeFromStorage(location, storageResolver)
} catch (e) {
console.log(e)
return '<decoding failed - ' + e.message + '>'
return { error: '<decoding failed - ' + e.message + '>' }
}
return format(decoded)
}
async decodeFromStack (stackDepth, stack, memory, calldata, variableDetails?) {
async decodeFromStack (stackDepth, stack, memory, storageResolver, calldata, cursor, variableDetails?) {
try {
return await super.decodeFromStack(stackDepth, stack, memory, null, calldata, variableDetails)
return await super.decodeFromStack(stackDepth, stack, memory, storageResolver, calldata, cursor, variableDetails)
} catch (e) {
console.log(e)
return '<decoding failed - ' + e.message + '>'
return { error: '<decoding failed - ' + e.message + '>' }
}
}

@ -22,7 +22,7 @@ export class Struct extends RefType {
ret[item.name] = await item.type.decodeFromStorage(globalLocation, storageResolver)
} catch (e) {
console.log(e)
ret[item.name] = '<decoding failed - ' + e.message + '>'
ret[item.name] = { error: '<decoding failed - ' + e.message + '>' }
}
}
return { value: ret, type: this.typeName }

@ -31,7 +31,7 @@ export class ValueType {
return { value: this.decodeValue(value), type: this.typeName }
} catch (e) {
console.log(e)
return { value: '<decoding failed - ' + e.message + '>', type: this.typeName }
return { error: '<decoding failed - ' + e.message + '>', type: this.typeName }
}
}
@ -43,7 +43,7 @@ export class ValueType {
* @param {String} - memory
* @return {Object} - decoded value
*/
async decodeFromStack (stackDepth, stack, memory, calldata, variableDetails?) {
async decodeFromStack (stackDepth, stack, memory, storageResolver, calldata, cursor, variableDetails?) {
let value
if (stackDepth >= stack.length) {
value = this.decodeValue('')

@ -30,9 +30,8 @@ export class TraceManager {
this.init()
if (!this.web3) throw new Error('web3 not loaded')
this.isLoading = true
const result = await this.getTrace(tx.hash)
try {
const result = await this.getTrace(tx.hash)
if (result['structLogs'].length > 0) {
this.trace = result['structLogs']

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node", "tape"],
"esModuleInterop": true

@ -0,0 +1,379 @@
// Fetched from https://github.com/nomiclabs/hardhat/blob/ee4969a0a8f746f4775d4018326056d161066869/packages/hardhat-core/src/internal/hardhat-network/stack-traces/logger.ts#L47
export const ConsoleLogs = {
1368866505: '()',
1309416733: '(int)',
4122065833: '(uint)',
1093685164: '(string)',
843419373: '(bool)',
741264322: '(address)',
199720790: '(bytes)',
1847107880: '(bytes1)',
3921027734: '(bytes2)',
763578662: '(bytes3)',
3764340945: '(bytes4)',
2793701517: '(bytes5)',
2927928721: '(bytes6)',
1322614312: '(bytes7)',
1334060334: '(bytes8)',
2428341456: '(bytes9)',
20780939: '(bytes10)',
67127854: '(bytes11)',
2258660029: '(bytes12)',
2488442420: '(bytes13)',
2456219775: '(bytes14)',
3667227872: '(bytes15)',
1717330180: '(bytes16)',
866084666: '(bytes17)',
3302112666: '(bytes18)',
1584093747: '(bytes19)',
1367925737: '(bytes20)',
3923391840: '(bytes21)',
3589990556: '(bytes22)',
2879508237: '(bytes23)',
4055063348: '(bytes24)',
193248344: '(bytes25)',
4172368369: '(bytes26)',
976705501: '(bytes27)',
3358255854: '(bytes28)',
1265222613: '(bytes29)',
3994207469: '(bytes30)',
3263516050: '(bytes31)',
666357637: '(bytes32)',
1812949376: '(uint,uint)',
262402885: '(uint,string)',
510514412: '(uint,bool)',
1491830284: '(uint,address)',
2534451664: '(string,uint)',
1264337527: '(string,string)',
3283441205: '(string,bool)',
832238387: '(string,address)',
910912146: '(bool,uint)',
2414527781: '(bool,string)',
705760899: '(bool,bool)',
2235320393: '(bool,address)',
574869411: '(address,uint)',
1973388987: '(address,string)',
1974863315: '(address,bool)',
3673216170: '(address,address)',
3884059252: '(uint,uint,uint)',
2104037094: '(uint,uint,string)',
1733758967: '(uint,uint,bool)',
3191032091: '(uint,uint,address)',
1533929535: '(uint,string,uint)',
1062716053: '(uint,string,string)',
1185403086: '(uint,string,bool)',
529592906: '(uint,string,address)',
1515034914: '(uint,bool,uint)',
2332955902: '(uint,bool,string)',
3587091680: '(uint,bool,bool)',
1112473535: '(uint,bool,address)',
2286109610: '(uint,address,uint)',
3464692859: '(uint,address,string)',
2060456590: '(uint,address,bool)',
2104993307: '(uint,address,address)',
2526862595: '(string,uint,uint)',
2750793529: '(string,uint,string)',
4043501061: '(string,uint,bool)',
3817119609: '(string,uint,address)',
4083337817: '(string,string,uint)',
753761519: '(string,string,string)',
2967534005: '(string,string,bool)',
2515337621: '(string,string,address)',
689682896: '(string,bool,uint)',
3801674877: '(string,bool,string)',
2232122070: '(string,bool,bool)',
2469116728: '(string,bool,address)',
130552343: '(string,address,uint)',
3773410639: '(string,address,string)',
3374145236: '(string,address,bool)',
4243355104: '(string,address,address)',
995886048: '(bool,uint,uint)',
3359211184: '(bool,uint,string)',
464374251: '(bool,uint,bool)',
3302110471: '(bool,uint,address)',
3224906412: '(bool,string,uint)',
2960557183: '(bool,string,string)',
3686056519: '(bool,string,bool)',
2509355347: '(bool,string,address)',
2954061243: '(bool,bool,uint)',
626391622: '(bool,bool,string)',
1349555864: '(bool,bool,bool)',
276362893: '(bool,bool,address)',
3950005167: '(bool,address,uint)',
3734671984: '(bool,address,string)',
415876934: '(bool,address,bool)',
3530962535: '(bool,address,address)',
2273710942: '(address,uint,uint)',
3136907337: '(address,uint,string)',
3846889796: '(address,uint,bool)',
2548867988: '(address,uint,address)',
484110986: '(address,string,uint)',
4218888805: '(address,string,string)',
3473018801: '(address,string,bool)',
4035396840: '(address,string,address)',
742821141: '(address,bool,uint)',
555898316: '(address,bool,string)',
3951234194: '(address,bool,bool)',
4044790253: '(address,bool,address)',
1815506290: '(address,address,uint)',
7426238: '(address,address,string)',
4070990470: '(address,address,bool)',
25986242: '(address,address,address)',
1554033982: '(uint,uint,uint,uint)',
2024634892: '(uint,uint,uint,string)',
1683143115: '(uint,uint,uint,bool)',
3766828905: '(uint,uint,uint,address)',
949229117: '(uint,uint,string,uint)',
2080582194: '(uint,uint,string,string)',
2989403910: '(uint,uint,string,bool)',
1127384482: '(uint,uint,string,address)',
1818524812: '(uint,uint,bool,uint)',
4024028142: '(uint,uint,bool,string)',
2495495089: '(uint,uint,bool,bool)',
3776410703: '(uint,uint,bool,address)',
1628154048: '(uint,uint,address,uint)',
3600994782: '(uint,uint,address,string)',
2833785006: '(uint,uint,address,bool)',
3398671136: '(uint,uint,address,address)',
3221501959: '(uint,string,uint,uint)',
2730232985: '(uint,string,uint,string)',
2270850606: '(uint,string,uint,bool)',
2877020669: '(uint,string,uint,address)',
1995203422: '(uint,string,string,uint)',
1474103825: '(uint,string,string,string)',
310782872: '(uint,string,string,bool)',
3432549024: '(uint,string,string,address)',
2763295359: '(uint,string,bool,uint)',
2370346144: '(uint,string,bool,string)',
1371286465: '(uint,string,bool,bool)',
2037328032: '(uint,string,bool,address)',
2565338099: '(uint,string,address,uint)',
4170733439: '(uint,string,address,string)',
4181720887: '(uint,string,address,bool)',
2141537675: '(uint,string,address,address)',
1451396516: '(uint,bool,uint,uint)',
3906845782: '(uint,bool,uint,string)',
3534472445: '(uint,bool,uint,bool)',
1329595790: '(uint,bool,uint,address)',
2438978344: '(uint,bool,string,uint)',
2754870525: '(uint,bool,string,string)',
879671495: '(uint,bool,string,bool)',
1231956916: '(uint,bool,string,address)',
3173363033: '(uint,bool,bool,uint)',
831186331: '(uint,bool,bool,string)',
1315722005: '(uint,bool,bool,bool)',
1392910941: '(uint,bool,bool,address)',
1102442299: '(uint,bool,address,uint)',
2721084958: '(uint,bool,address,string)',
2449150530: '(uint,bool,address,bool)',
2263728396: '(uint,bool,address,address)',
3399106228: '(uint,address,uint,uint)',
1054063912: '(uint,address,uint,string)',
435581801: '(uint,address,uint,bool)',
4256361684: '(uint,address,uint,address)',
2697204968: '(uint,address,string,uint)',
2373420580: '(uint,address,string,string)',
581204390: '(uint,address,string,bool)',
3420819197: '(uint,address,string,address)',
2064181483: '(uint,address,bool,uint)',
1676730946: '(uint,address,bool,string)',
2116501773: '(uint,address,bool,bool)',
3056677012: '(uint,address,bool,address)',
2587672470: '(uint,address,address,uint)',
2034490470: '(uint,address,address,string)',
22350596: '(uint,address,address,bool)',
1430734329: '(uint,address,address,address)',
149837414: '(string,uint,uint,uint)',
2773406909: '(string,uint,uint,string)',
4147936829: '(string,uint,uint,bool)',
3201771711: '(string,uint,uint,address)',
2697245221: '(string,uint,string,uint)',
1821956834: '(string,uint,string,string)',
3919545039: '(string,uint,string,bool)',
3144824297: '(string,uint,string,address)',
1427009269: '(string,uint,bool,uint)',
1993105508: '(string,uint,bool,string)',
3816813520: '(string,uint,bool,bool)',
3847527825: '(string,uint,bool,address)',
1481210622: '(string,uint,address,uint)',
844415720: '(string,uint,address,string)',
285649143: '(string,uint,address,bool)',
3939013249: '(string,uint,address,address)',
3587119056: '(string,string,uint,uint)',
2366909661: '(string,string,uint,string)',
3864418506: '(string,string,uint,bool)',
1565476480: '(string,string,uint,address)',
2681211381: '(string,string,string,uint)',
3731419658: '(string,string,string,string)',
739726573: '(string,string,string,bool)',
1834430276: '(string,string,string,address)',
2256636538: '(string,string,bool,uint)',
1585754346: '(string,string,bool,string)',
1081628777: '(string,string,bool,bool)',
3279013851: '(string,string,bool,address)',
1250010474: '(string,string,address,uint)',
3944480640: '(string,string,address,string)',
1556958775: '(string,string,address,bool)',
1134328815: '(string,string,address,address)',
1572859960: '(string,bool,uint,uint)',
1119461927: '(string,bool,uint,string)',
1019590099: '(string,bool,uint,bool)',
1909687565: '(string,bool,uint,address)',
885731469: '(string,bool,string,uint)',
2821114603: '(string,bool,string,string)',
1066037277: '(string,bool,string,bool)',
3764542249: '(string,bool,string,address)',
2155164136: '(string,bool,bool,uint)',
2636305885: '(string,bool,bool,string)',
2304440517: '(string,bool,bool,bool)',
1905304873: '(string,bool,bool,address)',
685723286: '(string,bool,address,uint)',
764294052: '(string,bool,address,string)',
2508990662: '(string,bool,address,bool)',
870964509: '(string,bool,address,address)',
3668153533: '(string,address,uint,uint)',
1280700980: '(string,address,uint,string)',
1522647356: '(string,address,uint,bool)',
2741431424: '(string,address,uint,address)',
2405583849: '(string,address,string,uint)',
609847026: '(string,address,string,string)',
1595265676: '(string,address,string,bool)',
2864486961: '(string,address,string,address)',
3318856587: '(string,address,bool,uint)',
72663161: '(string,address,bool,string)',
2038975531: '(string,address,bool,bool)',
573965245: '(string,address,bool,address)',
1857524797: '(string,address,address,uint)',
2148146279: '(string,address,address,string)',
3047013728: '(string,address,address,bool)',
3985582326: '(string,address,address,address)',
853517604: '(bool,uint,uint,uint)',
3657852616: '(bool,uint,uint,string)',
2753397214: '(bool,uint,uint,bool)',
4049711649: '(bool,uint,uint,address)',
1098907931: '(bool,uint,string,uint)',
3542771016: '(bool,uint,string,string)',
2446522387: '(bool,uint,string,bool)',
2781285673: '(bool,uint,string,address)',
3554563475: '(bool,uint,bool,uint)',
3067439572: '(bool,uint,bool,string)',
2650928961: '(bool,uint,bool,bool)',
1114097656: '(bool,uint,bool,address)',
3399820138: '(bool,uint,address,uint)',
403247937: '(bool,uint,address,string)',
1705899016: '(bool,uint,address,bool)',
2318373034: '(bool,uint,address,address)',
2387273838: '(bool,string,uint,uint)',
2007084013: '(bool,string,uint,string)',
549177775: '(bool,string,uint,bool)',
1529002296: '(bool,string,uint,address)',
1574643090: '(bool,string,string,uint)',
392356650: '(bool,string,string,string)',
508266469: '(bool,string,string,bool)',
2547225816: '(bool,string,string,address)',
2372902053: '(bool,string,bool,uint)',
1211958294: '(bool,string,bool,string)',
3697185627: '(bool,string,bool,bool)',
1401816747: '(bool,string,bool,address)',
453743963: '(bool,string,address,uint)',
316065672: '(bool,string,address,string)',
1842623690: '(bool,string,address,bool)',
724244700: '(bool,string,address,address)',
1181212302: '(bool,bool,uint,uint)',
1348569399: '(bool,bool,uint,string)',
2874982852: '(bool,bool,uint,bool)',
201299213: '(bool,bool,uint,address)',
395003525: '(bool,bool,string,uint)',
1830717265: '(bool,bool,string,string)',
3092715066: '(bool,bool,string,bool)',
4188875657: '(bool,bool,string,address)',
3259532109: '(bool,bool,bool,uint)',
719587540: '(bool,bool,bool,string)',
992632032: '(bool,bool,bool,bool)',
2352126746: '(bool,bool,bool,address)',
1620281063: '(bool,bool,address,uint)',
2695133539: '(bool,bool,address,string)',
3231908568: '(bool,bool,address,bool)',
4102557348: '(bool,bool,address,address)',
2617143996: '(bool,address,uint,uint)',
2691192883: '(bool,address,uint,string)',
4002252402: '(bool,address,uint,bool)',
1760647349: '(bool,address,uint,address)',
194640930: '(bool,address,string,uint)',
2805734838: '(bool,address,string,string)',
3804222987: '(bool,address,string,bool)',
1870422078: '(bool,address,string,address)',
1287000017: '(bool,address,bool,uint)',
1248250676: '(bool,address,bool,string)',
1788626827: '(bool,address,bool,bool)',
474063670: '(bool,address,bool,address)',
1384430956: '(bool,address,address,uint)',
3625099623: '(bool,address,address,string)',
1180699616: '(bool,address,address,bool)',
487903233: '(bool,address,address,address)',
1024368100: '(address,uint,uint,uint)',
2301889963: '(address,uint,uint,string)',
3964381346: '(address,uint,uint,bool)',
519451700: '(address,uint,uint,address)',
4111650715: '(address,uint,string,uint)',
2119616147: '(address,uint,string,string)',
2751614737: '(address,uint,string,bool)',
3698927108: '(address,uint,string,address)',
1770996626: '(address,uint,bool,uint)',
2391690869: '(address,uint,bool,string)',
4272018778: '(address,uint,bool,bool)',
602229106: '(address,uint,bool,address)',
2782496616: '(address,uint,address,uint)',
1567749022: '(address,uint,address,string)',
4051804649: '(address,uint,address,bool)',
3961816175: '(address,uint,address,address)',
2764647008: '(address,string,uint,uint)',
1561552329: '(address,string,uint,string)',
2116357467: '(address,string,uint,bool)',
3755464715: '(address,string,uint,address)',
2706362425: '(address,string,string,uint)',
1560462603: '(address,string,string,string)',
900007711: '(address,string,string,bool)',
2689478535: '(address,string,string,address)',
3877655068: '(address,string,bool,uint)',
3154862590: '(address,string,bool,string)',
1595759775: '(address,string,bool,bool)',
542667202: '(address,string,bool,address)',
2350461865: '(address,string,address,uint)',
4158874181: '(address,string,address,string)',
233909110: '(address,string,address,bool)',
221706784: '(address,string,address,address)',
3255869470: '(address,bool,uint,uint)',
2606272204: '(address,bool,uint,string)',
2244855215: '(address,bool,uint,bool)',
227337758: '(address,bool,uint,address)',
2652011374: '(address,bool,string,uint)',
1197235251: '(address,bool,string,string)',
1353532957: '(address,bool,string,bool)',
436029782: '(address,bool,string,address)',
3484780374: '(address,bool,bool,uint)',
3754205928: '(address,bool,bool,string)',
3401856121: '(address,bool,bool,bool)',
3476636805: '(address,bool,bool,address)',
3698398930: '(address,bool,address,uint)',
769095910: '(address,bool,address,string)',
2801077007: '(address,bool,address,bool)',
1711502813: '(address,bool,address,address)',
1425929188: '(address,address,uint,uint)',
2647731885: '(address,address,uint,string)',
3270936812: '(address,address,uint,bool)',
3603321462: '(address,address,uint,address)',
69767936: '(address,address,string,uint)',
566079269: '(address,address,string,string)',
1863997774: '(address,address,string,bool)',
2406706454: '(address,address,string,address)',
2513854225: '(address,address,bool,uint)',
2858762440: '(address,address,bool,string)',
752096074: '(address,address,bool,bool)',
2669396846: '(address,address,bool,address)',
3982404743: '(address,address,address,uint)',
4161329696: '(address,address,address,string)',
238520724: '(address,address,address,bool)',
1717301556: '(address,address,address,address)'
}

@ -1,7 +1,9 @@
import { hexListFromBNs, formatMemory } from '../util'
import { normalizeHexAddress } from '../helpers/uiHelper'
import { ConsoleLogs } from '../helpers/hhconsoleSigs'
import { toChecksumAddress, BN, bufferToHex, Address } from 'ethereumjs-util'
import Web3 from 'web3'
import { ethers } from 'ethers'
export class Web3VmProvider {
web3
@ -9,6 +11,7 @@ export class Web3VmProvider {
vmTraces
txs
txsReceipt
hhLogs
processingHash
processingAddress
processingIndex
@ -41,6 +44,7 @@ export class Web3VmProvider {
this.vmTraces = {}
this.txs = {}
this.txsReceipt = {}
this.hhLogs = {}
this.processingHash = null
this.processingAddress = null
this.processingIndex = null
@ -206,6 +210,29 @@ export class Web3VmProvider {
error: data.error === false ? undefined : data.error
}
this.vmTraces[this.processingHash].structLogs.push(step)
// Track hardhat console.log call
if (step.op === 'STATICCALL' && step.stack[step.stack.length - 2] === '0x000000000000000000000000000000000000000000636f6e736f6c652e6c6f67') {
const stackLength = step.stack.length
const payloadStart = parseInt(step.stack[stackLength - 3], 16)
const memory = step.memory.join('')
let payload = memory.substring(payloadStart * 2, memory.length)
const fnselectorStr = payload.substring(0, 8)
const fnselectorStrInHex = '0x' + fnselectorStr
const fnselector = parseInt(fnselectorStrInHex)
const fnArgs = ConsoleLogs[fnselector]
const iface = new ethers.utils.Interface([`function log${fnArgs} view`])
const functionDesc = iface.getFunction(`log${fnArgs}`)
const sigHash = iface.getSighash(`log${fnArgs}`)
if (fnArgs.includes('uint') && sigHash !== fnselectorStrInHex) {
payload = payload.replace(fnselectorStr, sigHash)
} else {
payload = '0x' + payload
}
const consoleArgs = iface.decodeFunctionData(functionDesc, payload)
this.hhLogs[this.processingHash] = this.hhLogs[this.processingHash] ? this.hhLogs[this.processingHash] : []
this.hhLogs[this.processingHash].push(consoleArgs)
}
if (step.op === 'CREATE' || step.op === 'CALL') {
if (step.op === 'CREATE') {
this.processingAddress = '(Contract Creation - Step ' + this.processingIndex + ')'

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node", "tape"],
"esModuleInterop": true

@ -41,6 +41,7 @@ export class Blocks {
}
const b = {
baseFeePerGas: '0x01',
number: this.toHex(block.header.number),
hash: this.toHex(block.hash()),
parentHash: this.toHex(block.header.parentHash),
@ -73,6 +74,7 @@ export class Blocks {
const block = this.vmContext.blocks[payload.params[0]]
const b = {
baseFeePerGas: '0x01',
number: this.toHex(block.header.number),
hash: this.toHex(block.hash()),
parentHash: this.toHex(block.header.parentHash),

@ -57,6 +57,7 @@ export class Transactions {
eth_getTransactionByBlockHashAndIndex: this.eth_getTransactionByBlockHashAndIndex.bind(this),
eth_getTransactionByBlockNumberAndIndex: this.eth_getTransactionByBlockNumberAndIndex.bind(this),
eth_getExecutionResultFromSimulator: this.eth_getExecutionResultFromSimulator.bind(this),
eth_getHHLogsForTx: this.eth_getHHLogsForTx.bind(this),
eth_getHashFromTagBySimulator: this.eth_getHashFromTagBySimulator.bind(this)
}
}
@ -83,6 +84,11 @@ export class Transactions {
cb(null, this.vmContext.exeResults[txHash])
}
eth_getHHLogsForTx (payload, cb) {
const txHash = payload.params[0]
cb(null, this.vmContext.currentVm.web3vm.hhLogs[txHash] ? this.vmContext.currentVm.web3vm.hhLogs[txHash] : [])
}
eth_getTransactionReceipt (payload, cb) {
this.vmContext.web3().eth.getTransactionReceipt(payload.params[0], (error, receipt) => {
if (error) {
@ -187,6 +193,7 @@ export class Transactions {
blockNumber: '0x' + txBlock.header.number.toString('hex'),
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
chainId: '0xd05',
// 'gasPrice': '2000000000000', // 0x123
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
@ -233,6 +240,7 @@ export class Transactions {
blockNumber: '0x' + txBlock.header.number.toString('hex'),
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
chainId: '0xd05',
// 'gasPrice': '2000000000000', // 0x123
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
@ -276,6 +284,7 @@ export class Transactions {
from: receipt.from,
gas: Web3.utils.toHex(receipt.gas),
// 'gasPrice': '2000000000000', // 0x123
chainId: '0xd05',
gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash,
input: receipt.input,

@ -103,6 +103,15 @@ export function extend (web3) {
}))
}
if (!(web3.eth && web3.eth.getHHLogsForTx)) {
methods.push(new web3.extend.Method({
name: 'getHHLogsForTx',
call: 'eth_getHHLogsForTx',
inputFormatter: [null],
params: 1
}))
}
if (!(web3.eth && web3.eth.getHashFromTagBySimulator)) {
methods.push(new web3.extend.Method({
name: 'getHashFromTagBySimulator',

@ -18,6 +18,7 @@ describe('blocks', () => {
const block = await web3.eth.getBlock(0)
const expectedBlock = {
baseFeePerGas: '0x01',
difficulty: '69762765929000',
extraData: '0x0',
gasLimit: 8000000,

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node", "mocha"],
"esModuleInterop": true

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node"]
},

@ -5,7 +5,7 @@ import { deployAll } from './deployer'
import { runTest } from './testRunner'
import Web3 from 'web3'
import { Provider } from '@remix-project/remix-simulator'
import { Provider, extend } from '@remix-project/remix-simulator'
import {
FinalResult, SrcIfc, compilationInterface, ASTInterface, Options,
TestResultInterface, AstNode, CompilerConfiguration
@ -17,6 +17,7 @@ const createWeb3Provider = async function () {
const provider: any = new Provider()
await provider.init()
web3.setProvider(provider)
extend(web3)
return web3
}
@ -102,7 +103,7 @@ export async function runTestSources (contractSources: SrcIfc, compilerConfig: C
async.eachOfLimit(contractsToTest, 1, (contractName: string, index: string | number, cb: ErrorCallback) => {
const fileAST: AstNode = sourceASTs[contracts[contractName]['filename']]
runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts }, _testCallback, (err, result) => {
runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts, web3 }, _testCallback, (err, result) => {
if (err) {
return cb(err)
}

@ -217,7 +217,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
const isJSONInterfaceAvailable = testObject && testObject.options && testObject.options.jsonInterface
if (!isJSONInterfaceAvailable) { return resultsCallback(new Error('Contract interface not available'), { passingNum, failureNum, timePassed }) }
const runList: RunListInterface[] = createRunList(testObject.options.jsonInterface, fileAST, testName)
const web3 = new Web3()
const web3 = opts.web3 || new Web3()
const accts: TestResultInterface = {
type: 'accountList',
value: opts.accounts
@ -282,8 +282,10 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
}
if (!sendParams) sendParams = {}
sendParams.gas = 10000000 * 8
method.send(sendParams).on('receipt', (receipt) => {
method.send(sendParams).on('receipt', async (receipt) => {
try {
let hhLogs
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(receipt.transactionHash)
const time: number = (Date.now() - startTime) / 1000.0
const assertionEventHashes = assertionEvents.map(e => Web3.utils.sha3(e.name + '(' + e.params.join() + ')'))
let testPassed = false
@ -313,6 +315,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
expected: testEvent[4],
location
}
if (hhLogs) resp.hhLogs = hhLogs
testCallback(undefined, resp)
failureNum += 1
timePassed += time
@ -331,6 +334,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
time: time,
context: testName
}
if (hhLogs) resp.hhLogs = hhLogs
testCallback(undefined, resp)
passingNum += 1
timePassed += time

@ -36,6 +36,7 @@ export interface TestResultInterface {
returned?: string | number
expected?: string | number
location?: string
hhLogs?: []
}
export interface TestCbInterface {
(error: Error | null | undefined, result: TestResultInterface) : void;

@ -1,12 +1,17 @@
import "remix_tests.sol"; // this import is automatically injected by Remix.
import "./hardhat/console.sol";
contract AssertOkTest {
function okPassTest() public {
console.log("AssertOkTest", "okPassTest");
Assert.ok(true, "okPassTest passes");
}
function okFailTest() public {
console.log("AssertOkTest", "okFailTest");
Assert.ok(false, "okFailTest fails");
}
}

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
import * as async from 'async'
import Web3 from 'web3';
import * as assert from 'assert'
import { Provider } from '@remix-project/remix-simulator'
import { Provider, extend } from '@remix-project/remix-simulator'
import { compileFileOrFiles } from '../src/compiler'
import { deployAll } from '../src/deployer'
@ -47,6 +47,7 @@ async function compileAndDeploy(filename: string, callback: Function) {
let sourceASTs: any = {}
await provider.init()
web3.setProvider(provider)
extend(web3)
let compilationData: object
async.waterfall([
function getAccountList(next: Function): void {
@ -72,7 +73,7 @@ async function compileAndDeploy(filename: string, callback: Function) {
}
}
], function (_err: Error | null | undefined, contracts: any): void {
callback(null, compilationData, contracts, sourceASTs, accounts)
callback(null, compilationData, contracts, sourceASTs, accounts, web3)
})
}
@ -106,8 +107,8 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_0/assert_ok_test.sol'
beforeAll((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => {
runTest('AssertOkTest', contracts.AssertOkTest, compilationData[filename]['AssertOkTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertOkTest', contracts.AssertOkTest, compilationData[filename]['AssertOkTest'], asts[filename], { accounts, web3 }, testCallback, resultsCallback(done))
})
})
@ -121,12 +122,14 @@ describe('testRunner', () => {
assert.equal(results.failureNum, 1)
})
const hhLogs1 = [ [ "AssertOkTest", "okPassTest"]]
const hhLogs2 = [ [ "AssertOkTest", "okFailTest"]]
it('should return', () => {
deepEqualExcluding(tests, [
{ type: 'accountList', value: accounts },
{ type: 'contract', value: 'AssertOkTest', filename: __dirname + '/examples_0/assert_ok_test.sol' },
{ type: 'testPass', value: 'Ok pass test', filename: __dirname + '/examples_0/assert_ok_test.sol', context: 'AssertOkTest' },
{ type: 'testFailure', value: 'Ok fail test', filename: __dirname + '/examples_0/assert_ok_test.sol', errMsg: 'okFailTest fails', context: 'AssertOkTest', assertMethod: 'ok', location: '234:36:0', expected: 'true', returned: 'false'},
{ type: 'testPass', value: 'Ok pass test', filename: __dirname + '/examples_0/assert_ok_test.sol', context: 'AssertOkTest', hhLogs: hhLogs1 },
{ type: 'testFailure', value: 'Ok fail test', filename: __dirname + '/examples_0/assert_ok_test.sol', errMsg: 'okFailTest fails', context: 'AssertOkTest', hhLogs: hhLogs2, assertMethod: 'ok', location: '370:36:0', expected: 'true', returned: 'false'},
], ['time'])
})
@ -136,7 +139,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_0/assert_equal_test.sol'
beforeAll((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertEqualTest', contracts.AssertEqualTest, compilationData[filename]['AssertEqualTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -175,7 +178,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_0/assert_notEqual_test.sol'
beforeAll((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertNotEqualTest', contracts.AssertNotEqualTest, compilationData[filename]['AssertNotEqualTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -214,7 +217,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_0/assert_greaterThan_test.sol'
beforeAll((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertGreaterThanTest', contracts.AssertGreaterThanTest, compilationData[filename]['AssertGreaterThanTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -248,7 +251,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_0/assert_lesserThan_test.sol'
beforeAll((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('AssertLesserThanTest', contracts.AssertLesserThanTest, compilationData[filename]['AssertLesserThanTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -283,7 +286,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_1/simple_storage_test.sol'
beforeAll((done) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => {
compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) => {
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -314,7 +317,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_2/simple_storage_test.sol'
beforeAll(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -344,7 +347,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_3/simple_string_test.sol'
beforeAll(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -370,7 +373,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_5/test/simple_storage_test.sol'
beforeAll(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -397,7 +400,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/examples_4/SafeMath_test.sol'
beforeAll(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SafeMathTest', contracts.SafeMathTest, compilationData[filename]['SafeMathTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -417,7 +420,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/number/number_test.sol'
beforeAll(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -437,7 +440,7 @@ describe('testRunner', () => {
const filename: string = __dirname + '/various_sender/sender_and_value_test.sol'
beforeAll(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SenderAndValueTest', contracts.SenderAndValueTest, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
})
})
@ -465,7 +468,7 @@ describe('testRunner', () => {
}
}
beforeAll(done => {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[], web3: any) {
runTest('SenderAndValueTest', undefined, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, errorCallback(done))
})
})

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node", "jest"],
"module": "commonjs",

@ -0,0 +1,35 @@
# remix-ui
This library was generated with [Nx](https://nx.dev).
## Pre-requisite
- Install **NxConsole** vscose extension
## Steps To Generate React App
- Open **NxConsole** extension
- Click generate option
- Select **@nrwl/react - application**
- Enter the name of the application
- Set **e2eTestRunner** to **none**. (This is because we run e2e tests with nightwatch)
- Set **unitTestRunner** to **none**.
- Click the run button in the top right corner of the generate page.
- Your react application should be created in **{root}/apps** directory.
## Steps To Generate React Lib
- Open **NxConsole** extension
- Click generate option
- Select **@nrwl/react - library**
- Enter the name of the library
- Set **directory** to **remix-ui**
- Set **importPath** to **@remix-ui/{library-name}**
- Set **unitTestRunner** to **none**.
- Click the run button in the top right corner of the generate page.
- Your react library should be created on **{root}/libs/remix-ui** directory.
## Steps To Generate React Component
- Open **NxConsole** extension
- Click generate option
- Select **@nrwl/react - component**
- Enter the name of the component
- Select the name of the project/library that uses the component. (e.g TreeView library)
- Set component directory if needed.
- Click the run button in the top right corner of the generate page.
- Your react component should be created with the project/library name specified.

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -15,17 +15,19 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
const debuggerModule = props.debuggerAPI
const [state, setState] = useState({
isActive: false,
statusMessage: '',
debugger: null,
currentReceipt: {
contractAddress: null,
to: null
},
currentBlock: null,
currentTransaction: null,
blockNumber: null,
txNumber: '',
debugging: false,
opt: {
debugWithGeneratedSources: false
debugWithGeneratedSources: false,
debugWithLocalNode: false
},
toastMessage: '',
validationError: '',
@ -132,12 +134,13 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return {
...prevState,
isActive: false,
statusMessage: '',
debugger: null,
currentReceipt: {
contractAddress: null,
to: null
},
currentBlock: null,
currentTransaction: null,
blockNumber: null,
ready: {
vmDebugger: false,
@ -166,7 +169,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return
}
const web3 = await debuggerModule.getDebugWeb3()
const web3 = state.opt.debugWithLocalNode ? await debuggerModule.web3() : await debuggerModule.getDebugWeb3()
try {
const networkId = await web3.eth.net.getId()
_paq.push(['trackEvent', 'debugger', 'startDebugging', networkId])
@ -183,8 +186,12 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
console.error(e)
}
let currentReceipt
let currentBlock
let currentTransaction
try {
currentReceipt = await web3.eth.getTransactionReceipt(txNumber)
currentBlock = await web3.eth.getBlock(currentReceipt.blockHash)
currentTransaction = await web3.eth.getTransaction(txNumber)
} catch (e) {
setState(prevState => {
return {
@ -211,33 +218,33 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
debugWithGeneratedSources: state.opt.debugWithGeneratedSources
})
debuggerInstance.debug(blockNumber, txNumber, tx, () => {
listenToEvents(debuggerInstance, currentReceipt)
setState(prevState => {
return {
...prevState,
blockNumber,
txNumber,
debugging: true,
currentReceipt,
debugger: debuggerInstance,
toastMessage: `debugging ${txNumber}`,
validationError: ''
}
})
}).catch((error) => {
if (JSON.stringify(error) !== '{}') {
let message = 'Error: ' + JSON.stringify(error)
message = message.split('\\"').join('\'')
try {
await debuggerInstance.debug(blockNumber, txNumber, tx, () => {
listenToEvents(debuggerInstance, currentReceipt)
setState(prevState => {
return {
...prevState,
validationError: message
blockNumber,
txNumber,
debugging: true,
currentReceipt,
currentBlock,
currentTransaction,
debugger: debuggerInstance,
toastMessage: `debugging ${txNumber}`,
validationError: ''
}
})
}
})
} catch (error) {
unLoad()
})
setState(prevState => {
return {
...prevState,
validationError: error.message || error
}
})
}
}
const debug = (txHash) => {
@ -277,19 +284,26 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
<div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox">
<input className="custom-control-input" id="debugGeneratedSourcesInput" onChange={({ target: { checked } }) => {
setState(prevState => {
return { ...prevState, opt: { debugWithGeneratedSources: checked } }
return { ...prevState, opt: { ...prevState.opt, debugWithGeneratedSources: checked } }
})
}} type="checkbox" title="Debug with generated sources" />
<label data-id="debugGeneratedSourcesLabel" className="form-check-label custom-control-label" htmlFor="debugGeneratedSourcesInput">Use generated sources (from Solidity v0.7.2)</label>
</div>
<div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox">
<input className="custom-control-input" id="debugWithLocalNodeInput" onChange={({ target: { checked } }) => {
setState(prevState => {
return { ...prevState, opt: { ...prevState.opt, debugWithLocalNode: checked } }
})
}} type="checkbox" title="Force the debugger to use the current local node" />
<label data-id="debugLocaNodeLabel" className="form-check-label custom-control-label" htmlFor="debugWithLocalNodeInput">Force using local node</label>
</div>
{ state.validationError && <span className="w-100 py-1 text-danger validationError">{state.validationError}</span> }
</div>
<TxBrowser requestDebug={ requestDebug } unloadRequested={ unloadRequested } updateTxNumberFlag={ updateTxNumberFlag } transactionNumber={ state.txNumber } debugging={ state.debugging } />
{ state.debugging && <StepManager stepManager={ stepManager } /> }
{ state.debugging && <VmDebuggerHead vmDebugger={ vmDebugger } /> }
</div>
{ state.debugging && <div className="statusMessage">{ state.statusMessage }</div> }
{ state.debugging && <VmDebugger vmDebugger={ vmDebugger } /> }
{ state.debugging && <VmDebugger vmDebugger={ vmDebugger } currentBlock={ state.currentBlock } currentReceipt={ state.currentReceipt } currentTransaction={ state.currentTransaction } /> }
</div>
)
}

@ -62,6 +62,7 @@ export interface IDebuggerApi {
fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise<CompilationOutput>
getFile: (path: string) => Promise<string>
setFile: (path: string, content: string) => Promise<void>
getDebugWeb3: () => any // returns an instance of web3.js
getDebugWeb3: () => any // returns an instance of web3.js, if applicable (mainet, goerli, ...) it returns a reference to a node from devops (so we are sure debug endpoint is available)
web3: () => any // returns an instance of web3.js
showMessage (title: string, message: string): void
}

@ -0,0 +1,27 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
import { BN } from 'ethereumjs-util'
export const GlobalVariables = ({ block, receipt, tx }) => {
// see https://docs.soliditylang.org/en/latest/units-and-global-variables.html#block-and-transaction-properties
const globals = {
'block.basefee': (new BN(block.baseFeePerGas.replace('0x', ''), 'hex')).toString(10) + ` Wei (${block.baseFeePerGas})`,
'block.chainid': tx.chainId,
'block.coinbase': block.miner,
'block.difficulty': block.difficulty,
'block.gaslimit': block.gasLimit,
'block.number': block.number,
'block.timestamp': block.timestamp,
'msg.sender': tx.from,
'msg.sig': tx.input.substring(0, 10),
'msg.value': tx.value + ' Wei',
'tx.origin': tx.from
}
return (
<div id='globalvariable' data-id='globalvariable'>
<DropdownPanel hexHighlight={false} bodyStyle={{ fontFamily: 'monospace' }} dropdownName='Global Variables' calldata={globals || {}} />
</div>
)
}
export default GlobalVariables

@ -15,6 +15,7 @@ export const VmDebuggerHead = ({ vmDebugger: { registerEvent, triggerEvent } })
'remaining gas': '-',
'loaded address': '-'
})
const [solidityState, setSolidityState] = useState({
calldata: null,
message: null

@ -6,8 +6,9 @@ import StackPanel from './stack-panel' // eslint-disable-line
import StoragePanel from './storage-panel' // eslint-disable-line
import ReturnValuesPanel from './dropdown-panel' // eslint-disable-line
import FullStoragesChangesPanel from './full-storages-changes' // eslint-disable-line
import GlobalVariables from './global-variables' // eslint-disable-line
export const VmDebugger = ({ vmDebugger: { registerEvent } }) => {
export const VmDebugger = ({ vmDebugger: { registerEvent }, currentBlock, currentReceipt, currentTransaction }) => {
const [calldataPanel, setCalldataPanel] = useState(null)
const [memoryPanel, setMemoryPanel] = useState(null)
const [callStackPanel, setCallStackPanel] = useState(null)
@ -58,6 +59,7 @@ export const VmDebugger = ({ vmDebugger: { registerEvent } }) => {
<StoragePanel calldata={storagePanel.calldata} header={storagePanel.header} />
<CallstackPanel calldata={callStackPanel} />
<CalldataPanel calldata={calldataPanel} />
<GlobalVariables block={currentBlock} receipt={currentReceipt} tx={currentTransaction} />
<ReturnValuesPanel dropdownName='Return Value' calldata={returnValuesPanel || {}} />
<FullStoragesChangesPanel calldata={fullStoragesChangesPanel} />
</div>

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -5,7 +5,7 @@ import { publishToIPFS } from './publishToIPFS'
import { publishToSwarm } from './publishOnSwarm'
export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
const { storage, fileProvider, fileManager, contract, resetStorage } = props
const { api, storage, contract, resetStorage } = props
const [state, setState] = useState({
modal: {
title: '',
@ -25,11 +25,11 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
} else {
if (storage === 'swarm') {
try {
const result = await publishToSwarm(contract, fileManager)
const result = await publishToSwarm(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond)
fileProvider.addExternal('swarm/' + result.item.hash, result.item.content)
api.addExternalFile('swarm/' + result.item.hash, result.item.content)
} catch (err) {
let parseError = err
try {
@ -39,11 +39,11 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
}
} else {
try {
const result = await publishToIPFS(contract, fileManager)
const result = await publishToIPFS(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond)
fileProvider.addExternal('ipfs/' + result.item.hash, result.item.content)
api.addExternalFile('ipfs/' + result.item.hash, result.item.content)
} catch (err) {
modal('IPFS Publish Failed', publishMessageFailed(storage, err))
}

@ -2,7 +2,7 @@ import swarm from 'swarmgw'
const swarmgw = swarm()
export const publishToSwarm = async (contract, fileManager) => {
export const publishToSwarm = async (contract, api) => {
// gather list of files to publish
const sources = []
let metadata
@ -38,16 +38,14 @@ export const publishToSwarm = async (contract, fileManager) => {
throw new Error('Error while extracting the hash from metadata.json')
}
fileManager.fileProviderOf(fileName).get(fileName, (error, content) => {
if (error) {
console.log(error)
} else {
sources.push({
content: content,
hash: hash,
filename: fileName
})
}
api.readFile(fileName).then((content) => {
sources.push({
content: content,
hash: hash,
filename: fileName
})
}).catch((error) => {
console.log(error)
})
}))
// publish the list of sources in order, fail if any failed

@ -6,7 +6,7 @@ const ipfsNodes = [
new IpfsClient({ host: '127.0.0.1', port: 5001, protocol: 'http' })
]
export const publishToIPFS = async (contract, fileManager) => {
export const publishToIPFS = async (contract, api) => {
// gather list of files to publish
const sources = []
let metadata
@ -42,16 +42,14 @@ export const publishToIPFS = async (contract, fileManager) => {
throw new Error('Error while extracting the hash from metadata.json')
}
fileManager.fileProviderOf(fileName).get(fileName, (error, content) => {
if (error) {
console.log(error)
} else {
sources.push({
content: content,
hash: hash,
filename: fileName
})
}
api.readFile(fileName).then((content) => {
sources.push({
content: content,
hash: hash,
filename: fileName
})
}).catch((error) => {
console.log(error)
})
}))
// publish the list of sources in order, fail if any failed

@ -1,7 +1,6 @@
export interface RemixUiPublishToStorageProps {
api: any,
storage: string,
fileProvider: any,
fileManager: any,
contract: any,
resetStorage: () => void
}

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -4,12 +4,9 @@ interface RendererProps {
message: any;
opt?: any,
plugin: any,
editor: any,
config: any,
fileManager: any
}
export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugin }: RendererProps) => {
export const Renderer = ({ message, opt = {}, plugin }: RendererProps) => {
const [messageText, setMessageText] = useState(null)
const [editorOptions, setEditorOptions] = useState({
useSpan: false,
@ -57,7 +54,7 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi
setMessageText(text)
setEditorOptions(options)
setClose(false)
}, [message])
}, [message, opt])
const getPositionDetails = (msg: any) => {
const result = { } as Record<string, number | string>
@ -77,7 +74,7 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi
}
const addAnnotation = (file, error) => {
if (file === config.get('currentFile')) {
if (file === plugin.getConfiguration('currentFile')) {
plugin.call('editor', 'addAnnotation', error, file)
}
}
@ -95,19 +92,19 @@ export const Renderer = ({ message, opt = {}, editor, config, fileManager, plugi
}
const _errorClick = (errFile, errLine, errCol) => {
if (errFile !== config.get('currentFile')) {
if (errFile !== plugin.getConfiguration('currentFile')) {
// TODO: refactor with this._components.contextView.jumpTo
const provider = fileManager.fileProviderOf(errFile)
const provider = plugin.fileProviderOf(errFile)
if (provider) {
provider.exists(errFile).then(() => {
fileManager.open(errFile)
editor.gotoLine(errLine, errCol)
plugin.open(errFile)
plugin.call('editor', 'gotoLine', errLine, errCol)
}).catch(error => {
if (error) return console.log(error)
})
}
} else {
editor.gotoLine(errLine, errCol)
plugin.call('editor', 'gotoLine', errLine, errCol)
}
}

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -26,8 +26,8 @@ export const resetCompilerMode = () => (dispatch: React.Dispatch<any>) => {
})
}
export const listenToEvents = (editor, compileTabLogic) => (dispatch: React.Dispatch<any>) => {
editor.event.register('sessionSwitched', () => {
export const listenToEvents = (compileTabLogic, api) => (dispatch: React.Dispatch<any>) => {
api.on('editor', 'sessionSwitched', () => {
dispatch(setEditorMode('sessionSwitched'))
})
@ -39,7 +39,7 @@ export const listenToEvents = (editor, compileTabLogic) => (dispatch: React.Disp
dispatch(setCompilerMode('compilationDuration', speed))
})
editor.event.register('contentChanged', () => {
api.on('editor', 'contentChanged', () => {
dispatch(setEditorMode('contentChanged'))
})

@ -18,7 +18,7 @@ declare global {
const _paq = window._paq = window._paq || [] //eslint-disable-line
export const CompilerContainer = (props: CompilerContainerProps) => {
const { editor, config, queryParams, compileTabLogic, tooltip, modal, compiledFileName, setHardHatCompilation, updateCurrentVersion, isHardHatProject, configurationSettings } = props // eslint-disable-line
const { api, compileTabLogic, tooltip, modal, compiledFileName, updateCurrentVersion, configurationSettings } = props // eslint-disable-line
const [state, setState] = useState({
hideWarnings: false,
autoCompile: false,
@ -28,7 +28,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
allversions: [],
customVersions: [],
selectedVersion: null,
defaultVersion: 'soljson-v0.8.4+commit.c7e474f2.js', // this default version is defined: in makeMockCompiler (for browser test)
defaultVersion: 'soljson-v0.8.7+commit.e28d00a7.js', // this default version is defined: in makeMockCompiler (for browser test)
selectedLanguage: '',
runs: '',
compiledFileName: '',
@ -56,26 +56,26 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
_updateVersionSelector(selectedVersion)
}
})
const currentFileName = config.get('currentFile')
const currentFileName = api.getConfiguration('currentFile')
currentFile(currentFileName)
listenToEvents(editor, compileTabLogic)(dispatch)
listenToEvents(compileTabLogic, api)(dispatch)
}, [])
useEffect(() => {
if (compileTabLogic && compileTabLogic.compiler) {
setState(prevState => {
const params = queryParams.get()
const params = api.getParameters()
const optimize = params.optimize === 'false' ? false : params.optimize === 'true' ? true : null
const runs = params.runs
const evmVersion = params.evmVersion
return {
...prevState,
hideWarnings: config.get('hideWarnings') || false,
autoCompile: config.get('autoCompile') || false,
includeNightlies: config.get('includeNightlies') || false,
optimise: (optimize !== null) && (optimize !== undefined) ? optimize : config.get('optimise') || false,
hideWarnings: api.getConfiguration('hideWarnings') || false,
autoCompile: api.getConfiguration('autoCompile') || false,
includeNightlies: api.getConfiguration('includeNightlies') || false,
optimise: (optimize !== null) && (optimize !== undefined) ? optimize : api.getConfiguration('optimise') || false,
runs: (runs !== null) && (runs !== 'null') && (runs !== undefined) && (runs !== 'undefined') ? runs : 200,
evmVersion: (evmVersion !== null) && (evmVersion !== 'null') && (evmVersion !== undefined) && (evmVersion !== 'undefined') ? evmVersion : 'default'
}
@ -152,7 +152,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
allVersions = [...allVersions, ...versions]
selectedVersion = state.defaultVersion
if (queryParams.get().version) selectedVersion = queryParams.get().version
if (api.getParameters().version) selectedVersion = api.getParameters().version
// Check if version is a URL and corresponding filename starts with 'soljson'
if (selectedVersion.startsWith('https://')) {
const urlArr = selectedVersion.split('/')
@ -197,7 +197,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
// Load solc compiler version according to pragma in contract file
const _setCompilerVersionFromPragma = (filename: string) => {
if (!state.allversions) return
compileTabLogic.fileManager.readFile(filename).then(data => {
api.readFile(filename).then(data => {
const pragmaArr = data.match(/(pragma solidity (.+?);)/g)
if (pragmaArr && pragmaArr.length === 1) {
const pragmaStr = pragmaArr[0].replace('pragma solidity', '').trim()
@ -228,7 +228,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}
const isSolFileSelected = (currentFile = '') => {
if (!currentFile) currentFile = config.get('currentFile')
if (!currentFile) currentFile = api.getConfiguration('currentFile')
if (!currentFile) return false
const extention = currentFile.substr(currentFile.length - 3, currentFile.length)
return extention.toLowerCase() === 'sol' || extention.toLowerCase() === 'yul'
@ -297,7 +297,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}
const compile = () => {
const currentFile = config.get('currentFile')
const currentFile = api.getConfiguration('currentFile')
if (!isSolFileSelected()) return
@ -321,7 +321,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
})
}
updateCurrentVersion(selectedVersion)
queryParams.update({ version: selectedVersion })
api.setParameters({ version: selectedVersion })
let url
if (customUrl !== '') {
@ -331,7 +331,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
})
updateCurrentVersion(selectedVersion)
url = customUrl
queryParams.update({ version: selectedVersion })
api.setParameters({ version: selectedVersion })
} else if (selectedVersion === 'builtin') {
let location: string | Location = window.document.location
let path = location.pathname
@ -406,7 +406,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const handleAutoCompile = (e) => {
const checked = e.target.checked
config.set('autoCompile', checked)
api.setConfiguration('autoCompile', checked)
setState(prevState => {
return { ...prevState, autoCompile: checked }
})
@ -415,7 +415,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const handleOptimizeChange = (value) => {
const checked = !!value
config.set('optimise', checked)
api.setConfiguration('optimise', checked)
compileTabLogic.setOptimize(checked)
if (compileTabLogic.optimize) {
compileTabLogic.setRuns(parseInt(state.runs))
@ -441,7 +441,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const handleHideWarningsChange = (e) => {
const checked = e.target.checked
config.set('hideWarnings', checked)
api.setConfiguration('hideWarnings', checked)
state.autoCompile && compile()
setState(prevState => {
return { ...prevState, hideWarnings: checked }
@ -452,7 +452,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const checked = e.target.checked
if (!checked) handleLoadVersion(state.defaultVersion)
config.set('includeNightlies', checked)
api.setConfiguration('includeNightlies', checked)
setState(prevState => {
return { ...prevState, includeNightlies: checked }
})
@ -483,7 +483,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const checked = event.target.checked
sethhCompilation(checked)
setHardHatCompilation(checked)
api.setHardHatCompilation(checked)
}
/*
@ -534,6 +534,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<label className="remixui_compilerLabel form-check-label" htmlFor="evmVersionSelector">EVM Version</label>
<select value={state.evmVersion} onChange={(e) => handleEvmVersionChange(e.target.value)} className="custom-select" id="evmVersionSelector">
<option data-id={state.evmVersion === 'default' ? 'selected' : ''} value="default">compiler default</option>
<option data-id={state.evmVersion === 'london' ? 'selected' : ''} value="london">london</option>
<option data-id={state.evmVersion === 'berlin' ? 'selected' : ''} value="berlin">berlin</option>
<option data-id={state.evmVersion === 'muirGlacier' ? 'selected' : ''} value="muirGlacier">muirGlacier</option>
<option data-id={state.evmVersion === 'istanbul' ? 'selected' : ''} value="istanbul">istanbul</option>
@ -574,7 +575,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
</div>
</div>
{
isHardHatProject &&
api.isHardHatProject &&
<div className="mt-3 remixui_compilerConfig custom-control custom-checkbox">
<input className="remixui_autocompile custom-control-input" onChange={updatehhCompilation} id="enableHardhat" type="checkbox" title="Enable Hardhat Compilation" checked={hhCompilation} />
<label className="form-check-label custom-control-label" htmlFor="enableHardhat">Enable Hardhat Compilation</label>

@ -7,7 +7,7 @@ import { CopyToClipboard } from '@remix-ui/clipboard' // eslint-disable-line
import './css/style.css'
export const ContractSelection = (props: ContractSelectionProps) => {
const { contractMap, fileProvider, fileManager, contractsDetails, modal } = props
const { api, contractMap, contractsDetails, modal } = props
const [contractList, setContractList] = useState([])
const [selectedContract, setSelectedContract] = useState('')
const [storage, setStorage] = useState(null)
@ -203,10 +203,6 @@ export const ContractSelection = (props: ContractSelectionProps) => {
</select>
</div>
<article className="mt-2 pb-0">
<button id="publishOnSwarm" className="btn btn-secondary btn-block" title="Publish on Swarm" onClick={() => { handlePublishToStorage('swarm') }}>
<span>Publish on Swarm</span>
<img id="swarmLogo" className="remixui_storageLogo ml-2" src="assets/img/swarm.webp" />
</button>
<button id="publishOnIpfs" className="btn btn-secondary btn-block" title="Publish on Ipfs" onClick={() => { handlePublishToStorage('ipfs') }}>
<span>Publish on Ipfs</span>
<img id="ipfsLogo" className="remixui_storageLogo ml-2" src="assets/img/ipfs.webp" />
@ -238,7 +234,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
<span className="mt-2 mx-3 w-100 alert alert-warning" role="alert">No Contract Compiled Yet</span>
</article></section>
}
<PublishToStorage storage={storage} fileManager={fileManager} fileProvider={fileProvider} contract={contractsDetails[selectedContract]} resetStorage={resetStorage} />
<PublishToStorage api={api} storage={storage} contract={contractsDetails[selectedContract]} resetStorage={resetStorage} />
</>
)
}

@ -18,46 +18,46 @@ export class CompileTab extends Plugin {
public compilerImport
public event
constructor (public queryParams, public fileManager, public editor, public config, public fileProvider, public contentImport) {
constructor (public api, public contentImport) {
super(profile)
this.event = new EventEmitter()
this.compiler = new Compiler((url, cb) => this.call('contentImport', 'resolveAndSave', url).then((result) => cb(null, result)).catch((error) => cb(error.message)))
}
init () {
this.optimize = this.queryParams.get().optimize
this.optimize = this.api.getParameters().optimize
this.optimize = this.optimize === 'true'
this.queryParams.update({ optimize: this.optimize })
this.api.setParameters({ optimize: this.optimize })
this.compiler.set('optimize', this.optimize)
this.runs = this.queryParams.get().runs
this.runs = this.api.getParameters().runs
this.runs = this.runs && this.runs !== 'undefined' ? this.runs : 200
this.queryParams.update({ runs: this.runs })
this.api.setParameters({ runs: this.runs })
this.compiler.set('runs', this.runs)
this.evmVersion = this.queryParams.get().evmVersion
this.evmVersion = this.api.getParameters().evmVersion
if (this.evmVersion === 'undefined' || this.evmVersion === 'null' || !this.evmVersion) {
this.evmVersion = null
}
this.queryParams.update({ evmVersion: this.evmVersion })
this.api.setParameters({ evmVersion: this.evmVersion })
this.compiler.set('evmVersion', this.evmVersion)
}
setOptimize (newOptimizeValue) {
this.optimize = newOptimizeValue
this.queryParams.update({ optimize: this.optimize })
this.api.setParameters({ optimize: this.optimize })
this.compiler.set('optimize', this.optimize)
}
setRuns (runs) {
this.runs = runs
this.queryParams.update({ runs: this.runs })
this.api.setParameters({ runs: this.runs })
this.compiler.set('runs', this.runs)
}
setEvmVersion (newEvmVersion) {
this.evmVersion = newEvmVersion
this.queryParams.update({ evmVersion: this.evmVersion })
this.api.setParameters({ evmVersion: this.evmVersion })
this.compiler.set('evmVersion', this.evmVersion)
}
@ -79,7 +79,7 @@ export class CompileTab extends Plugin {
*/
compileFile (target) {
if (!target) throw new Error('No target provided for compiliation')
const provider = this.fileManager.fileProviderOf(target)
const provider = this.api.fileProviderOf(target)
if (!provider) throw new Error(`cannot compile ${target}. Does not belong to any explorer`)
return new Promise((resolve, reject) => {
provider.get(target, (error, content) => {
@ -93,14 +93,14 @@ export class CompileTab extends Plugin {
}
async isHardhatProject () {
if (this.fileManager.mode === 'localhost') {
return await this.fileManager.exists('hardhat.config.js')
if (this.api.getFileManagerMode() === 'localhost') {
return await this.api.fileExists('hardhat.config.js')
} else return false
}
runCompiler (hhCompilation) {
try {
if (this.fileManager.mode === 'localhost' && hhCompilation) {
if (this.api.getFileManagerMode() === 'localhost' && hhCompilation) {
const { currentVersion, optimize, runs } = this.compiler.state
if (currentVersion) {
const fileContent = `module.exports = {
@ -114,7 +114,7 @@ export class CompileTab extends Plugin {
}
`
const configFilePath = 'remix-compiler.config.js'
this.fileManager.setFileContent(configFilePath, fileContent)
this.api.writeFile(configFilePath, fileContent)
this.call('hardhat', 'compile', configFilePath).then((result) => {
this.call('terminal', 'log', { type: 'info', value: result })
}).catch((error) => {
@ -122,9 +122,9 @@ export class CompileTab extends Plugin {
})
}
}
this.fileManager.saveCurrentFile()
this.api.saveCurrentFile()
this.event.emit('removeAnnotations')
var currentFile = this.config.get('currentFile')
var currentFile = this.api.getConfiguration('currentFile')
return this.compileFile(currentFile)
} catch (err) {
console.error(err)

@ -9,7 +9,7 @@ import { Renderer } from '@remix-ui/renderer' // eslint-disable-line
import './css/style.css'
export const SolidityCompiler = (props: SolidityCompilerProps) => {
const { plugin, plugin: { editor, config, queryParams, compileTabLogic, currentFile, fileProvider, fileManager, contractsDetails, contractMap, compileErrors, isHardHatProject, setHardHatCompilation, configurationSettings } } = props
const { plugin, plugin: { compileTabLogic, contractsDetails, contractMap, compileErrors, configurationSettings } } = props
const [state, setState] = useState({
contractsDetails: {},
eventHandlers: {},
@ -75,22 +75,23 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
</div>
)
const currentFile = plugin.getConfiguration('currentFile')
return (
<>
<div id="compileTabView">
<CompilerContainer editor={editor} config={config} queryParams={queryParams} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={currentFile} setHardHatCompilation={setHardHatCompilation.bind(plugin)} updateCurrentVersion={updateCurrentVersion} isHardHatProject={isHardHatProject} configurationSettings={configurationSettings} />
<ContractSelection contractMap={contractMap} fileProvider={fileProvider} fileManager={fileManager} contractsDetails={contractsDetails} modal={modal} />
<CompilerContainer api={plugin} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={currentFile} updateCurrentVersion={updateCurrentVersion} configurationSettings={configurationSettings} />
<ContractSelection api={plugin} contractMap={contractMap} contractsDetails={contractsDetails} modal={modal} />
<div className="remixui_errorBlobs p-4" data-id="compiledErrors">
<span data-id={`compilationFinishedWith_${currentVersion}`}></span>
{ compileErrors.error && <Renderer message={compileErrors.error.formattedMessage || compileErrors.error} plugin={plugin} opt={{ type: compileErrors.error.severity || 'error', errorType: compileErrors.error.type }} config={config} editor={editor} fileManager={fileManager} /> }
{ compileErrors.error && <Renderer message={compileErrors.error.formattedMessage || compileErrors.error} plugin={plugin} opt={{ type: compileErrors.error.severity || 'error', errorType: compileErrors.error.type }} /> }
{ compileErrors.error && (compileErrors.error.mode === 'panic') && modal('Error', panicMessage(compileErrors.error.formattedMessage), 'Close', null) }
{ compileErrors.errors && compileErrors.errors.length && compileErrors.errors.map((err, index) => {
if (config.get('hideWarnings')) {
if (plugin.getConfiguration('hideWarnings')) {
if (err.severity !== 'warning') {
return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} config={config} editor={editor} fileManager={fileManager} />
return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} />
}
} else {
return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} config={config} editor={editor} fileManager={fileManager} />
return <Renderer key={index} message={err.formattedMessage} plugin={plugin} opt={{ type: err.severity, errorType: err.type }} />
}
}) }
</div>

@ -4,43 +4,32 @@ export interface SolidityCompilerProps {
file: string
} | Record<string, any>
compileErrors: any,
isHardHatProject: boolean,
queryParams: any,
compileTabLogic: any,
currentFile: string,
contractsDetails: Record<string, any>,
editor: any,
config: any,
fileProvider: any,
fileManager: any,
contentImport: any,
call: (...args) => void
on: (...args) => void,
setHardHatCompilation: (value: boolean) => void,
setSelectedVersion: (value: string) => void,
configurationSettings: ConfigurationSettings
configurationSettings: ConfigurationSettings,
getConfiguration: (value: string) => string,
setConfiguration: (name: string, value: string) => void
},
}
export interface CompilerContainerProps {
editor: any,
config: any,
queryParams: any,
api: any,
compileTabLogic: any,
tooltip: (message: string | JSX.Element) => void,
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void,
compiledFileName: string,
setHardHatCompilation: (value: boolean) => void,
updateCurrentVersion: any,
isHardHatProject: boolean,
configurationSettings: ConfigurationSettings
}
export interface ContractSelectionProps {
api: any,
contractMap: {
file: string
} | Record<string, any>,
fileManager: any,
fileProvider: any,
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void,
contractsDetails: Record<string, any>
}

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -23,7 +23,7 @@
word-break: break-all;
}
.label_key {
min-width: 15%;
min-width: max-content;
max-width: 80%;
word-break: break-word;
}

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node", "mocha"],
"module": "commonjs",

@ -2,7 +2,7 @@
import * as WS from 'ws' // eslint-disable-line
import { PluginClient } from '@remixproject/plugin'
import { existsSync, readFileSync, readdirSync } from 'fs'
import { existsSync, readFileSync, readdirSync, unlink } from 'fs'
import { OutputStandard } from '../types' // eslint-disable-line
const { spawn, execSync } = require('child_process')
@ -114,21 +114,30 @@ export class SlitherClient extends PluginClient {
// Allow paths and set solc remapping for import URLs
const fileContent = readFileSync(`${this.currentSharedFolder}/${filePath}`, 'utf8')
const importsArr = fileContent.match(/import ['"][^.|..](.+?)['"];/g)
let allowPaths = ''; let remaps = ''
let remaps = ''
if (importsArr?.length) {
const { remapString, allowPathString } = this.mapNpmDepsDir(importsArr)
allowPaths = allowPathString
const { remapString } = this.mapNpmDepsDir(importsArr)
remaps = remapString.trim()
}
const allowPathsOption: string = allowPaths ? `--allow-paths ${allowPaths} ` : ''
const optimizeOption: string = optimize ? '--optimize ' : ''
const optimizeOption: string = optimize ? '--optimize' : ''
const evmOption: string = evmVersion ? `--evm-version ${evmVersion}` : ''
const solcArgs: string = optimizeOption || evmOption || allowPathsOption ? `--solc-args '${allowPathsOption}${optimizeOption}${evmOption}'` : ''
let solcArgs = ''
if (optimizeOption) {
solcArgs += optimizeOption + ' '
}
if (evmOption) {
if (!solcArgs.endsWith(' ')) solcArgs += ' '
solcArgs += evmOption
}
if (solcArgs) {
solcArgs = `--solc-args "${solcArgs.trimStart()}"`
}
const solcRemaps = remaps ? `--solc-remaps "${remaps}"` : ''
const outputFile: string = 'remix-slitherReport_' + Math.floor(Date.now() / 1000) + '.json'
const cmd: string = `slither ${filePath} ${solcArgs} ${solcRemaps} --json ${outputFile}`
console.log('\x1b[32m%s\x1b[0m', '[Slither Analysis]: Running Slither...')
console.log(cmd)
// Added `stdio: 'ignore'` as for contract with NPM imports analysis which is exported in 'stderr'
// get too big and hangs the process. We process analysis from the report file only
const child = spawn(cmd, { cwd: this.currentSharedFolder, shell: true, stdio: 'ignore' })
@ -140,6 +149,9 @@ export class SlitherClient extends PluginClient {
if (existsSync(outputFileAbsPath)) {
let report = readFileSync(outputFileAbsPath, 'utf8')
report = JSON.parse(report)
unlink(outputFileAbsPath, (err) => {
if (err) console.log(err)
})
if (report['success']) {
response['status'] = true
if (!report['results'] || !report['results'].detectors || !report['results'].detectors.length) {

@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [

@ -6,8 +6,9 @@
"dependencies": "*",
"devDependencies": "*"
},
"tsconfig.json": "*",
"tsconfig.base.json": "*",
"tslint.json": "*",
".eslintrc": "*",
"nx.json": "*"
},
"tasksRunnerOptions": {

@ -50,7 +50,7 @@
"bumpVersion:libs": "gulp & gulp syncLibVersions;",
"browsertest": "sleep 5 && npm run nightwatch_local",
"csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='apps/remix-ide/src/assets/css/font-awesome.min.css' apps/remix-ide/src/assets/css/",
"downloadsolc_assets": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.4+commit.c7e474f2.js -O ./apps/remix-ide/src/assets/js/soljson.js",
"downloadsolc_assets": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.7+commit.e28d00a7.js -O ./apps/remix-ide/src/assets/js/soljson.js",
"make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js",
"minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false",
"nightwatch_parallel": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js --env=chrome,firefox",

@ -0,0 +1,48 @@
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": ".",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"module": "commonjs",
"typeRoots": ["node_modules/@types"],
"lib": ["es2017", "es2019", "dom"],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"@remix-project/remix-analyzer": ["dist/libs/remix-analyzer/index.js"],
"@remix-project/remix-astwalker": ["dist/libs/remix-astwalker/index.js"],
"@remix-project/remix-debug": ["dist/libs/remix-debug/src/index.js"],
"@remix-project/remix-lib": ["dist/libs/remix-lib/src/index.js"],
"@remix-project/remix-simulator": ["dist/libs/remix-simulator/src/index.js"],
"@remix-project/remix-solidity": ["dist/libs/remix-solidity/index.js"],
"@remix-project/remix-tests": ["dist/libs/remix-tests/src/index.js"],
"@remix-project/remix-url-resolver": ["dist/libs/remix-url-resolver/index.js"],
"@remixproject/debugger-plugin": ["apps/debugger/src/index.ts"],
"@remix-project/remixd": ["dist/libs/remixd/index.js"],
"@remix-ui/tree-view": ["libs/remix-ui/tree-view/src/index.ts"],
"@remix-ui/debugger-ui": ["libs/remix-ui/debugger-ui/src/index.ts"],
"@remix-ui/utils": ["libs/remix-ui/utils/src/index.ts"],
"@remix-ui/clipboard": ["libs/remix-ui/clipboard/src/index.ts"],
"@remix-project/remix-solidity-ts": ["libs/remix-solidity/src/index.ts"],
"@remix-ui/modal-dialog": ["libs/remix-ui/modal-dialog/src/index.ts"],
"@remix-ui/toaster": ["libs/remix-ui/toaster/src/index.ts"],
"@remix-ui/file-explorer": ["libs/remix-ui/file-explorer/src/index.ts"],
"@remix-ui/workspace": ["libs/remix-ui/workspace/src/index.ts"],
"@remix-ui/static-analyser": ["libs/remix-ui/static-analyser/src/index.ts"],
"@remix-ui/checkbox": ["libs/remix-ui/checkbox/src/index.ts"],
"@remix-ui/settings": ["libs/remix-ui/settings/src/index.ts"],
"@remix-project/core-plugin": ["libs/remix-core-plugin/src/index.ts"],
"@remix-ui/solidity-compiler": ["libs/remix-ui/solidity-compiler/src/index.ts"],
"@remix-ui/publish-to-storage": ["libs/remix-ui/publish-to-storage/src/index.ts"],
"@remix-ui/renderer": ["libs/remix-ui/renderer/src/index.ts"]
}
},
"exclude": ["node_modules", "tmp"]
}

@ -10,39 +10,12 @@
"importHelpers": true,
"target": "es2015",
"module": "commonjs",
"typeRoots": ["node_modules/@types"],
"lib": ["es2017", "es2019", "dom"],
"lib": ["es2017", "dom"],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"@remix-project/remix-analyzer": ["dist/libs/remix-analyzer/index.js"],
"@remix-project/remix-astwalker": ["dist/libs/remix-astwalker/index.js"],
"@remix-project/remix-debug": ["dist/libs/remix-debug/src/index.js"],
"@remix-project/remix-lib": ["dist/libs/remix-lib/src/index.js"],
"@remix-project/remix-simulator": ["dist/libs/remix-simulator/src/index.js"],
"@remix-project/remix-solidity": ["dist/libs/remix-solidity/index.js"],
"@remix-project/remix-tests": ["dist/libs/remix-tests/src/index.js"],
"@remix-project/remix-url-resolver": ["dist/libs/remix-url-resolver/index.js"],
"@remixproject/debugger-plugin": ["apps/debugger/src/index.ts"],
"@remix-project/remixd": ["dist/libs/remixd/index.js"],
"@remix-ui/tree-view": ["libs/remix-ui/tree-view/src/index.ts"],
"@remix-ui/debugger-ui": ["libs/remix-ui/debugger-ui/src/index.ts"],
"@remix-ui/utils": ["libs/remix-ui/utils/src/index.ts"],
"@remix-ui/clipboard": ["libs/remix-ui/clipboard/src/index.ts"],
"@remix-project/remix-solidity-ts": ["libs/remix-solidity/src/index.ts"],
"@remix-ui/modal-dialog": ["libs/remix-ui/modal-dialog/src/index.ts"],
"@remix-ui/toaster": ["libs/remix-ui/toaster/src/index.ts"],
"@remix-ui/file-explorer": ["libs/remix-ui/file-explorer/src/index.ts"],
"@remix-ui/workspace": ["libs/remix-ui/workspace/src/index.ts"],
"@remix-ui/static-analyser": ["libs/remix-ui/static-analyser/src/index.ts"],
"@remix-ui/checkbox": ["libs/remix-ui/checkbox/src/index.ts"],
"@remix-ui/settings": ["libs/remix-ui/settings/src/index.ts"],
"@remix-project/core-plugin": ["libs/remix-core-plugin/src/index.ts"],
"@remix-ui/solidity-compiler": ["libs/remix-ui/solidity-compiler/src/index.ts"],
"@remix-ui/publish-to-storage": ["libs/remix-ui/publish-to-storage/src/index.ts"],
"@remix-ui/renderer": ["libs/remix-ui/renderer/src/index.ts"]
}
"paths": {},
"allowSyntheticDefaultImports": true
},
"exclude": ["node_modules", "tmp"]
}

Loading…
Cancel
Save