Merge pull request #1464 from ethereum/new_remix_lib

Adapt to remix lib refactoring
pull/1/head
yann300 6 years ago committed by GitHub
commit ef8e8b54d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      .circleci/config.yml
  2. 2
      .travis.yml
  3. 10
      package.json
  4. 44
      src/app/debugger/debugger.js
  5. 5
      src/app/debugger/remix-debugger/index.html
  6. 6
      src/app/debugger/remix-debugger/index.js
  7. 1
      src/app/debugger/remix-debugger/src/ui/ButtonNavigator.js
  8. 10
      src/app/debugger/remix-debugger/src/ui/CalldataPanel.js
  9. 2
      src/app/debugger/remix-debugger/src/ui/CodeListView.js
  10. 42
      src/app/debugger/remix-debugger/src/ui/Ethdebugger.js
  11. 154
      src/app/debugger/remix-debugger/src/ui/EthdebuggerUI.js
  12. 9
      src/app/debugger/remix-debugger/src/ui/FullStoragesChanges.js
  13. 7
      src/app/debugger/remix-debugger/src/ui/SolidityLocals.js
  14. 7
      src/app/debugger/remix-debugger/src/ui/SolidityState.js
  15. 11
      src/app/debugger/remix-debugger/src/ui/StepDetail.js
  16. 20
      src/app/debugger/remix-debugger/src/ui/StepManager.js
  17. 4
      src/app/debugger/remix-debugger/src/ui/StoragePanel.js
  18. 35
      src/app/debugger/remix-debugger/src/ui/TxBrowser.js
  19. 76
      src/app/debugger/remix-debugger/src/ui/VmDebugger.js
  20. 3
      src/app/debugger/remix-debugger/test-browser-debugger/resources/insertTestWeb3.js
  21. 2
      src/app/staticanalysis/staticAnalysisView.js
  22. 1
      team-best-practices.md
  23. 2
      test-browser-debugger/test/vmdebugger.js

@ -26,13 +26,13 @@ jobs:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- dep-bundle-18-{{ checksum "package.json" }} - dep-bundle-20-{{ checksum "package.json" }}
- run: npm install - run: npm install
- save_cache: - save_cache:
key: dep-bundle-18-{{ checksum "package.json" }} key: dep-bundle-20-{{ checksum "package.json" }}
paths: paths:
- ~/repo/node_modules - ~/repo/node_modules
- run: npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run build - run: npm run lint && npm run test && npm run make-mock-compiler && npm run build
- run: ./ci/browser_tests.sh - run: ./ci/browser_tests.sh
remix-debugger: remix-debugger:
@ -46,10 +46,10 @@ jobs:
- checkout - checkout
- restore_cache: - restore_cache:
keys: keys:
- dep-bundle-13-{{ checksum "package.json" }} - dep-bundle-15-{{ checksum "package.json" }}
- run: npm install - run: npm install
- save_cache: - save_cache:
key: dep-bundle-13-{{ checksum "package.json" }} key: dep-bundle-15-{{ checksum "package.json" }}
paths: paths:
- ~/repo/node_modules - ~/repo/node_modules
- run: npm run build_debugger - run: npm run build_debugger

@ -6,7 +6,7 @@ branches:
- master - master
- remix_live - remix_live
script: script:
- npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run build - npm run lint && npm run test && npm run make-mock-compiler && npm run build
- ./ci/browser_tests.sh - ./ci/browser_tests.sh
deploy: deploy:
- provider: script - provider: script

