Merge branch 'master' into remixd_terminal

pull/5370/head
David Zagi 3 years ago committed by GitHub
commit 98b8ae61a3
  1. 63
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  2. 1
      libs/remix-debug/package.json
  3. 2
      libs/remix-debug/src/storage/storageResolver.ts
  4. 24
      libs/remix-debug/test/debugger.ts
  5. 19
      libs/remix-debug/test/decoder/localDecoder.ts
  6. 19
      libs/remix-debug/test/decoder/localsTests/calldata.ts
  7. 14
      libs/remix-debug/test/decoder/localsTests/int.ts
  8. 16
      libs/remix-debug/test/decoder/localsTests/misc.ts
  9. 14
      libs/remix-debug/test/decoder/localsTests/misc2.ts
  10. 14
      libs/remix-debug/test/decoder/localsTests/structArray.ts
  11. 34
      libs/remix-debug/test/decoder/stateTests/mapping.ts
  12. 76
      libs/remix-debug/test/decoder/vmCall.ts
  13. 2
      libs/remix-debug/test/tests.ts
  14. 73
      libs/remix-debug/test/vmCall.ts
  15. 25
      libs/remix-lib/src/execution/logsManager.ts
  16. 1
      libs/remix-lib/src/execution/txRunnerVM.ts
  17. 5
      libs/remix-simulator/src/methods/blocks.ts
  18. 32
      libs/remix-simulator/src/methods/transactions.ts
  19. 72
      libs/remix-simulator/src/vm-context.ts

