diff --git a/src/app/debugger/debuggerUI/VmDebugger.js b/src/app/debugger/debuggerUI/VmDebugger.js
index aaf777f848..ca32a31073 100644
--- a/src/app/debugger/debuggerUI/VmDebugger.js
+++ b/src/app/debugger/debuggerUI/VmDebugger.js
@@ -7,10 +7,10 @@ var CallstackPanel = require('./vmDebugger/CallstackPanel')
var StackPanel = require('./vmDebugger/StackPanel')
var StoragePanel = require('./vmDebugger/StoragePanel')
var StepDetail = require('./vmDebugger/StepDetail')
+var SolidityState = require('./vmDebugger/SolidityState')
+var SolidityLocals = require('../remix-debugger/src/ui/SolidityLocals')
var FullStoragesChangesPanel = require('../remix-debugger/src/ui/FullStoragesChanges')
var DropdownPanel = require('../remix-debugger/src/ui/DropdownPanel')
-var SolidityState = require('../remix-debugger/src/ui/SolidityState')
-var SolidityLocals = require('../remix-debugger/src/ui/SolidityLocals')
var remixDebug = require('remix-debug')
var remixLib = require('remix-lib')
var ui = remixLib.helpers.ui
diff --git a/src/app/debugger/debuggerUI/vmDebugger/SolidityState.js b/src/app/debugger/debuggerUI/vmDebugger/SolidityState.js
new file mode 100644
index 0000000000..74dcba9548
--- /dev/null
+++ b/src/app/debugger/debuggerUI/vmDebugger/SolidityState.js
@@ -0,0 +1,103 @@
+var DropdownPanel = require('./DropdownPanel')
+var remixDebug = require('remix-debug')
+var stateDecoder = remixDebug.SolidityDecoder.stateDecoder
+var solidityTypeFormatter = require('./utils/SolidityTypeFormatter')
+var StorageViewer = remixDebug.storage.StorageViewer
+var yo = require('yo-yo')
+
+function SolidityState (_parent, _traceManager, _codeManager, _solidityProxy) {
+ this.storageResolver = null
+ this.parent = _parent
+ this.traceManager = _traceManager
+ this.codeManager = _codeManager
+ this.solidityProxy = _solidityProxy
+ this.basicPanel = new DropdownPanel('Solidity State', {
+ json: true,
+ formatSelf: solidityTypeFormatter.formatSelf,
+ extractData: solidityTypeFormatter.extractData
+ })
+ this.init()
+ this.view
+ this.stateVariablesByAddresses = {}
+ _parent.event.register('traceUnloaded', () => { this.stateVariablesByAddresses = {} })
+ _parent.event.register('newTraceLoaded', () => { this.stateVariablesByAddresses = {} })
+}
+
+SolidityState.prototype.render = function () {
+ if (!this.view) {
+ this.view = yo`
+ ${this.basicPanel.render()}
+
`
+ }
+ return this.view
+}
+
+SolidityState.prototype.init = function () {
+ var self = this
+ var decodeTimeout = null
+ this.parent.event.register('indexChanged', this, function (index) {
+ if (index < 0) {
+ self.basicPanel.setMessage('invalid step index')
+ return
+ }
+
+ if (self.parent.currentStepIndex !== index) return
+ if (!self.solidityProxy.loaded()) {
+ self.basicPanel.setMessage('no source has been specified')
+ return
+ }
+
+ if (!self.storageResolver) {
+ return
+ }
+ if (decodeTimeout) {
+ window.clearTimeout(decodeTimeout)
+ }
+ self.basicPanel.setUpdating()
+ decodeTimeout = setTimeout(() => {
+ decode(self, index)
+ }, 500)
+ })
+}
+
+function decode (self, index) {
+ self.traceManager.getCurrentCalledAddressAt(self.parent.currentStepIndex, (error, address) => {
+ if (error) {
+ self.basicPanel.update({})
+ console.log(error)
+ } else {
+ if (self.stateVariablesByAddresses[address]) {
+ extractStateVariables(self, self.stateVariablesByAddresses[address], address)
+ } else {
+ self.solidityProxy.extractStateVariablesAt(index, function (error, stateVars) {
+ if (error) {
+ self.basicPanel.update({})
+ console.log(error)
+ } else {
+ self.stateVariablesByAddresses[address] = stateVars
+ extractStateVariables(self, stateVars, address)
+ }
+ })
+ }
+ }
+ })
+}
+
+function extractStateVariables (self, stateVars, address) {
+ var storageViewer = new StorageViewer({
+ stepIndex: self.parent.currentStepIndex,
+ tx: self.parent.tx,
+ address: address
+ }, self.storageResolver, self.traceManager)
+ stateDecoder.decodeState(stateVars, storageViewer).then((result) => {
+ self.basicPanel.setMessage('')
+ if (!result.error) {
+ self.basicPanel.update(result)
+ } else {
+ self.basicPanel.setMessage(result.error)
+ }
+ })
+}
+
+module.exports = SolidityState
+
diff --git a/src/app/debugger/debuggerUI/vmDebugger/utils/SolidityTypeFormatter.js b/src/app/debugger/debuggerUI/vmDebugger/utils/SolidityTypeFormatter.js
new file mode 100644
index 0000000000..f24a939098
--- /dev/null
+++ b/src/app/debugger/debuggerUI/vmDebugger/utils/SolidityTypeFormatter.js
@@ -0,0 +1,71 @@
+var yo = require('yo-yo')
+var BN = require('ethereumjs-util').BN
+
+module.exports = {
+ formatSelf: formatSelf,
+ extractData: extractData
+}
+
+function formatSelf (key, data) {
+ var style = fontColor(data)
+ var keyStyle = data.isProperty ? 'color:#847979' : ''
+ if (data.type === 'string') {
+ data.self = JSON.stringify(data.self)
+ }
+ return yo``
+}
+
+function extractData (item, parent, key) {
+ var ret = {}
+ if (item.isProperty) {
+ return item
+ }
+ if (item.type.lastIndexOf(']') === item.type.length - 1) {
+ ret.children = (item.value || []).map(function (item, index) {
+ return {key: index, value: item}
+ })
+ ret.children.unshift({
+ key: 'length',
+ value: {
+ self: (new BN(item.length.replace('0x', ''), 16)).toString(10),
+ type: 'uint',
+ isProperty: true
+ }
+ })
+ ret.isArray = true
+ ret.self = parent.isArray ? '' : item.type
+ } else if (item.type.indexOf('struct') === 0) {
+ ret.children = Object.keys((item.value || {})).map(function (key) {
+ return {key: key, value: item.value[key]}
+ })
+ ret.self = item.type
+ ret.isStruct = true
+ } else if (item.type.indexOf('mapping') === 0) {
+ ret.children = Object.keys((item.value || {})).map(function (key) {
+ return {key: key, value: item.value[key]}
+ })
+ ret.isMapping = true
+ ret.self = item.type
+ } else {
+ ret.children = null
+ ret.self = item.value
+ ret.type = item.type
+ }
+ return ret
+}
+
+function fontColor (data) {
+ var color = '#124B46'
+ if (data.isArray || data.isStruct || data.isMapping) {
+ color = '#847979'
+ } else if (data.type.indexOf('uint') === 0 ||
+ data.type.indexOf('int') === 0 ||
+ data.type.indexOf('bool') === 0 ||
+ data.type.indexOf('enum') === 0) {
+ color = '#0F0CE9'
+ } else if (data.type === 'string') {
+ color = '#E91E0C'
+ }
+ return 'color:' + color
+}
+