@ -37,9 +37,10 @@
"npm-link-local": "^1.1.0", "npm-link-local": "^1.1.0",
"npm-run-all": "^4.0.2", "npm-run-all": "^4.0.2",
"onchange": "^3.2.1", "onchange": "^3.2.1",
"remix-core": "0.0.15", "remix-debug": "latest",
"remix-lib": "0.2.9", "remix-analyzer": "latest",
"remix-solidity": "0.1.11", "remix-lib": "latest",
"remix-solidity": "latest",
"remix-tests": "latest", "remix-tests": "latest",
"remixd": "git+https://github.com/ethereum/remixd.git", "remixd": "git+https://github.com/ethereum/remixd.git",
"request": "^2.83.0", "request": "^2.83.0",
@ -145,19 +146,18 @@
"scripts": { "scripts": {
"setupremix": "npm run pullremix && npm run linkremixcore && npm run linkremixlib && npm run linkremixsolidity;", "setupremix": "npm run pullremix && npm run linkremixcore && npm run linkremixlib && npm run linkremixsolidity;",
"pullremix": "git clone https://github.com/ethereum/remix", "pullremix": "git clone https://github.com/ethereum/remix",
"linkremixcore": "cd node_modules && rm -rf remix-core && ln -s ../remix/remix-core remix-core && cd ..",
"linkremixlib": "cd node_modules && rm -rf remix-lib && ln -s ../remix/remix-lib remix-lib && cd ..", "linkremixlib": "cd node_modules && rm -rf remix-lib && ln -s ../remix/remix-lib remix-lib && cd ..",
"linkremixsolidity": "cd node_modules && rm -rf remix-solidity && ln -s ../remix/remix-solidity remix-solidity && cd ..", "linkremixsolidity": "cd node_modules && rm -rf remix-solidity && ln -s ../remix/remix-solidity remix-solidity && cd ..",
"build": "browserify src/index.js -o build/app.js --exclude solc", "build": "browserify src/index.js -o build/app.js --exclude solc",
"build_debugger": "browserify src/app/debugger/remix-debugger/index.js -o src/app/debugger/remix-debugger/build/app.js", "build_debugger": "browserify src/app/debugger/remix-debugger/index.js -o src/app/debugger/remix-debugger/build/app.js",
"browsertest": "sleep 5 && npm run nightwatch_local", "browsertest": "sleep 5 && npm run nightwatch_local",
"csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='assets/css/font-awesome.min.css' assets/css/", "csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='assets/css/font-awesome.min.css' assets/css/",
"downloadsolc": "rimraf soljson.js && cd node_modules/solc && wget --no-check-certificate https://solc-bin.ethereum.org/soljson.js && cd ../../",
"downloadsolc_root": "wget --no-check-certificate https://solc-bin.ethereum.org/soljson.js", "downloadsolc_root": "wget --no-check-certificate https://solc-bin.ethereum.org/soljson.js",
"lint": "standard | notify-error", "lint": "standard | notify-error",
"make-mock-compiler": "node ci/makeMockCompiler.js", "make-mock-compiler": "node ci/makeMockCompiler.js",
"minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false", "minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false",
"nightwatch_local": "nightwatch --config nightwatch.js --env local", "nightwatch_local": "nightwatch --config nightwatch.js --env local",
"nightwatch_local_debugger": "nightwatch --config nightwatch_debugger.js --env local",
"nightwatch_remote_chrome": "nightwatch --config nightwatch.js --env chrome", "nightwatch_remote_chrome": "nightwatch --config nightwatch.js --env chrome",
"nightwatch_remote_firefox": "nightwatch --config nightwatch.js --env default", "nightwatch_remote_firefox": "nightwatch --config nightwatch.js --env default",
"nightwatch_remote_ie": "nightwatch --config nightwatch.js --env ie", "nightwatch_remote_ie": "nightwatch --config nightwatch.js --env ie",

@ -1,8 +1,7 @@
'use strict' 'use strict'
var EthdebuggerUI = require('./remix-debugger/src/ui/EthdebuggerUI')
var Ethdebugger = require('./remix-debugger/src/ui/Ethdebugger') var Ethdebugger = require('remix-debug').EthDebugger
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var remixCore = require('remix-core')
var executionContext = require('../../execution-context') var executionContext = require('../../execution-context')
var globlalRegistry = require('../../global/registry') var globlalRegistry = require('../../global/registry')
@ -22,6 +21,7 @@ function Debugger (container, sourceHighlighter, localRegistry) {
} }
this.debugger = new Ethdebugger( this.debugger = new Ethdebugger(
{ {
executionContext: executionContext,
compilationResult: () => { compilationResult: () => {
var compilationResult = this._deps.compiler.lastCompilationResult var compilationResult = this._deps.compiler.lastCompilationResult
if (compilationResult) { if (compilationResult) {
@ -30,17 +30,21 @@ function Debugger (container, sourceHighlighter, localRegistry) {
return null return null
} }
}) })
this.debugger_ui = new EthdebuggerUI({debugger: this.debugger})
this.sourceMappingDecoder = new remixLib.SourceMappingDecoder() this.sourceMappingDecoder = new remixLib.SourceMappingDecoder()
container.appendChild(this.debugger.render()) //
// TODO: render doesn't exist anymore
container.appendChild(this.debugger_ui.render())
//
this.isActive = false this.isActive = false
this.breakPointManager = new remixCore.code.BreakpointManager(this.debugger, (sourceLocation) => { this.breakPointManager = new remixLib.code.BreakpointManager(this.debugger, (sourceLocation) => {
return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, this._deps.compiler.lastCompilationResult.source.sources) return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, this._deps.compiler.lastCompilationResult.source.sources)
}, (step) => {
this.debugger_ui.stepManager.jumpTo(step)
}) })
this.debugger.setBreakpointManager(this.breakPointManager) this.debugger.setBreakpointManager(this.breakPointManager)
this.breakPointManager.event.register('breakpointHit', (sourceLocation) => {
})
var self = this var self = this
self._deps.editor.event.register('breakpointCleared', (fileName, row) => { self._deps.editor.event.register('breakpointCleared', (fileName, row) => {
@ -70,15 +74,18 @@ function Debugger (container, sourceHighlighter, localRegistry) {
}) })
// register selected code item, highlight the corresponding source location // register selected code item, highlight the corresponding source location
this.debugger.codeManager.event.register('changed', this, function (code, address, index) { this.debugger_ui.event.register('indexChanged', function (index) {
if (self._deps.compiler.lastCompilationResult) { if (self._deps.compiler.lastCompilationResult) {
self.debugger.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, index, self._deps.compiler.lastCompilationResult.data.contracts, function (error, rawLocation) { self.debugger.traceManager.getCurrentCalledAddressAt(index, (error, address) => {
if (!error && self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) { if (error) return console.log(error)
var lineColumnPos = self._deps.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, self._deps.compiler.lastCompilationResult.source.sources) self.debugger.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, index, self._deps.compiler.lastCompilationResult.data.contracts, function (error, rawLocation) {
self._components.sourceHighlighter.currentSourceLocation(lineColumnPos, rawLocation) if (!error && self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) {
} else { var lineColumnPos = self._deps.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, self._deps.compiler.lastCompilationResult.source.sources)
self._components.sourceHighlighter.currentSourceLocation(null) self._components.sourceHighlighter.currentSourceLocation(lineColumnPos, rawLocation)
} } else {
self._components.sourceHighlighter.currentSourceLocation(null)
}
})
}) })
} }
}) })
@ -91,9 +98,10 @@ function Debugger (container, sourceHighlighter, localRegistry) {
*/ */
Debugger.prototype.debug = function (txHash) { Debugger.prototype.debug = function (txHash) {
var self = this var self = this
this.debugger.web3().eth.getTransaction(txHash, function (error, tx) {
this.debugger.web3.eth.getTransaction(txHash, function (error, tx) {
if (!error) { if (!error) {
self.debugger.debug(tx) self.debugger_ui.debug(tx)
} }
}) })
} }
@ -121,7 +129,7 @@ Debugger.prototype.switchProvider = function (type) {
* get the current provider * get the current provider
*/ */
Debugger.prototype.web3 = function (type) { Debugger.prototype.web3 = function (type) {
return this.debugger.web3() return this.debugger.web3
} }
module.exports = Debugger module.exports = Debugger

@ -7,9 +7,8 @@
<script type="text/javascript"> <script type="text/javascript">
function loadDebugger() { function loadDebugger() {
var container = document.getElementById('app') var container = document.getElementById('app')
container.debugger = new window.remix.ui.Debugger() var debuggerBackend = new window.remix.ui.DebuggerBackend({})
container.debugger.addProvider('INTERNAL') container.debugger = new window.remix.ui.Debugger({debugger: debuggerBackend})
container.debugger.switchProvider('INTERNAL')
container.appendChild(container.debugger.render()) container.appendChild(container.debugger.render())
} }
</script> </script>

@ -1,6 +1,7 @@
'use strict' 'use strict'
var VMDebugger = require('./src/ui/VmDebugger') var VMDebugger = require('./src/ui/VmDebugger')
var Debugger = require('./src/ui/Ethdebugger') var Debugger = require('./src/ui/EthdebuggerUI')
var DebuggerBackend = require('remix-debug').EthDebugger
if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') { if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') {
module.exports = modules() module.exports = modules()
@ -14,7 +15,8 @@ function modules () {
return { return {
ui: { ui: {
Debugger: Debugger, Debugger: Debugger,
VMdebugger: VMDebugger VMdebugger: VMDebugger,
DebuggerBackend
} }
} }
} }

@ -51,6 +51,7 @@ function ButtonNavigator (_parent, _traceManager) {
this.revertionPoint = null this.revertionPoint = null
_parent.event.register('indexChanged', this, (index) => { _parent.event.register('indexChanged', this, (index) => {
if (!this.view) return
if (index < 0) return if (index < 0) return
if (_parent.currentStepIndex !== index) return if (_parent.currentStepIndex !== index) return

@ -2,8 +2,8 @@
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var yo = require('yo-yo') var yo = require('yo-yo')
function CalldataPanel (_parent, _traceManager) { function CalldataPanel (_parentUI, _traceManager) {
this.parent = _parent this._parentUI = _parentUI
this.traceManager = _traceManager this.traceManager = _traceManager
this.basicPanel = new DropdownPanel('Call Data', {json: true}) this.basicPanel = new DropdownPanel('Call Data', {json: true})
this.init() this.init()
@ -15,15 +15,15 @@ CalldataPanel.prototype.render = function () {
CalldataPanel.prototype.init = function () { CalldataPanel.prototype.init = function () {
var self = this var self = this
this.parent.event.register('indexChanged', this, function (index) { this._parentUI.event.register('indexChanged', this, function (index) {
if (index < 0) return if (index < 0) return
if (self.parent.currentStepIndex !== index) return if (self._parentUI.currentStepIndex !== index) return
self.traceManager.getCallDataAt(index, function (error, calldata) { self.traceManager.getCallDataAt(index, function (error, calldata) {
if (error) { if (error) {
self.basicPanel.update({}) self.basicPanel.update({})
console.log(error) console.log(error)
} else if (self.parent.currentStepIndex === index) { } else if (self._parentUI.currentStepIndex === index) {
self.basicPanel.update(calldata) self.basicPanel.update(calldata)
} }
}) })

@ -12,7 +12,7 @@ var css = csjs`
.instructions { .instructions {
${styles.rightPanel.debuggerTab.box_Debugger} ${styles.rightPanel.debuggerTab.box_Debugger}
overflow-y: scroll; overflow-y: scroll;
max-height: 100px; max-height: 150px;
} }
` `
function CodeListView (_parent, _codeManager) { function CodeListView (_parent, _codeManager) {

@ -1,11 +1,9 @@
'use strict' 'use strict'
var TxBrowser = require('./TxBrowser') var TxBrowser = require('./TxBrowser')
var StepManager = require('./StepManager') var StepManager = require('./StepManager')
var remixCore = require('remix-core')
var TraceManager = remixCore.trace.TraceManager
var VmDebugger = require('./VmDebugger')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var global = remixLib.global var TraceManager = remixLib.trace.TraceManager
var VmDebugger = require('./VmDebugger')
var init = remixLib.init var init = remixLib.init
var executionContext = remixLib.execution.executionContext var executionContext = remixLib.execution.executionContext
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
@ -13,10 +11,10 @@ var yo = require('yo-yo')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var Web3Providers = remixLib.vm.Web3Providers var Web3Providers = remixLib.vm.Web3Providers
var DummyProvider = remixLib.vm.DummyProvider var DummyProvider = remixLib.vm.DummyProvider
var CodeManager = remixCore.code.CodeManager var CodeManager = remixLib.code.CodeManager
var remixSolidity = require('remix-solidity') var remixDebug = require('remix-debug')
var SolidityProxy = remixSolidity.SolidityProxy var SolidityProxy = remixDebug.SolidityDecoder.SolidityProxy
var InternalCallTree = remixSolidity.InternalCallTree var InternalCallTree = remixDebug.SolidityDecoder.InternalCallTree
var css = csjs` var css = csjs`
.statusMessage { .statusMessage {
@ -59,6 +57,8 @@ function Ethdebugger (opts) {
self.unLoad() self.unLoad()
}) })
this.txBrowser.event.register('newTraceRequested', this, function (blockNumber, txIndex, tx) { this.txBrowser.event.register('newTraceRequested', this, function (blockNumber, txIndex, tx) {
console.dir('newTraceRequestd')
console.dir(arguments)
self.startDebugging(blockNumber, txIndex, tx) self.startDebugging(blockNumber, txIndex, tx)
}) })
this.txBrowser.event.register('unloadRequested', this, function (blockNumber, txIndex, tx) { this.txBrowser.event.register('unloadRequested', this, function (blockNumber, txIndex, tx) {
@ -79,6 +79,18 @@ function Ethdebugger (opts) {
}) })
} }
Ethdebugger.prototype.setManagers = function () {
this.traceManager = new TraceManager({web3: this.web3})
this.codeManager = new CodeManager(this.traceManager)
this.solidityProxy = new SolidityProxy(this.traceManager, this.codeManager)
this.storageResolver = null
var callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true })
this.callTree = callTree // TODO: currently used by browser solidity, we should improve the API
this.vmDebugger = new VmDebugger(this, this.traceManager, this.codeManager, this.solidityProxy, callTree)
this.callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true })
}
Ethdebugger.prototype.setBreakpointManager = function (breakpointManager) { Ethdebugger.prototype.setBreakpointManager = function (breakpointManager) {
this.breakpointManager = breakpointManager this.breakpointManager = breakpointManager
} }
@ -92,13 +104,20 @@ Ethdebugger.prototype.addProvider = function (type, obj) {
this.event.trigger('providerAdded', [type]) this.event.trigger('providerAdded', [type])
} }
Ethdebugger.prototype.updateWeb3Reference = function () {
if (!this.txBrowser) return
this.txBrowser.web3 = this.web3
}
Ethdebugger.prototype.switchProvider = function (type) { Ethdebugger.prototype.switchProvider = function (type) {
var self = this var self = this
this.web3Providers.get(type, function (error, obj) { this.web3Providers.get(type, function (error, obj) {
if (error) { if (error) {
console.log('provider ' + type + ' not defined') console.log('provider ' + type + ' not defined')
} else { } else {
global.web3 = obj self.web3 = obj
self.setManagers()
self.updateWeb3Reference()
executionContext.detectNetwork((error, network) => { executionContext.detectNetwork((error, network) => {
if (error || !network) { if (error || !network) {
global.web3Debug = obj global.web3Debug = obj
@ -106,6 +125,7 @@ Ethdebugger.prototype.switchProvider = function (type) {
var webDebugNode = init.web3DebugNode(network.name) var webDebugNode = init.web3DebugNode(network.name)
global.web3Debug = !webDebugNode ? obj : webDebugNode global.web3Debug = !webDebugNode ? obj : webDebugNode
} }
self.updateWeb3Reference()
}) })
self.event.trigger('providerChanged', [type]) self.event.trigger('providerChanged', [type])
} }
@ -158,6 +178,8 @@ Ethdebugger.prototype.stepChanged = function (stepIndex) {
} }
Ethdebugger.prototype.startDebugging = function (blockNumber, txIndex, tx) { Ethdebugger.prototype.startDebugging = function (blockNumber, txIndex, tx) {
console.dir('startDebugging')
console.dir(arguments)
if (this.traceManager.isLoading) { if (this.traceManager.isLoading) {
return return
} }
@ -167,6 +189,8 @@ Ethdebugger.prototype.startDebugging = function (blockNumber, txIndex, tx) {
console.log('loading trace...') console.log('loading trace...')
this.tx = tx this.tx = tx
var self = this var self = this
console.dir('resolving a trace with tx: ')
console.dir(tx)
this.traceManager.resolveTrace(tx, function (error, result) { this.traceManager.resolveTrace(tx, function (error, result) {
console.log('trace loaded ' + result) console.log('trace loaded ' + result)
if (result) { if (result) {

@ -0,0 +1,154 @@
'use strict'
var TxBrowser = require('./TxBrowser')
var StepManager = require('./StepManager')
var VmDebugger = require('./VmDebugger')
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var remixLib = require('remix-lib')
var executionContext = remixLib.execution.executionContext
var EventManager = remixLib.EventManager
var css = csjs`
.statusMessage {
margin-left: 15px;
}
.innerShift {
padding: 2px;
margin-left: 10px;
}
`
function EthdebuggerUI (opts) {
this.opts = opts || {}
this.debugger = opts.debugger
if (!this.opts.compilationResult) this.opts.compilationResult = () => { return null }
var self = this
this.event = new EventManager()
this.currentStepIndex = -1
this.tx
this.statusMessage = ''
this.view
this.event.register('indexChanged', this, function (index) {
self.debugger.codeManager.resolveStep(index, self.tx)
})
executionContext.event.register('contextChanged', this, function () {
self.updateWeb3Reference()
})
this.txBrowser = new TxBrowser(this, {displayConnectionSetting: false, web3: executionContext.web3()})
this.txBrowser.event.register('newTxLoading', this, function () {
self.unLoad()
})
this.txBrowser.event.register('newTraceRequested', this, function (blockNumber, txIndex, tx) {
self.startDebugging(blockNumber, txIndex, tx)
})
this.txBrowser.event.register('unloadRequested', this, function (blockNumber, txIndex, tx) {
self.unLoad()
})
}
EthdebuggerUI.prototype.setBreakpointManager = function (breakpointManager) {
this.breakpointManager = breakpointManager
}
EthdebuggerUI.prototype.get_web3 = function () {
return this.web3
}
EthdebuggerUI.prototype.updateWeb3Reference = function (web3) {
if (!this.txBrowser) return
this.txBrowser.web3 = web3 || executionContext.web3()
}
EthdebuggerUI.prototype.setCompilationResult = function (compilationResult) {
if (compilationResult && compilationResult.sources && compilationResult.contracts) {
this.debugger.solidityProxy.reset(compilationResult)
} else {
this.debugger.solidityProxy.reset({})
}
}
EthdebuggerUI.prototype.debug = function (tx) {
this.setCompilationResult(this.opts.compilationResult())
if (tx instanceof Object) {
this.txBrowser.load(tx.hash, tx)
} else if (tx instanceof String) {
this.txBrowser.load(tx)
}
}
EthdebuggerUI.prototype.render = function () {
this.debuggerPanelsView = yo`<div class="${css.innerShift}"></div>`
this.debuggerHeadPanelsView = yo`<div class="${css.innerShift}"></div>`
this.stepManagerView = yo`<div class="${css.innerShift}"></div>`
var view = yo`<div>
<div class="${css.innerShift}">
${this.txBrowser.render()}
${this.debuggerHeadPanelsView}
${this.stepManagerView}
</div>
<div class="${css.statusMessage}" >${this.statusMessage}</div>
${this.debuggerPanelsView}
</div>`
if (!this.view) {
this.view = view
}
return view
}
EthdebuggerUI.prototype.unLoad = function () {
this.debugger.unLoad()
yo.update(this.debuggerHeadPanelsView, yo`<div></div>`)
yo.update(this.debuggerPanelsView, yo`<div></div>`)
yo.update(this.stepManagerView, yo`<div></div>`)
if (this.vmDebugger) this.vmDebugger.remove()
if (this.stepManager) this.stepManager.remove()
this.vmDebugger = null
this.stepManager = null
this.event.trigger('traceUnloaded')
}
EthdebuggerUI.prototype.stepChanged = function (stepIndex) {
this.currentStepIndex = stepIndex
this.event.trigger('indexChanged', [stepIndex])
}
EthdebuggerUI.prototype.startDebugging = function (blockNumber, txIndex, tx) {
const self = this
if (this.debugger.traceManager.isLoading) {
return
}
this.tx = tx
this.stepManager = new StepManager(this, this.debugger.traceManager)
this.stepManager.event.register('stepChanged', this, function (stepIndex) {
self.stepChanged(stepIndex)
})
this.debugger.codeManager.event.register('changed', this, (code, address, instIndex) => {
self.debugger.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, this.currentStepIndex, this.debugger.solidityProxy.contracts, (error, sourceLocation) => {
if (!error) {
self.event.trigger('sourceLocationChanged', [sourceLocation])
}
})
})
this.vmDebugger = new VmDebugger(this, this.debugger.traceManager, this.debugger.codeManager, this.debugger.solidityProxy, this.debugger.callTree)
yo.update(this.debuggerHeadPanelsView, this.vmDebugger.renderHead())
yo.update(this.debuggerPanelsView, this.vmDebugger.render())
yo.update(this.stepManagerView, this.stepManager.render())
this.debugger.debug(tx)
}
module.exports = EthdebuggerUI

@ -1,12 +1,13 @@
'use strict' 'use strict'
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var remixCore = require('remix-core') var remixDebug = require('remix-debug')
var StorageViewer = remixCore.storage.StorageViewer var StorageViewer = remixDebug.storage.StorageViewer
var yo = require('yo-yo') var yo = require('yo-yo')
function FullStoragesChanges (_parent, _traceManager) { function FullStoragesChanges (_parent, _traceManager) {
this.storageResolver = null this.storageResolver = null
this.parent = _parent this.parent = _parent
this.debugger = _parent.debugger
this.traceManager = _traceManager this.traceManager = _traceManager
this.addresses = [] this.addresses = []
this.view this.view
@ -25,7 +26,7 @@ FullStoragesChanges.prototype.render = function () {
FullStoragesChanges.prototype.init = function () { FullStoragesChanges.prototype.init = function () {
var self = this var self = this
this.parent.event.register('newTraceLoaded', this, function (length) { this.debugger.event.register('newTraceLoaded', this, function (length) {
self.panels = [] self.panels = []
self.traceManager.getAddresses(function (error, addresses) { self.traceManager.getAddresses(function (error, addresses) {
if (!error) { if (!error) {
@ -41,7 +42,7 @@ FullStoragesChanges.prototype.init = function () {
}) })
}) })
this.parent.event.register('indexChanged', this, function (index) { this.debugger.event.register('indexChanged', this, function (index) {
if (index < 0) return if (index < 0) return
if (self.parent.currentStepIndex !== index) return if (self.parent.currentStepIndex !== index) return
if (!self.storageResolver) return if (!self.storageResolver) return

@ -1,10 +1,9 @@
'use strict' 'use strict'
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var remixSolidity = require('remix-solidity') var remixDebug = require('remix-debug')
var localDecoder = remixSolidity.localDecoder var localDecoder = remixDebug.SolidityDecoder.localDecoder
var solidityTypeFormatter = require('./SolidityTypeFormatter') var solidityTypeFormatter = require('./SolidityTypeFormatter')
var remixCore = require('remix-core') var StorageViewer = remixDebug.storage.StorageViewer
var StorageViewer = remixCore.storage.StorageViewer
var yo = require('yo-yo') var yo = require('yo-yo')
class SolidityLocals { class SolidityLocals {

@ -1,10 +1,9 @@
'use strict' 'use strict'
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var remixSolidity = require('remix-solidity') var remixDebug = require('remix-debug')
var stateDecoder = remixSolidity.stateDecoder var stateDecoder = remixDebug.SolidityDecoder.stateDecoder
var solidityTypeFormatter = require('./SolidityTypeFormatter') var solidityTypeFormatter = require('./SolidityTypeFormatter')
var remixCore = require('remix-core') var StorageViewer = remixDebug.storage.StorageViewer
var StorageViewer = remixCore.storage.StorageViewer
var yo = require('yo-yo') var yo = require('yo-yo')
function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) { function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) {

@ -2,8 +2,9 @@
var yo = require('yo-yo') var yo = require('yo-yo')
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
function StepDetail (_parent, _traceManager) { function StepDetail (_parentUI, _traceManager) {
this.parent = _parent this.debugger = _parentUI.debugger
this.parentUI = _parentUI
this.traceManager = _traceManager this.traceManager = _traceManager
this.basicPanel = new DropdownPanel('Step detail', {json: true, displayContentOnly: true}) this.basicPanel = new DropdownPanel('Step detail', {json: true, displayContentOnly: true})
@ -19,17 +20,17 @@ StepDetail.prototype.render = function () {
StepDetail.prototype.init = function () { StepDetail.prototype.init = function () {
var self = this var self = this
this.parent.event.register('traceUnloaded', this, function () { this.debugger.event.register('traceUnloaded', this, function () {
self.detail = initDetail() self.detail = initDetail()
self.basicPanel.update(self.detail) self.basicPanel.update(self.detail)
}) })
this.parent.event.register('newTraceLoaded', this, function () { this.debugger.event.register('newTraceLoaded', this, function () {
self.detail = initDetail() self.detail = initDetail()
self.basicPanel.update(self.detail) self.basicPanel.update(self.detail)
}) })
this.parent.event.register('indexChanged', this, function (index) { this.parentUI.event.register('indexChanged', this, function (index) {
if (index < 0) return if (index < 0) return
self.detail['vm trace step'] = index self.detail['vm trace step'] = index

@ -8,13 +8,14 @@ var util = remixLib.util
function StepManager (_parent, _traceManager) { function StepManager (_parent, _traceManager) {
this.event = new EventManager() this.event = new EventManager()
this.parent = _parent this.parent = _parent.debugger
this.traceManager = _traceManager this.traceManager = _traceManager
this.sourceMapByAddress = {} this.sourceMapByAddress = {}
this.solidityMode = false this.solidityMode = false
var self = this var self = this
this.parent.event.register('newTraceLoaded', this, function () { this.parent.event.register('newTraceLoaded', this, function () {
if (!this.slider) return
self.traceManager.getLength(function (error, length) { self.traceManager.getLength(function (error, length) {
if (error) { if (error) {
console.log(error) console.log(error)
@ -33,6 +34,7 @@ function StepManager (_parent, _traceManager) {
}) })
this.parent.callTree.event.register('callTreeReady', () => { this.parent.callTree.event.register('callTreeReady', () => {
if (!this.slider) return
if (this.parent.callTree.functionCallStack.length) { if (this.parent.callTree.functionCallStack.length) {
this.jumpTo(this.parent.callTree.functionCallStack[0]) this.jumpTo(this.parent.callTree.functionCallStack[0])
} }
@ -58,13 +60,21 @@ function StepManager (_parent, _traceManager) {
self.jumpTo(exceptionIndex) self.jumpTo(exceptionIndex)
}) })
this.buttonNavigator.event.register('jumpNextBreakpoint', (exceptionIndex) => { this.buttonNavigator.event.register('jumpNextBreakpoint', (exceptionIndex) => {
self.parent.breakpointManager.jumpNextBreakpoint(this.parent.currentStepIndex, true) self.parent.breakpointManager.jumpNextBreakpoint(_parent.currentStepIndex, true)
}) })
this.buttonNavigator.event.register('jumpPreviousBreakpoint', (exceptionIndex) => { this.buttonNavigator.event.register('jumpPreviousBreakpoint', (exceptionIndex) => {
self.parent.breakpointManager.jumpPreviousBreakpoint(this.parent.currentStepIndex, true) self.parent.breakpointManager.jumpPreviousBreakpoint(_parent.currentStepIndex, true)
}) })
} }
StepManager.prototype.remove = function () {
// used to stop listenning on event. bad and should be "refactored"
this.slider.view = null
this.slider = null
this.buttonNavigator.view = null
this.buttonNavigator = null
}
StepManager.prototype.resolveToReducedTrace = function (value, incr) { StepManager.prototype.resolveToReducedTrace = function (value, incr) {
if (this.parent.callTree.reducedTrace.length) { if (this.parent.callTree.reducedTrace.length) {
var nextSource = util.findClosestIndex(value, this.parent.callTree.reducedTrace) var nextSource = util.findClosestIndex(value, this.parent.callTree.reducedTrace)
@ -80,12 +90,10 @@ StepManager.prototype.resolveToReducedTrace = function (value, incr) {
} }
StepManager.prototype.render = function () { StepManager.prototype.render = function () {
return ( return yo`<div>
yo`<div>
${this.slider.render()} ${this.slider.render()}
${this.buttonNavigator.render()} ${this.buttonNavigator.render()}
</div>` </div>`
)
} }
StepManager.prototype.reset = function () { StepManager.prototype.reset = function () {

@ -1,7 +1,7 @@
'use strict' 'use strict'
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var remixCore = require('remix-core') var remixDebug = require('remix-debug')
var StorageViewer = remixCore.storage.StorageViewer var StorageViewer = remixDebug.storage.StorageViewer
var yo = require('yo-yo') var yo = require('yo-yo')
function StoragePanel (_parent, _traceManager) { function StoragePanel (_parent, _traceManager) {

@ -1,5 +1,4 @@
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var global = remixLib.global
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
var traceHelper = remixLib.helpers.trace var traceHelper = remixLib.helpers.trace
var yo = require('yo-yo') var yo = require('yo-yo')
@ -24,8 +23,8 @@ var css = csjs`
} }
.txinput { .txinput {
${styles.rightPanel.debuggerTab.input_Debugger} ${styles.rightPanel.debuggerTab.input_Debugger}
min-width: 30px;
margin: 3px; margin: 3px;
width: inherit;
} }
.txbuttons { .txbuttons {
width: 100%; width: 100%;
@ -34,6 +33,10 @@ var css = csjs`
} }
.txbutton { .txbutton {
${styles.rightPanel.debuggerTab.button_Debugger} ${styles.rightPanel.debuggerTab.button_Debugger}
width: inherit;
}
.txbuttonstart {
${styles.rightPanel.debuggerTab.button_Debugger}
} }
.txbutton:hover { .txbutton:hover {
color: ${styles.rightPanel.debuggerTab.button_Debugger_icon_HoverColor}; color: ${styles.rightPanel.debuggerTab.button_Debugger_icon_HoverColor};
@ -43,16 +46,16 @@ var css = csjs`
margin-bottom: 10px; margin-bottom: 10px;
} }
` `
function TxBrowser (_parent) { function TxBrowser (_parent, opts) {
this.event = new EventManager() this.event = new EventManager()
this.blockNumber this.blockNumber
this.txNumber this.txNumber
this.view this.view
this.displayConnectionSetting = true this.displayConnectionSetting = opts.displayConnectionSetting
this.web3 = opts.web3
var self = this var self = this
_parent.event.register('providerChanged', this, function (provider) { _parent.event.register('providerChanged', this, function (provider) {
self.displayConnectionSetting = provider === 'INTERNAL'
self.setDefaultValues() self.setDefaultValues()
if (self.view) { if (self.view) {
yo.update(self.view, self.render()) yo.update(self.view, self.render())
@ -73,19 +76,23 @@ TxBrowser.prototype.setDefaultValues = function () {
} }
} }
TxBrowser.prototype.submit = function () { TxBrowser.prototype.submit = function (tx) {
var self = this
self.event.trigger('newTxLoading', [this.blockNumber, this.txNumber])
if (tx) {
return self.update(null, tx)
}
if (!this.txNumber) { if (!this.txNumber) {
self.update('no tx index or tx hash to look for')
return return
} }
this.event.trigger('newTxLoading', [this.blockNumber, this.txNumber])
try { try {
var self = this
if (this.txNumber.indexOf('0x') !== -1) { if (this.txNumber.indexOf('0x') !== -1) {
global.web3.eth.getTransaction(this.txNumber, function (error, result) { self.web3.eth.getTransaction(this.txNumber, function (error, result) {
self.update(error, result) self.update(error, result)
}) })
} else { } else {
global.web3.eth.getTransactionFromBlock(this.blockNumber, this.txNumber, function (error, result) { self.web3.eth.getTransactionFromBlock(this.blockNumber, this.txNumber, function (error, result) {
self.update(error, result) self.update(error, result)
}) })
} }
@ -150,9 +157,9 @@ TxBrowser.prototype.updateTxN = function (ev) {
this.txNumber = ev.target.value this.txNumber = ev.target.value
} }
TxBrowser.prototype.load = function (txHash) { TxBrowser.prototype.load = function (txHash, tx) {
this.txNumber = txHash this.txNumber = txHash
this.submit() this.submit(tx)
} }
TxBrowser.prototype.unload = function (txHash) { TxBrowser.prototype.unload = function (txHash) {
@ -184,8 +191,8 @@ TxBrowser.prototype.render = function () {
<input class="${css.txinput}" id='txinput' onkeyup=${function () { self.updateTxN(arguments[0]) }} type='text' placeholder=${'Transaction index or hash'} /> <input class="${css.txinput}" id='txinput' onkeyup=${function () { self.updateTxN(arguments[0]) }} type='text' placeholder=${'Transaction index or hash'} />
</div> </div>
<div class="${css.txbuttons}"> <div class="${css.txbuttons}">
<button id='load' class='fa fa-play ${css.txbutton}' title='start debugging' onclick=${function () { self.submit() }}></button> <button id='load' class='${css.txbutton}' title='start debugging' onclick=${function () { self.submit() }}>Start debugging</button>
<button id='unload' class='fa fa-stop ${css.txbutton}' title='stop debugging' onclick=${function () { self.unload() }}></button> <button id='unload' class='${css.txbutton}' title='stop debugging' onclick=${function () { self.unload() }}>Stop</button>
</div> </div>
</div> </div>
<span id='error'></span> <span id='error'></span>

@ -11,79 +11,82 @@ var StepDetail = require('./StepDetail')
var DropdownPanel = require('./DropdownPanel') var DropdownPanel = require('./DropdownPanel')
var SolidityState = require('./SolidityState') var SolidityState = require('./SolidityState')
var SolidityLocals = require('./SolidityLocals') var SolidityLocals = require('./SolidityLocals')
var remixCore = require('remix-core') var remixDebug = require('remix-debug')
var StorageResolver = remixCore.storage.StorageResolver var StorageResolver = remixDebug.storage.StorageResolver
var yo = require('yo-yo') var yo = require('yo-yo')
var css = csjs` var css = csjs`
.asmCode { .asmCode {
float: left; float: left;
width: 250px; width: 50%;
} }
.stepDetail { .stepDetail {
float: right; }
.vmheadView {
margin-top:10px;
} }
` `
function VmDebugger (_parent, _traceManager, _codeManager, _solidityProxy, _callTree) { function VmDebugger (_parentUI, _traceManager, _codeManager, _solidityProxy, _callTree) {
let _parent = _parentUI.debugger
var self = this
this.view
this.asmCode = new CodeListView(_parent, _codeManager) this.asmCode = new CodeListView(_parent, _codeManager)
this.stackPanel = new StackPanel(_parent, _traceManager) this.stackPanel = new StackPanel(_parentUI, _traceManager)
this.storagePanel = new StoragePanel(_parent, _traceManager) this.storagePanel = new StoragePanel(_parentUI, _traceManager)
this.memoryPanel = new MemoryPanel(_parent, _traceManager) this.memoryPanel = new MemoryPanel(_parentUI, _traceManager)
this.calldataPanel = new CalldataPanel(_parent, _traceManager) this.calldataPanel = new CalldataPanel(_parentUI, _traceManager)
this.callstackPanel = new CallstackPanel(_parent, _traceManager) this.callstackPanel = new CallstackPanel(_parentUI, _traceManager)
this.stepDetail = new StepDetail(_parent, _traceManager) this.stepDetail = new StepDetail(_parentUI, _traceManager)
this.solidityState = new SolidityState(_parent, _traceManager, _codeManager, _solidityProxy) this.solidityState = new SolidityState(_parentUI, _traceManager, _codeManager, _solidityProxy)
this.solidityLocals = new SolidityLocals(_parent, _traceManager, _callTree) this.solidityLocals = new SolidityLocals(_parentUI, _traceManager, _callTree)
/* Return values - */ /* Return values - */
this.returnValuesPanel = new DropdownPanel('Return Value', {json: true}) this.returnValuesPanel = new DropdownPanel('Return Value', {json: true})
this.returnValuesPanel.data = {} this.returnValuesPanel.data = {}
_parent.event.register('indexChanged', this.returnValuesPanel, function (index) { _parentUI.event.register('indexChanged', this.returnValuesPanel, function (index) {
var self = this if (!self.view) return
var innerself = this
_traceManager.getReturnValue(index, function (error, returnValue) { _traceManager.getReturnValue(index, function (error, returnValue) {
if (error) { if (error) {
self.update([error]) innerself.update([error])
} else if (_parent.currentStepIndex === index) { } else if (_parentUI.currentStepIndex === index) {
self.update([returnValue]) innerself.update([returnValue])
} }
}) })
}) })
/* Return values - */ /* Return values - */
this.fullStoragesChangesPanel = new FullStoragesChangesPanel(_parent, _traceManager) this.fullStoragesChangesPanel = new FullStoragesChangesPanel(_parentUI, _traceManager)
this.view
var self = this
_parent.event.register('newTraceLoaded', this, function () { _parent.event.register('newTraceLoaded', this, function () {
var storageResolver = new StorageResolver() if (!self.view) return
var storageResolver = new StorageResolver({web3: _parent.web3})
self.storagePanel.storageResolver = storageResolver self.storagePanel.storageResolver = storageResolver
self.solidityState.storageResolver = storageResolver self.solidityState.storageResolver = storageResolver
self.solidityLocals.storageResolver = storageResolver self.solidityLocals.storageResolver = storageResolver
self.fullStoragesChangesPanel.storageResolver = storageResolver self.fullStoragesChangesPanel.storageResolver = storageResolver
self.headView.style.display = 'block' self.asmCode.basicPanel.show()
self.view.style.display = 'block' self.stackPanel.basicPanel.show()
self.storagePanel.basicPanel.show()
self.memoryPanel.basicPanel.show()
self.calldataPanel.basicPanel.show()
self.callstackPanel.basicPanel.show()
}) })
_parent.event.register('traceUnloaded', this, function () { _parent.event.register('traceUnloaded', this, function () {
self.headView.style.display = 'none' if (!self.view) return
self.view.style.display = 'none'
}) })
_parent.callTree.event.register('callTreeReady', () => { _parent.callTree.event.register('callTreeReady', () => {
self.asmCode.basicPanel.show() if (!self.view) return
if (_parent.callTree.reducedTrace.length) { if (_parent.callTree.reducedTrace.length) {
self.solidityLocals.basicPanel.show() self.solidityLocals.basicPanel.show()
self.solidityState.basicPanel.show() self.solidityState.basicPanel.show()
} }
self.stackPanel.basicPanel.show()
self.storagePanel.basicPanel.show()
self.memoryPanel.basicPanel.show()
self.calldataPanel.basicPanel.show()
self.callstackPanel.basicPanel.show()
}) })
} }
VmDebugger.prototype.renderHead = function () { VmDebugger.prototype.renderHead = function () {
var headView = yo`<div id='vmheadView' style='display:none'> var headView = yo`<div id='vmheadView' class=${css.vmheadView}>
<div> <div>
<div class=${css.asmCode}>${this.asmCode.render()}</div> <div class=${css.asmCode}>${this.asmCode.render()}</div>
<div class=${css.stepDetail}>${this.stepDetail.render()}</div> <div class=${css.stepDetail}>${this.stepDetail.render()}</div>
@ -95,8 +98,13 @@ VmDebugger.prototype.renderHead = function () {
return headView return headView
} }
VmDebugger.prototype.remove = function () {
// used to stop listenning on event. bad and should be "refactored"
this.view = null
}
VmDebugger.prototype.render = function () { VmDebugger.prototype.render = function () {
var view = yo`<div id='vmdebugger' style='display:none'> var view = yo`<div id='vmdebugger'>
<div> <div>
${this.solidityLocals.render()} ${this.solidityLocals.render()}
${this.solidityState.render()} ${this.solidityState.render()}

@ -13,7 +13,7 @@ function loadJSON (url, callback) {
function loadTestWeb3 (data) { function loadTestWeb3 (data) {
var container = document.getElementById('app') var container = document.getElementById('app')
var vmdebugger = container.debugger var vmdebugger = container.debugger.debugger
var uiTestweb3 = {} var uiTestweb3 = {}
uiTestweb3.eth = {} uiTestweb3.eth = {}
uiTestweb3.debug = {} uiTestweb3.debug = {}
@ -58,6 +58,7 @@ function loadTestWeb3 (data) {
uiTestweb3.currentProvider = {host: 'web3 modified for testing purposes :)'} uiTestweb3.currentProvider = {host: 'web3 modified for testing purposes :)'}
vmdebugger.addProvider('TEST', uiTestweb3) vmdebugger.addProvider('TEST', uiTestweb3)
vmdebugger.switchProvider('TEST') vmdebugger.switchProvider('TEST')
container.debugger.updateWeb3Reference(uiTestweb3)
} }
function waitForRemix (data) { function waitForRemix (data) {

@ -1,5 +1,5 @@
'use strict' 'use strict'
var StaticAnalysisRunner = require('remix-solidity').CodeAnalysis var StaticAnalysisRunner = require('remix-analyzer').CodeAnalysis
var yo = require('yo-yo') var yo = require('yo-yo')
var $ = require('jquery') var $ = require('jquery')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')

@ -16,7 +16,6 @@ Related links:
- Remix live: remix.ethereum.org - Remix live: remix.ethereum.org
- Remix alpha live: remix-alpha.ethereum.org - Remix alpha live: remix-alpha.ethereum.org
- Remix-ide NPM module: https://www.npmjs.com/package/remix-ide - Remix-ide NPM module: https://www.npmjs.com/package/remix-ide
- Remix-core NPM module: https://www.npmjs.com/package/remix-core
- Remix-lib NPM module: https://www.npmjs.com/package/remix-lib - Remix-lib NPM module: https://www.npmjs.com/package/remix-lib
- Remix-solidity NPM module: https://www.npmjs.com/package/remix-solidity - Remix-solidity NPM module: https://www.npmjs.com/package/remix-solidity
- Remix-debug NPM module: https://www.npmjs.com/package/remix-debug - Remix-debug NPM module: https://www.npmjs.com/package/remix-debug

@ -54,7 +54,7 @@ function panels (browser) {
.click('#load') .click('#load')
.multipleClick('#intoforward', 63) .multipleClick('#intoforward', 63)
.assertStack(['0:0x00', '1:0x60', '2:0x65', '3:0x38', '4:0x55', '5:0x60fe47b1']) .assertStack(['0:0x00', '1:0x60', '2:0x65', '3:0x38', '4:0x55', '5:0x60fe47b1'])
.assertStorageChanges(['0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563:Objectkey:0x00value:0x38']) .assertStorageChanges(['0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563:Object'])
.assertCallData(['0:0x60fe47b10000000000000000000000000000000000000000000000000000000000000038']) .assertCallData(['0:0x60fe47b10000000000000000000000000000000000000000000000000000000000000038'])
.assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5']) .assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5'])
.assertStackValue(1, '1:0x60') .assertStackValue(1, '1:0x60')

Loading…
Cancel
Save