@ -99,6 +99,32 @@ module.exports = {
.executeScript('remix.execute(\'resolveExternalUrlAndSaveToaPath.js\')') .executeScript('remix.execute(\'resolveExternalUrlAndSaveToaPath.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'abstract contract ERC20Burnable', 60000) .waitForElementContainsText('*[data-id="terminalJournal"]', 'abstract contract ERC20Burnable', 60000)
.openFile('.deps/github/newFile.sol') .openFile('.deps/github/newFile.sol')
},
'Deploy "Owner" using an ether.js script, listen to event and check event are logged in the terminal': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('settings')
.clickLaunchIcon('udapp')
.click('*[data-id="settingsVMLondonMode"]')
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.clickLaunchIcon('filePanel')
.click('*[data-id="treeViewDivtreeViewItem"]') // make sure we create the file at the root folder
.addFile('deployWithEthersJs.js', { content: deployWithEthersJs })
.openFile('deployWithEthersJs.js')
.pause(1000)
.openFile('contracts/2_Owner.sol')
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]') // compile Owner
.executeScript('remix.execute(\'deployWithEthersJs.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Contract Address: 0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deployment successful.', 60000)
.addAtAddressInstance('0xd9145CCE52D386f254917e481eB44e9943F39138', true, true)
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000)
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('changeOwner - transact (not payable)', { types: 'address newOwner', values: '0xd9145CCE52D386f254917e481eB44e9943F39138' }) // execute the "changeOwner" function
.waitForElementContainsText('*[data-id="terminalJournal"]', 'previousOwner0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', 60000) // check that the script is logging the event
.waitForElementContainsText('*[data-id="terminalJournal"]', 'newOwner0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.end() .end()
} }
} }
@ -172,3 +198,40 @@ const resolveUrl = `
} }
})() })()
` `
const deployWithEthersJs = `
// Right click on the script name and hit "Run" to execute
(async () => {
try {
console.log('Running deployWithEthers script...')
const constructorArgs = [] // Put constructor args (if any) here for your contract
// Note that the script needs the ABI which is generated from the compilation artifact.
// Make sure contract is compiled and artifacts are generated
const artifactsPath = 'contracts/artifacts/Owner.json' // Change this for different path
const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath))
// 'web3Provider' is a remix global variable object
const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner()
let factory = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer);
let contract = await factory.deploy(...constructorArgs);
console.log('Contract Address: ', contract.address);
// The contract is NOT deployed yet; we must wait until it is mined
await contract.deployed()
console.log('Deployment successful.')
contract.on('OwnerSet', (previousOwner, newOwner) => {
console.log('previousOwner' , previousOwner)
console.log('newOwner' , newOwner)
})
console.log('ok')
} catch (e) {
console.log(e.message)
}
})()`

@ -24,6 +24,7 @@
"@ethereumjs/vm": "^5.5.0", "@ethereumjs/vm": "^5.5.0",
"@remix-project/remix-astwalker": "^0.0.37", "@remix-project/remix-astwalker": "^0.0.37",
"@remix-project/remix-lib": "^0.5.7", "@remix-project/remix-lib": "^0.5.7",
"@remix-project/remix-simulator": "^0.2.7",
"async": "^2.6.2", "async": "^2.6.2",
"commander": "^2.19.0", "commander": "^2.19.0",
"deep-equal": "^1.0.1", "deep-equal": "^1.0.1",

@ -133,7 +133,7 @@ export class StorageResolver {
resolve([{}, null]) resolve([{}, null])
} else { } else {
this.web3.debug.storageRangeAt( this.web3.debug.storageRangeAt(
tx.blockHash, tx.transactionIndex === undefined ? tx.hash : tx.transactionIndex, tx.blockHash, tx.hash,
address, address,
start, start,
maxSize, maxSize,

@ -7,7 +7,6 @@ import { BreakpointManager } from '../src/code/breakpointManager'
var compiler = require('solc') var compiler = require('solc')
var vmCall = require('./vmCall') var vmCall = require('./vmCall')
var remixLib = require('@remix-project/remix-lib')
var ballot = `pragma solidity >=0.4.22 <0.8.0; var ballot = `pragma solidity >=0.4.22 <0.8.0;
@ -151,19 +150,17 @@ contract Ballot {
`; `;
(async () => { (async () => {
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex') var privateKey = Buffer.from('503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb', 'hex')
var vm = await vmCall.initVM(privateKey)
var output = compiler.compile(compilerInput(ballot)) var output = compiler.compile(compilerInput(ballot))
output = JSON.parse(output) output = JSON.parse(output)
var web3VM = new remixLib.vm.Web3VMProvider()
web3VM.setVM(vm)
const param = '0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000148656c6c6f20576f726c64210000000000000000000000000000000000000000' const param = '0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000148656c6c6f20576f726c64210000000000000000000000000000000000000000'
vmCall.sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['Ballot'].evm.bytecode.object + param, (error, txHash) => { const web3 = await vmCall.getWeb3()
console.log(error, txHash) vmCall.sendTx(web3, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['Ballot'].evm.bytecode.object + param, (error, hash) => {
console.log(error, hash)
if (error) { if (error) {
throw error throw error
} else { } else {
web3VM.eth.getTransaction(txHash, (error, tx) => { web3.eth.getTransaction(hash, (error, tx) => {
if (error) { if (error) {
throw error throw error
} else { } else {
@ -171,7 +168,7 @@ contract Ballot {
compilationResult: function () { compilationResult: function () {
return { data: output } return { data: output }
}, },
web3: web3VM web3: web3
}) })
debugManager.callTree.event.register('callTreeReady', () => { debugManager.callTree.event.register('callTreeReady', () => {
@ -230,7 +227,7 @@ function testDebugging (debugManager) {
var storageView = debugManager.storageViewAt(196, address) var storageView = debugManager.storageViewAt(196, address)
storageView.storageRange().then((storage) => { storageView.storageRange().then((storage) => {
t.equal(JSON.stringify(storage), JSON.stringify({ '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563': { key: '0x0000000000000000000000000000000000000000000000000000000000000000', value: '0x0000000000000000000000004b0897b0513fdc7c541b6d9d7e929c4e5364d2db' } })) t.equal(JSON.stringify(storage), JSON.stringify({ '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563': { key: '0x0000000000000000000000000000000000000000000000000000000000000000', value: '0x0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4' } }))
}).catch((error) => { }).catch((error) => {
if (error) return t.end(error) if (error) return t.end(error)
}) })
@ -245,7 +242,7 @@ function testDebugging (debugManager) {
const state = await debugManager.extractStateAt(312) const state = await debugManager.extractStateAt(312)
const decodedState = await debugManager.decodeStateAt(312, state) const decodedState = await debugManager.decodeStateAt(312, state)
console.log(decodedState) console.log(decodedState)
t.equal(decodedState['chairperson'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB') t.equal(decodedState['chairperson'].value, '0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4')
t.equal(decodedState['chairperson'].type, 'address') t.equal(decodedState['chairperson'].type, 'address')
t.equal(decodedState['proposals'].value[0].value.voteCount.value, '0') t.equal(decodedState['proposals'].value[0].value.voteCount.value, '0')
t.equal(decodedState['proposals'].value[0].value.voteCount.type, 'uint256') t.equal(decodedState['proposals'].value[0].value.voteCount.type, 'uint256')
@ -259,13 +256,14 @@ function testDebugging (debugManager) {
tape('traceManager.decodeLocalsAt', async (t) => { tape('traceManager.decodeLocalsAt', async (t) => {
t.plan(1) t.plan(1)
const tested = JSON.parse('{"proposalNames":{"value":[{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"}],"length":"0x1","type":"bytes32[]","cursor":1,"hasNext":false},"p":{"value":"45","type":"uint256"},"addressLocal":{"value":"0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB","type":"address"},"i":{"value":"2","type":"uint256"},"proposalsLocals":{"value":[{"value":{"name":{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"},"voteCount":{"value":"0","type":"uint256"}},"type":"struct Ballot.Proposal"}],"length":"0x1","type":"struct Ballot.Proposal[]"}}') const tested = JSON.parse('{"proposalNames":{"value":[{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"}],"length":"0x1","type":"bytes32[]","cursor":1,"hasNext":false},"p":{"value":"45","type":"uint256"},"addressLocal":{"value":"0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4","type":"address"},"i":{"value":"2","type":"uint256"},"proposalsLocals":{"value":[{"value":{"name":{"value":"0x48656C6C6F20576F726C64210000000000000000000000000000000000000000","type":"bytes32"},"voteCount":{"value":"0","type":"uint256"}},"type":"struct Ballot.Proposal"}],"length":"0x1","type":"struct Ballot.Proposal[]"}}')
try { try {
const address = debugManager.traceManager.getCurrentCalledAddressAt(327) const address = debugManager.traceManager.getCurrentCalledAddressAt(327)
const location = await debugManager.sourceLocationFromVMTraceIndex(address, 327) const location = await debugManager.sourceLocationFromVMTraceIndex(address, 327)
debugManager.decodeLocalsAt(327, location, (error, decodedlocals) => { debugManager.decodeLocalsAt(327, location, (error, decodedlocals) => {
if (error) return t.end(error) if (error) return t.end(error)
t.ok(deepequal(decodedlocals, tested), `locals does not match. expected: ${JSON.stringify(tested)} - current: ${decodedlocals}`) const res = deepequal(decodedlocals, tested)
t.ok(res, `test if locals does match. expected: ${JSON.stringify(tested)} - current: ${JSON.stringify(decodedlocals)}`)
}) })
} catch (error) { } catch (error) {
return t.end(error) return t.end(error)

@ -5,7 +5,7 @@ var intLocal = require('./contracts/intLocal')
var miscLocal = require('./contracts/miscLocal') var miscLocal = require('./contracts/miscLocal')
var structArrayLocal = require('./contracts/structArrayLocal') var structArrayLocal = require('./contracts/structArrayLocal')
var calldataLocal = require('./contracts/calldata') var calldataLocal = require('./contracts/calldata')
var vmCall = require('./vmCall') var vmCall = require('../vmCall')
var intLocalTest = require('./localsTests/int') var intLocalTest = require('./localsTests/int')
var miscLocalTest = require('./localsTests/misc') var miscLocalTest = require('./localsTests/misc')
var misc2LocalTest = require('./localsTests/misc2') var misc2LocalTest = require('./localsTests/misc2')
@ -15,29 +15,28 @@ var compilerInput = require('../helpers/compilerHelper').compilerInput
tape('solidity', function (t) { tape('solidity', function (t) {
t.test('local decoder', async function (st) { t.test('local decoder', async function (st) {
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex') var privateKey = Buffer.from('503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb', 'hex')
var vm = await vmCall.initVM(st, privateKey) await test(st, privateKey)
await test(st, vm, privateKey)
}) })
}) })
async function test (st, vm, privateKey) { async function test (st, privateKey) {
var output = compiler.compile(compilerInput(intLocal.contract)) var output = compiler.compile(compilerInput(intLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
await intLocalTest(st, vm, privateKey, output.contracts['test.sol']['intLocal'].evm.bytecode.object, output) await intLocalTest(st, privateKey, output.contracts['test.sol']['intLocal'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(miscLocal.contract)) output = compiler.compile(compilerInput(miscLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
await miscLocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal'].evm.bytecode.object, output) await miscLocalTest(st, privateKey, output.contracts['test.sol']['miscLocal'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(miscLocal.contract)) output = compiler.compile(compilerInput(miscLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
await misc2LocalTest(st, vm, privateKey, output.contracts['test.sol']['miscLocal2'].evm.bytecode.object, output) await misc2LocalTest(st, privateKey, output.contracts['test.sol']['miscLocal2'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(structArrayLocal.contract)) output = compiler.compile(compilerInput(structArrayLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
await structArrayLocalTest(st, vm, privateKey, output.contracts['test.sol']['structArrayLocal'].evm.bytecode.object, output) await structArrayLocalTest(st, privateKey, output.contracts['test.sol']['structArrayLocal'].evm.bytecode.object, output)
output = compiler.compile(compilerInput(calldataLocal.contract)) output = compiler.compile(compilerInput(calldataLocal.contract))
output = JSON.parse(output) output = JSON.parse(output)
await calldataLocalTest(st, vm, privateKey, output.contracts['test.sol']['calldataLocal'].evm.bytecode.object, output) await calldataLocalTest(st, privateKey, output.contracts['test.sol']['calldataLocal'].evm.bytecode.object, output)
st.end() st.end()
} }

@ -1,7 +1,7 @@
'use strict' 'use strict'
import deepequal from 'deep-equal' import deepequal from 'deep-equal'
import { sendTx } from '../vmCall' import * as vmCall from '../../vmCall'
import { TraceManager } from '../../../src/trace/traceManager' import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager' import { CodeManager } from '../../../src/code/codeManager'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy' import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
@ -9,23 +9,26 @@ import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree
import { EventManager } from '../../../src/eventManager' import { EventManager } from '../../../src/eventManager'
import * as helper from './helper' import * as helper from './helper'
module.exports = async function (st, vm, privateKey, contractBytecode, compilationResult) { module.exports = async function (st, privateKey, contractBytecode, compilationResult) {
let txHash let txHash
let web3
try { try {
let data = await sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode) web3 = await (vmCall as any).getWeb3()
const to = (data as any).result.createdAddress.toString() let hash = await (vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode)
const receipt = await web3.eth.getTransactionReceipt(hash)
const to = receipt.contractAddress
console.log('to', to)
// call to level11 // call to level11
data = await sendTx(vm, { nonce: 1, privateKey: privateKey }, to, 0, 'a372a595000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000000') txHash = await (vmCall as any).sendTx(web3, { nonce: 1, privateKey: privateKey }, to, 0, 'a372a595000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000000')
txHash = (data as any).hash
} catch (e) { } catch (e) {
return st.fail(e) return st.fail(e)
} }
return new Promise((resolve) => { return new Promise((resolve) => {
vm.web3.eth.getTransaction(txHash, function (error, tx) { web3.eth.getTransaction(txHash, function (error, tx) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
var traceManager = new TraceManager({ web3: vm.web3 }) var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager) var codeManager = new CodeManager(traceManager)
codeManager.clear() codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })

@ -1,6 +1,6 @@
'use strict' 'use strict'
import { sendTx } from '../vmCall' import * as vmCall from '../../vmCall'
import { TraceManager } from '../../../src/trace/traceManager' import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager' import { CodeManager } from '../../../src/code/codeManager'
import { contractCreationToken } from '../../../src/trace/traceHelper' import { contractCreationToken } from '../../../src/trace/traceHelper'
@ -9,19 +9,19 @@ import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree
import { EventManager } from '../../../src/eventManager' import { EventManager } from '../../../src/eventManager'
import * as helper from './helper' import * as helper from './helper'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) { module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => { return new Promise(async (resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) { let web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
const txHash = data.hash web3.eth.getTransaction(hash, function (error, tx) {
vm.web3.eth.getTransaction(txHash, function (error, tx) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
tx.to = contractCreationToken('0') tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 }) var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager) var codeManager = new CodeManager(traceManager)
codeManager.clear() codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })

@ -1,5 +1,5 @@
'use strict' 'use strict'
import { sendTx } from '../vmCall' import * as vmCall from '../../vmCall'
import { contractCreationToken } from '../../../src/trace/traceHelper' import { contractCreationToken } from '../../../src/trace/traceHelper'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy' import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree' import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree'
@ -8,19 +8,19 @@ import * as helper from './helper'
import { TraceManager } from '../../../src/trace/traceManager' import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager' import { CodeManager } from '../../../src/code/codeManager'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) { module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => { return new Promise(async (resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) { const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
const txHash = data.hash web3.eth.getTransaction(hash, function (error, tx) {
vm.web3.eth.getTransaction(txHash, function (error, tx) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
tx.to = contractCreationToken('0') tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 }) var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager) var codeManager = new CodeManager(traceManager)
codeManager.clear() codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })
@ -36,7 +36,7 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
st.equals(locals['boolFalse'].value, false) st.equals(locals['boolFalse'].value, false)
st.equals(locals['boolTrue'].value, true) st.equals(locals['boolTrue'].value, true)
st.equals(locals['testEnum'].value, 'three') st.equals(locals['testEnum'].value, 'three')
st.equals(locals['sender'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB') st.equals(locals['sender'].value, '0x5B38DA6A701C568545DCFCB03FCB875F56BEDDC4')
st.equals(locals['_bytes1'].value, '0x99') st.equals(locals['_bytes1'].value, '0x99')
st.equals(locals['__bytes1'].value, '0x99') st.equals(locals['__bytes1'].value, '0x99')
st.equals(locals['__bytes2'].value, '0x99AB') st.equals(locals['__bytes2'].value, '0x99AB')

@ -1,5 +1,5 @@
'use strict' 'use strict'
import { sendTx } from '../vmCall' import * as vmCall from '../../vmCall'
import { contractCreationToken } from '../../../src/trace/traceHelper' import { contractCreationToken } from '../../../src/trace/traceHelper'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy' import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree' import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree'
@ -8,19 +8,19 @@ import * as helper from './helper'
import { TraceManager } from '../../../src/trace/traceManager' import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager' import { CodeManager } from '../../../src/code/codeManager'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) { module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => { return new Promise(async (resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) { const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
const txHash = data.hash web3.eth.getTransaction(hash, function (error, tx) {
vm.web3.eth.getTransaction(txHash, function (error, tx) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
tx.to = contractCreationToken('0') tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 }) var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager) var codeManager = new CodeManager(traceManager)
codeManager.clear() codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })

@ -1,5 +1,5 @@
'use strict' 'use strict'
import { sendTx } from '../vmCall' import * as vmCall from '../../vmCall'
import { contractCreationToken } from '../../../src/trace/traceHelper' import { contractCreationToken } from '../../../src/trace/traceHelper'
import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy' import { SolidityProxy } from '../../../src/solidity-decoder/solidityProxy'
import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree' import { InternalCallTree } from '../../../src/solidity-decoder/internalCallTree'
@ -8,19 +8,19 @@ import * as helper from './helper'
import { TraceManager } from '../../../src/trace/traceManager' import { TraceManager } from '../../../src/trace/traceManager'
import { CodeManager } from '../../../src/code/codeManager' import { CodeManager } from '../../../src/code/codeManager'
module.exports = function (st, vm, privateKey, contractBytecode, compilationResult) { module.exports = function (st, privateKey, contractBytecode, compilationResult) {
return new Promise((resolve) => { return new Promise(async (resolve) => {
sendTx(vm, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, data) { const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, { nonce: 0, privateKey: privateKey }, null, 0, contractBytecode, function (error, hash) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
const txHash = data.hash web3.eth.getTransaction(hash, function (error, tx) {
vm.web3.eth.getTransaction(txHash, function (error, tx) {
if (error) { if (error) {
return st.fail(error) return st.fail(error)
} }
tx.to = contractCreationToken('0') tx.to = contractCreationToken('0')
var traceManager = new TraceManager({ web3: vm.web3 }) var traceManager = new TraceManager({ web3 })
var codeManager = new CodeManager(traceManager) var codeManager = new CodeManager(traceManager)
codeManager.clear() codeManager.clear()
var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) }) var solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: traceManager.getCurrentCalledAddressAt.bind(traceManager), getCode: codeManager.getCode.bind(codeManager) })

@ -2,57 +2,59 @@ import { compilerInput } from '../../helpers/compilerHelper'
import { TraceManager } from '../../../src/trace/traceManager' import { TraceManager } from '../../../src/trace/traceManager'
import { compile } from 'solc' import { compile } from 'solc'
import * as stateDecoder from '../../../src/solidity-decoder/stateDecoder' import * as stateDecoder from '../../../src/solidity-decoder/stateDecoder'
import { sendTx, initVM } from '../vmCall' import * as vmCall from '../../vmCall'
import { StorageResolver } from '../../../src/storage/storageResolver' import { StorageResolver } from '../../../src/storage/storageResolver'
import { StorageViewer } from '../../../src/storage/storageViewer' import { StorageViewer } from '../../../src/storage/storageViewer'
import { Address, bufferToHex } from 'ethereumjs-util'
module.exports = async function testMappingStorage (st, cb) { module.exports = async function testMappingStorage (st, cb) {
var mappingStorage = require('../contracts/mappingStorage') var mappingStorage = require('../contracts/mappingStorage')
var privateKey = Buffer.from('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex') var privateKey = Buffer.from('503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb', 'hex')
var vm = await initVM(st, privateKey)
var output = compile(compilerInput(mappingStorage.contract)) var output = compile(compilerInput(mappingStorage.contract))
output = JSON.parse(output) output = JSON.parse(output);
sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, data) { const web3 = await (vmCall as any).getWeb3();
(vmCall as any).sendTx(web3, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['SimpleMappingState'].evm.bytecode.object, function (error, hash) {
if (error) { if (error) {
console.log(error) console.log(error)
st.end(error) st.end(error)
} else { } else {
const txHash = data.hash web3.eth.getTransactionReceipt(hash, (error, tx) => {
vm.web3.eth.getTransaction(txHash, (error, tx) => {
if (error) { if (error) {
console.log(error) console.log(error)
st.end(error) st.end(error)
} else { } else {
testMapping(st, vm, privateKey, tx.contractAddress, output, cb) // const storage = await this.vm.stateManager.dumpStorage(data.to)
// (vmCall as any).web3().eth.getCode(tx.contractAddress).then((code) => console.log('code:', code))
// (vmCall as any).web3().debug.traceTransaction(hash).then((code) => console.log('trace:', code))
testMapping(st, privateKey, tx.contractAddress, output, web3, cb)
// st.end()
} }
}) })
} }
}) })
} }
function testMapping (st, vm, privateKey, contractAddress, output, cb) { function testMapping (st, privateKey, contractAddress, output, web3, cb) {
sendTx(vm, {nonce: 1, privateKey: privateKey}, contractAddress, 0, '2fd0a83a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001074686973206973206120737472696e6700000000000000000000000000000000', (vmCall as any).sendTx(web3, {nonce: 1, privateKey: privateKey}, contractAddress, 0, '2fd0a83a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001074686973206973206120737472696e6700000000000000000000000000000000',
function (error, data) { function (error, hash) {
if (error) { if (error) {
console.log(error) console.log(error)
st.end(error) st.end(error)
} else { } else {
const txHash = data.hash web3.eth.getTransaction(hash, (error, tx) => {
vm.web3.eth.getTransaction(txHash, (error, tx) => {
if (error) { if (error) {
console.log(error) console.log(error)
st.end(error) st.end(error)
} else { } else {
var traceManager = new TraceManager({web3: vm.web3}) var traceManager = new TraceManager({web3})
traceManager.resolveTrace(tx).then(() => { traceManager.resolveTrace(tx).then(() => {
var storageViewer = new StorageViewer({ var storageViewer = new StorageViewer({
stepIndex: 268, stepIndex: 268,
tx: tx, tx: tx,
address: contractAddress address: contractAddress
}, new StorageResolver({web3: vm.web3}), traceManager) }, new StorageResolver({web3}), traceManager)
var stateVars = stateDecoder.extractStateVariables('SimpleMappingState', output.sources) var stateVars = stateDecoder.extractStateVariables('SimpleMappingState', output.sources)
stateDecoder.decodeState(stateVars, storageViewer).then((result) => { stateDecoder.decodeState(stateVars, storageViewer).then((result) => {
console.log('ok', JSON.stringify(result))
st.equal(result['_num'].value, '1') st.equal(result['_num'].value, '1')
st.equal(result['_num'].type, 'uint256') st.equal(result['_num'].type, 'uint256')
st.equal(result['_iBreakSolidityState'].type, 'mapping(string => uint256)') st.equal(result['_iBreakSolidityState'].type, 'mapping(string => uint256)')

@ -1,76 +0,0 @@
'use strict'
import { Transaction as Tx } from '@ethereumjs/tx'
import { Block } from '@ethereumjs/block'
import { BN, bufferToHex, Address } from 'ethereumjs-util'
import { vm as remixlibVM } from '@remix-project/remix-lib'
import VM from '@ethereumjs/vm'
import Common from '@ethereumjs/common'
export function sendTx (vm, from, to, value, data, cb?) {
cb = cb || (() => {})
return new Promise ((resolve, reject) => {
var tx = new Tx({
nonce: new BN(from.nonce++),
// gasPrice: new BN(1),
gasLimit: new BN(3000000, 10),
to: to,
value: new BN(value, 10),
data: Buffer.from(data, 'hex')
})
tx = tx.sign(from.privateKey)
var block = Block.fromBlockData({
header: {
timestamp: new Date().getTime() / 1000 | 0,
number: 0
}
}) // still using default common
try {
vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) {
setTimeout(() => {
const hash = bufferToHex(tx.hash())
cb(null, { hash, result })
resolve({ hash, result })
}, 500)
}).catch((error) => {
console.error(error)
cb(error)
reject(error)
})
} catch (e) {
console.error(e)
}
})
}
async function createVm (hardfork) {
const common = new Common({ chain: 'mainnet', hardfork })
const vm = new VM({ common })
await vm.init()
return { vm, stateManager: vm.stateManager }
}
/*
Init VM / Send Transaction
*/
export async function initVM (st, privateKey) {
var VM = await createVm('berlin')
const vm = VM.vm
var address = Address.fromPrivateKey(privateKey)
try {
let account = await vm.stateManager.getAccount(address)
account.balance = new BN('f00000000000000001', 16)
await vm.stateManager.putAccount(address, account)
} catch (error) {
console.log(error)
}
var web3Provider = new remixlibVM.Web3VMProvider()
web3Provider.setVM(vm)
vm.web3 = web3Provider
return vm
}

@ -1,5 +1,5 @@
'use strict' 'use strict'
require('./vmCall')
require('./traceManager') require('./traceManager')
require('./codeManager') require('./codeManager')
require('./disassembler') require('./disassembler')

@ -1,63 +1,44 @@
'use strict' 'use strict'
import { Block } from '@ethereumjs/block' import { Block } from '@ethereumjs/block'
import { Transaction } from '@ethereumjs/tx'
import VM from '@ethereumjs/vm' import VM from '@ethereumjs/vm'
import { rlp, keccak, bufferToHex } from 'ethereumjs-util'
import { extendWeb3 } from '../src/init'
var utileth = require('ethereumjs-util') var utileth = require('ethereumjs-util')
var Tx = require('@ethereumjs/tx').Transaction var Tx = require('@ethereumjs/tx').Transaction
var BN = require('ethereumjs-util').BN var BN = require('ethereumjs-util').BN
var remixLib = require('@remix-project/remix-lib') var remixLib = require('@remix-project/remix-lib')
const { Provider, extend } = require('@remix-project/remix-simulator')
const Web3 = require('web3')
function sendTx (vm, from, to, value, data, cb) {
var tx = new Tx({
nonce: new BN(from.nonce++),
// gasPrice: new BN(1),
gasLimit: new BN(3000000, 10),
to: to,
value: new BN(value, 10),
data: Buffer.from(data, 'hex')
})
tx = tx.sign(from.privateKey)
var block = Block.fromBlockData({ async function getWeb3 () {
header: { const remixSimulatorProvider = new Provider({ fork: 'berlin' })
timestamp: new Date().getTime() / 1000 | 0, await remixSimulatorProvider.init()
number: 0 await remixSimulatorProvider.Accounts.resetAccounts()
} const web3 = new Web3(remixSimulatorProvider)
}) // still using default common extendWeb3(web3)
vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) { return web3
setTimeout(() => {
cb(null, utileth.bufferToHex(tx.hash()))
}, 500)
}).catch((error) => {
console.error(error)
cb(error)
})
} }
/* async function sendTx (web3, from, to, value, data, cb) {
Init VM / Send Transaction
*/
async function initVM (privateKey) {
var address = utileth.Address.fromPrivateKey(privateKey)
var vm = new VM({
activatePrecompiles: true
})
await vm.init()
try { try {
let account = await vm.stateManager.getAccount(address) cb = cb || (() => {})
account.balance = new BN('f00000000000000001', 16) const receipt = await web3.eth.sendTransaction({
await vm.stateManager.putAccount(address, account) from: utileth.Address.fromPrivateKey(from.privateKey).toString('hex'),
} catch (error) { to,
console.log(error) value,
data,
gas: 7000000
})
cb(null, receipt.transactionHash)
return receipt.transactionHash
} catch (e) {
cb(e)
} }
var web3Provider = new remixLib.vm.Web3VMProvider()
web3Provider.setVM(vm)
vm.web3 = web3Provider
return vm
} }
module.exports = { module.exports = {
sendTx: sendTx, sendTx,
initVM: initVM getWeb3
} }

@ -55,10 +55,10 @@ export class LogsManager {
if (queryFilter.topics.filter((logTopic) => changeEvent.log.topics.indexOf(logTopic) >= 0).length === 0) return false if (queryFilter.topics.filter((logTopic) => changeEvent.log.topics.indexOf(logTopic) >= 0).length === 0) return false
if (queryType === 'logs') { if (queryType === 'logs') {
if ((queryFilter.address === ('0x' + changeEvent.tx.to.toString('hex'))) && (queryFilter.address === ('0x' + changeEvent.tx.from.toString('hex')))) { const fromBlock = queryFilter.fromBlock || '0x0'
if (!queryFilter.toBlock) { const toBlock = queryFilter.toBlock || this.oldLogs.length ? this.oldLogs[this.oldLogs.length - 1].blockNumber : '0x0'
return true if ((queryFilter.address === (changeEvent.tx.to || '').toString()) || queryFilter.address === (changeEvent.tx.getSenderAddress().toString())) {
} else if (parseInt(queryFilter.toBlock) > parseInt(changeEvent.blockNumber)) { if ((parseInt(toBlock) >= parseInt(changeEvent.blockNumber)) && (parseInt(fromBlock) <= parseInt(changeEvent.blockNumber))) {
return true return true
} }
} }
@ -144,6 +144,23 @@ export class LogsManager {
} }
} }
getLogsByTxHash (hash) {
return this.oldLogs.filter((log) => '0x' + log.tx.hash().toString('hex') === hash)
.map((log) => {
return {
logIndex: '0x1', // 1
blockNumber: log.blockNumber,
blockHash: ('0x' + log.block.hash().toString('hex')),
transactionHash: ('0x' + log.tx.hash().toString('hex')),
transactionIndex: '0x' + log.txNumber.toString(16),
// TODO: if it's a contract deploy, it should be that address instead
address: log.log.address,
data: log.log.data,
topics: log.log.topics
}
})
}
getLogsFor (params) { getLogsFor (params) {
const results = [] const results = []
for (const log of this.oldLogs) { for (const log of this.oldLogs) {

@ -13,7 +13,6 @@ export class TxRunnerVM {
vmaccounts vmaccounts
queusTxs queusTxs
blocks blocks
txs
logsManager logsManager
commonContext commonContext
getVMObject: () => any getVMObject: () => any

@ -1,13 +1,10 @@
export class Blocks { export class Blocks {
vmContext vmContext
coinbase: string coinbase: string
blockNumber: number
constructor (vmContext, _options) { constructor (vmContext, _options) {
this.vmContext = vmContext this.vmContext = vmContext
const options = _options || {} const options = _options || {}
this.coinbase = options.coinbase || '0x0000000000000000000000000000000000000000' this.coinbase = options.coinbase || '0x0000000000000000000000000000000000000000'
this.blockNumber = 0
} }
methods (): Record<string, unknown> { methods (): Record<string, unknown> {
@ -107,7 +104,7 @@ export class Blocks {
} }
eth_blockNumber (payload, cb) { eth_blockNumber (payload, cb) {
cb(null, this.blockNumber) cb(null, parseInt(this.vmContext.latestBlockNumber))
} }
eth_getBlockTransactionCountByHash (payload, cb) { eth_getBlockTransactionCountByHash (payload, cb) {

@ -11,6 +11,7 @@ export class Transactions {
tags tags
txRunnerVMInstance txRunnerVMInstance
txRunnerInstance txRunnerInstance
TX_INDEX = '0x0' // currently there's always only 1 tx per block, so the transaction index will always be 0x0
constructor (vmContext) { constructor (vmContext) {
this.vmContext = vmContext this.vmContext = vmContext
@ -71,7 +72,7 @@ export class Transactions {
if (!error && result) { if (!error && result) {
this.vmContext.addBlock(result.block) this.vmContext.addBlock(result.block)
const hash = '0x' + result.tx.hash().toString('hex') const hash = '0x' + result.tx.hash().toString('hex')
this.vmContext.trackTx(hash, result.block) this.vmContext.trackTx(hash, result.block, result.tx)
this.vmContext.trackExecResult(hash, result.result.execResult) this.vmContext.trackExecResult(hash, result.result.execResult)
return cb(null, result.transactionHash) return cb(null, result.transactionHash)
} }
@ -95,17 +96,19 @@ export class Transactions {
return cb(error) return cb(error)
} }
const txBlock = this.vmContext.txs[receipt.hash] const txBlock = this.vmContext.blockByTxHash[receipt.hash]
const logs = this.vmContext.logsManager.getLogsByTxHash(receipt.hash)
const r: Record <string, unknown> = { const r: Record <string, unknown> = {
transactionHash: receipt.hash, transactionHash: receipt.hash,
transactionIndex: '0x00', transactionIndex: this.TX_INDEX,
blockHash: '0x' + txBlock.hash().toString('hex'), blockHash: '0x' + txBlock.hash().toString('hex'),
blockNumber: '0x' + txBlock.header.number.toString('hex'), blockNumber: '0x' + txBlock.header.number.toString('hex'),
gasUsed: receipt.gasUsed, gasUsed: receipt.gasUsed,
cumulativeGasUsed: receipt.gasUsed, // only 1 tx per block cumulativeGasUsed: receipt.gasUsed, // only 1 tx per block
contractAddress: receipt.contractAddress, contractAddress: receipt.contractAddress,
logs: receipt.logs, logs,
status: receipt.status, status: receipt.status,
to: receipt.to to: receipt.to
} }
@ -151,7 +154,7 @@ export class Transactions {
if (!error && result) { if (!error && result) {
this.vmContext.addBlock(result.block) this.vmContext.addBlock(result.block)
const hash = '0x' + result.tx.hash().toString('hex') const hash = '0x' + result.tx.hash().toString('hex')
this.vmContext.trackTx(hash, result.block) this.vmContext.trackTx(hash, result.block, result.tx)
this.vmContext.trackExecResult(hash, result.result.execResult) this.vmContext.trackExecResult(hash, result.result.execResult)
this.tags[tag] = result.transactionHash this.tags[tag] = result.transactionHash
// calls are not supposed to return a transaction hash. we do this for keeping track of it and allowing debugging calls. // calls are not supposed to return a transaction hash. we do this for keeping track of it and allowing debugging calls.
@ -185,7 +188,8 @@ export class Transactions {
return cb(error) return cb(error)
} }
const txBlock = this.vmContext.txs[receipt.transactionHash] const txBlock = this.vmContext.blockByTxHash[receipt.transactionHash]
const tx = this.vmContext.txByHash[receipt.transactionHash]
// TODO: params to add later // TODO: params to add later
const r: Record<string, unknown> = { const r: Record<string, unknown> = {
@ -198,8 +202,8 @@ export class Transactions {
gasPrice: '0x4a817c800', // 20000000000 gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash, hash: receipt.transactionHash,
input: receipt.input, input: receipt.input,
nonce: 2, // 0x15 // the nonce should be updated nonce: '0x' + tx.nonce.toString('hex'),
// "transactionIndex": 0, transactionIndex: this.TX_INDEX,
value: receipt.value value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000 // "value":"0xf3dbb76162000" // 4290000000000000
// "v": "0x25", // 37 // "v": "0x25", // 37
@ -234,6 +238,8 @@ export class Transactions {
return cb(error) return cb(error)
} }
const tx = this.vmContext.txByHash[receipt.transactionHash]
// TODO: params to add later // TODO: params to add later
const r: Record<string, unknown> = { const r: Record<string, unknown> = {
blockHash: '0x' + txBlock.hash().toString('hex'), blockHash: '0x' + txBlock.hash().toString('hex'),
@ -245,8 +251,8 @@ export class Transactions {
gasPrice: '0x4a817c800', // 20000000000 gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash, hash: receipt.transactionHash,
input: receipt.input, input: receipt.input,
nonce: 2, // 0x15 // the nonce should be updated nonce: '0x' + tx.nonce.toString('hex'),
// "transactionIndex": 0, transactionIndex: this.TX_INDEX,
value: receipt.value value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000 // "value":"0xf3dbb76162000" // 4290000000000000
// "v": "0x25", // 37 // "v": "0x25", // 37
@ -277,6 +283,8 @@ export class Transactions {
return cb(error) return cb(error)
} }
const tx = this.vmContext.txByHash[receipt.transactionHash]
// TODO: params to add later // TODO: params to add later
const r: Record<string, unknown> = { const r: Record<string, unknown> = {
blockHash: '0x' + txBlock.hash().toString('hex'), blockHash: '0x' + txBlock.hash().toString('hex'),
@ -288,8 +296,8 @@ export class Transactions {
gasPrice: '0x4a817c800', // 20000000000 gasPrice: '0x4a817c800', // 20000000000
hash: receipt.transactionHash, hash: receipt.transactionHash,
input: receipt.input, input: receipt.input,
nonce: 2, // 0x15 // the nonce should be updated nonce: '0x' + tx.nonce.toString('hex'),
// "transactionIndex": 0, transactionIndex: this.TX_INDEX,
value: receipt.value value: receipt.value
// "value":"0xf3dbb76162000" // 4290000000000000 // "value":"0xf3dbb76162000" // 4290000000000000
// "v": "0x25", // 37 // "v": "0x25", // 37

@ -24,31 +24,27 @@ class StateManagerCommonStorageDump extends StateManager {
return super.putContractStorage(address, key, value) return super.putContractStorage(address, key, value)
} }
async dumpStorage (address) { async dumpStorage (address): Promise<StorageDump> {
let trie return new Promise((resolve, reject) => {
try { this._getStorageTrie(address)
trie = await this._getStorageTrie(address) .then((trie) => {
} catch (e) { const storage = {}
console.log(e) const stream = trie.createReadStream()
throw e
} stream.on('data', (val) => {
return new Promise<StorageDump>((resolve, reject) => { const value = rlp.decode(val.value)
try { storage['0x' + val.key.toString('hex')] = {
const storage = {} key: this.keyHashes[val.key.toString('hex')],
const stream = trie.createReadStream() value: '0x' + value.toString('hex')
stream.on('data', (val) => { }
const value = rlp.decode(val.value) })
storage['0x' + val.key.toString('hex')] = { stream.on('end', () => {
key: this.keyHashes[val.key.toString('hex')], resolve(storage)
value: '0x' + value.toString('hex') })
}
}) })
stream.on('end', function () { .catch((e) => {
resolve(storage) reject(e)
}) })
} catch (e) {
reject(e)
}
}) })
} }
@ -60,18 +56,17 @@ class StateManagerCommonStorageDump extends StateManager {
} }
async setStateRoot (stateRoot) { async setStateRoot (stateRoot) {
await this._cache.flush() if (this._checkpointCount !== 0) {
throw new Error('Cannot set state root with uncommitted checkpoints')
if (stateRoot === this._trie.EMPTY_TRIE_ROOT) {
this._trie.root = stateRoot
this._cache.clear()
this._storageTries = {}
return
} }
const hasRoot = await this._trie.checkRoot(stateRoot) await this._cache.flush()
if (!hasRoot) {
throw new Error('State trie does not contain state root') if (!stateRoot.equals(this._trie.EMPTY_TRIE_ROOT)) {
const hasRoot = await this._trie.checkRoot(stateRoot)
if (!hasRoot) {
throw new Error('State trie does not contain state root')
}
} }
this._trie.root = stateRoot this._trie.root = stateRoot
@ -90,7 +85,8 @@ export class VMContext {
customNetWorks customNetWorks
blocks blocks
latestBlockNumber latestBlockNumber
txs blockByTxHash
txByHash
currentVm currentVm
web3vm web3vm
logsManager logsManager
@ -103,7 +99,8 @@ export class VMContext {
this.currentVm = this.createVm(this.currentFork) this.currentVm = this.createVm(this.currentFork)
this.blocks = {} this.blocks = {}
this.latestBlockNumber = 0 this.latestBlockNumber = 0
this.txs = {} this.blockByTxHash = {}
this.txByHash = {}
this.exeResults = {} this.exeResults = {}
this.logsManager = new execution.LogsManager() this.logsManager = new execution.LogsManager()
} }
@ -156,8 +153,9 @@ export class VMContext {
this.logsManager.checkBlock(blockNumber, block, this.web3()) this.logsManager.checkBlock(blockNumber, block, this.web3())
} }
trackTx (tx, block) { trackTx (txHash, block, tx) {
this.txs[tx] = block this.blockByTxHash[txHash] = block
this.txByHash[txHash] = tx
} }
trackExecResult (tx, execReult) { trackExecResult (tx, execReult) {

Loading…
Cancel
Save