diff --git a/assets/css/universal-dapp.css b/assets/css/universal-dapp.css index 4d4f7c289e..cbbac4683b 100644 --- a/assets/css/universal-dapp.css +++ b/assets/css/universal-dapp.css @@ -200,6 +200,10 @@ width: 25%; } +.udapp .contractProperty button.debug { + width: 3%; +} + .udapp .contractProperty .call { background-color: #FF8B8B; border-color: #FF8B8B; diff --git a/src/app.js b/src/app.js index d19d2e8a0c..0909bbdbee 100644 --- a/src/app.js +++ b/src/app.js @@ -15,6 +15,7 @@ var Compiler = require('./app/compiler'); var ExecutionContext = require('./app/execution-context'); var Debugger = require('./app/debugger'); var FormalVerification = require('./app/formalVerification'); +var EthJSVM = require('ethereumjs-vm'); // The event listener needs to be registered as early as possible, because the // parent will send the message upon the "load" event. @@ -431,13 +432,17 @@ var run = function () { $('#output').append($('
').append($('').text('Loading github.com/' + root + '/' + path + ' ...'))); return $.getJSON('https://api.github.com/repos/' + root + '/contents/' + path, cb); } - - var executionContext = new ExecutionContext(); - var transactionDebugger = new Debugger(executionContext, '#debugger'); + var transactionDebugger = new Debugger('#debugger'); + var vm = new EthJSVM(null, null, { activatePrecompiles: true, enableHomestead: true }); + vm.stateManager.checkpoint(); + transactionDebugger.addProvider('VM', vm); + transactionDebugger.switchProvider('VM'); + var executionContext = new ExecutionContext(transactionDebugger); + transactionDebugger.addProvider('EXTERNAL', executionContext.web3()); transactionDebugger.onDebugRequested = function () { selectTab($('ul#options li.debugView')); }; - var renderer = new Renderer(editor, executionContext, updateFiles, transactionDebugger); + var renderer = new Renderer(editor, executionContext, updateFiles, transactionDebugger, vm); var formalVerification = new FormalVerification($('#verificationView'), renderer); var compiler = new Compiler(editor, renderer, queryParams, handleGithubCall, $('#output'), getHidingRHP, formalVerification, updateFiles); executionContext.setCompiler(compiler); diff --git a/src/app/debugger.js b/src/app/debugger.js index 1b60ecfef1..b44432558a 100644 --- a/src/app/debugger.js +++ b/src/app/debugger.js @@ -1,6 +1,6 @@ var remix = require('ethereum-remix'); -function Debugger (executionContext, id) { +function Debugger (id) { this.el = document.querySelector(id); this.debugger = new remix.ui.Debugger(); this.el.appendChild(this.debugger.render()); diff --git a/src/app/execution-context.js b/src/app/execution-context.js index db67897a80..70591307df 100644 --- a/src/app/execution-context.js +++ b/src/app/execution-context.js @@ -13,7 +13,8 @@ if (typeof window.web3 !== 'undefined') { web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); } -function ExecutionContext () { +function ExecutionContext (_txDebugger) { + var txDebugger = _txDebugger; var compiler; var executionContext = injectedProvider ? 'injected' : 'vm'; @@ -59,8 +60,12 @@ function ExecutionContext () { executionContext = ev.target.value; if (executionContext === 'web3') { setProviderFromEndpoint(); + txDebugger.switchProvider('EXTERNAL'); } else if (executionContext === 'injected') { web3.setProvider(injectedProvider); + txDebugger.switchProvider('EXTERNAL'); + } else if (executionContext === 'vm') { + txDebugger.switchProvider('VM'); } } compiler.compile(); diff --git a/src/app/renderer.js b/src/app/renderer.js index 808a347590..9a6837f271 100644 --- a/src/app/renderer.js +++ b/src/app/renderer.js @@ -4,7 +4,7 @@ var UniversalDApp = require('../universal-dapp.js'); var utils = require('./utils'); -function Renderer (editor, executionContext, updateFiles, transactionDebugger) { +function Renderer (editor, executionContext, updateFiles, transactionDebugger, vm) { var detailsOpen = {}; function renderError (message, container, noAnnotations) { @@ -61,6 +61,9 @@ function Renderer (editor, executionContext, updateFiles, transactionDebugger) { }); } + vm.stateManager.revert(function () { + vm.stateManager.checkpoint(); + }); var dapp = new UniversalDApp(udappContracts, { mode: executionContext.isVM() ? 'vm' : 'web3', web3: executionContext.web3(), @@ -81,7 +84,7 @@ function Renderer (editor, executionContext, updateFiles, transactionDebugger) { .append(textRow('uDApp', combined(contractName, contract['interface'], contract.bytecode), 'deploy')) .append(getDetails(contract, source, contractName)); } - }, transactionDebugger); + }, transactionDebugger, vm); var $contractOutput = dapp.render(); diff --git a/src/universal-dapp.js b/src/universal-dapp.js index 044512495a..b69f2f4488 100644 --- a/src/universal-dapp.js +++ b/src/universal-dapp.js @@ -1,14 +1,13 @@ /* global prompt */ var $ = require('jquery'); -var EthJSVM = require('ethereumjs-vm'); var ethJSUtil = require('ethereumjs-util'); var EthJSTX = require('ethereumjs-tx'); var ethJSABI = require('ethereumjs-abi'); var EthJSBlock = require('ethereumjs-block'); var BN = ethJSUtil.BN; -function UniversalDApp (contracts, options, transactionDebugger) { +function UniversalDApp (contracts, options, transactionDebugger, vm) { var self = this; self.options = options || {}; @@ -18,15 +17,13 @@ function UniversalDApp (contracts, options, transactionDebugger) { self.web3 = options.web3; self.transactionDebugger = transactionDebugger; - transactionDebugger.addProvider('EXTERNAL', self.web3); + if (options.mode === 'vm') { // FIXME: use `options.vm` or `self.vm` consistently options.vm = true; self.accounts = {}; - - self.vm = new EthJSVM(null, null, { activatePrecompiles: true, enableHomestead: true }); - transactionDebugger.addProvider('VM', self.vm); + self.vm = vm; self.addAccount('3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'); self.addAccount('2ac6c190b09897cd8987869cc7b918cfea07ee82038d492abce033c75c1b1d0c'); } else if (options.mode !== 'web3') { @@ -355,7 +352,7 @@ UniversalDApp.prototype.getCallButton = function (args) { var getDebugTransaction = function (result) { var $debugTx = $('