diff --git a/test/solidity/contracts/addressLocal.js b/test/solidity/contracts/addressLocal.js new file mode 100644 index 0000000000..e67de7ee8c --- /dev/null +++ b/test/solidity/contracts/addressLocal.js @@ -0,0 +1,10 @@ +'use strict' + +module.exports = { + contract: ` +contract addressLocal { + function addressLocal () { + address sender = msg.sender; + } + } +`} diff --git a/test/solidity/contracts/intLocal.js b/test/solidity/contracts/intLocal.js index 5fab1e92b3..1bfaf7c5ec 100644 --- a/test/solidity/contracts/intLocal.js +++ b/test/solidity/contracts/intLocal.js @@ -2,7 +2,7 @@ module.exports = { contract: ` - contract proxy { +contract proxy { struct testStruct { int one; uint two; diff --git a/test/solidity/localDecoder.js b/test/solidity/localDecoder.js index 3c1025272a..f2fc3552c7 100644 --- a/test/solidity/localDecoder.js +++ b/test/solidity/localDecoder.js @@ -2,120 +2,23 @@ var tape = require('tape') var compiler = require('solc') var intLocal = require('./contracts/intLocal') -var TraceManager = require('../../babelify-src/trace/traceManager') -var CodeManager = require('../../babelify-src/code/codeManager') +var addressLocal = require('./contracts/addressLocal') var VM = require('ethereumjs-vm') -var Tx = require('ethereumjs-tx') -var Block = require('ethereumjs-block') -var BN = require('ethereumjs-util').BN var utileth = require('ethereumjs-util') -var Web3Providers = require('../../babelify-src/web3Provider/web3Providers') -var traceHelper = require('../../babelify-src/helpers/traceHelper') -var util = require('../../babelify-src/helpers/global') -var SolidityProxy = require('../../babelify-src/solidity/solidityProxy') -var InternalCallTree = require('../../babelify-src/util/internalCallTree') -var EventManager = require('../../babelify-src/lib/eventManager') -var localDecoder = require('../../babelify-src/solidity/localDecoder') +var Web3Providers = require('../../src/web3Provider/web3Providers') +var util = require('../../src/helpers/global') +var intLocalTest = require('./localsTests/int') +var addressLocalTest = require('./localsTests/address') tape('solidity', function (t) { t.test('local decoder', function (st) { var privateKey = new Buffer('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex') var address = utileth.privateToAddress(privateKey) var vm = initVM(st, address) - var output = compiler.compile(intLocal.contract, 0) - - sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['intLocal'].bytecode, function (error, txHash) { - if (error) { - st.fail(error) - } else { - util.web3.getTransaction(txHash, function (error, tx) { - if (error) { - st.fail(error) - } else { - tx.to = traceHelper.contractCreationToken('0') - var traceManager = new TraceManager() - var codeManager = new CodeManager(traceManager) - var solidityProxy = new SolidityProxy(traceManager, codeManager) - solidityProxy.reset(output) - var debuggerEvent = new EventManager() - var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalVariables: true }) - callTree.event.register('callTreeBuildFailed', (error) => { - st.fail(JSON.stringify(error)) - }) - - callTree.event.register('callTreeReady', (scopes, scopeStarts) => { - st.equals(scopeStarts[0], '') - st.equals(scopeStarts[97], '1') - st.equals(scopeStarts[112], '1.1') - st.equals(scopeStarts[135], '2') - st.equals(scopeStarts[154], '3') - st.equals(scopeStarts[169], '3.1') - st.equals(scopes[''].locals['ui8'].type.typeName, 'uint') - st.equals(scopes[''].locals['ui16'].type.typeName, 'uint') - st.equals(scopes[''].locals['ui32'].type.typeName, 'uint') - st.equals(scopes[''].locals['ui64'].type.typeName, 'uint') - st.equals(scopes[''].locals['ui128'].type.typeName, 'uint') - st.equals(scopes[''].locals['ui256'].type.typeName, 'uint') - st.equals(scopes[''].locals['ui'].type.typeName, 'uint') - st.equals(scopes[''].locals['i8'].type.typeName, 'int') - st.equals(scopes[''].locals['i16'].type.typeName, 'int') - st.equals(scopes[''].locals['i32'].type.typeName, 'int') - st.equals(scopes[''].locals['i64'].type.typeName, 'int') - st.equals(scopes[''].locals['i128'].type.typeName, 'int') - st.equals(scopes[''].locals['i256'].type.typeName, 'int') - st.equals(scopes[''].locals['i'].type.typeName, 'int') - st.equals(scopes[''].locals['ishrink'].type.typeName, 'int') - st.equals(scopes['1'].locals['ui8'].type.typeName, 'uint') - st.equals(scopes['1.1'].locals['ui81'].type.typeName, 'uint') - st.equals(scopes['2'].locals['ui81'].type.typeName, 'uint') - st.equals(scopes['3'].locals['ui8'].type.typeName, 'uint') - st.equals(scopes['3.1'].locals['ui81'].type.typeName, 'uint') - - decodeLocal(st, 125, traceManager, callTree, function (locals) { - st.equals(Object.keys(locals).length, 16) - }) - - decodeLocal(st, 177, traceManager, callTree, function (locals) { - try { - st.equals(locals['ui8'], '') - st.equals(Object.keys(locals).length, 1) - } catch (e) { - st.fail(e.message) - } - }) - }) - traceManager.resolveTrace(tx, (error, result) => { - if (error) { - st.fail(error) - } else { - debuggerEvent.trigger('newTraceLoaded', [traceManager.trace]) - } - }) - } - }) - } - }) + test(st, vm, privateKey) }) }) -/* - Decode local variable -*/ -function decodeLocal (st, index, traceManager, callTree, verifier) { - traceManager.waterfall([ - traceManager.getStackAt, - traceManager.getMemoryAt], - index, - function (error, result) { - if (!error) { - var locals = localDecoder.solidityLocals(index, callTree, result[0].value, result[1].value) - verifier(locals) - } else { - st.fail(error) - } - }) -} - /* Init VM / Send Transaction */ @@ -140,25 +43,10 @@ function initVM (st, address) { return vm } -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: new Buffer(data, 'hex') - }) - tx.sign(from.privateKey) - var block = new Block({ - header: { - timestamp: new Date().getTime() / 1000 | 0, - number: 0 - }, - transactions: [], - uncleHeaders: [] - }) - vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}, function (error, result) { - cb(error, utileth.bufferToHex(tx.hash())) +function test (st, vm, privateKey) { + var output = compiler.compile(intLocal.contract, 0) + intLocalTest(st, vm, privateKey, output.contracts['intLocal'].bytecode, output, function () { + output = compiler.compile(addressLocal.contract, 0) + addressLocalTest(st, vm, privateKey, output.contracts['addressLocal'].bytecode, output, function () {}) }) } diff --git a/test/solidity/localsTests/address.js b/test/solidity/localsTests/address.js new file mode 100644 index 0000000000..91a54365a2 --- /dev/null +++ b/test/solidity/localsTests/address.js @@ -0,0 +1,60 @@ +'use strict' +var TraceManager = require('../../../src/trace/traceManager') +var CodeManager = require('../../../src/code/codeManager') +var vmSendTx = require('./vmCall') +var traceHelper = require('../../../src/helpers/traceHelper') +var util = require('../../../src/helpers/global') +var SolidityProxy = require('../../../src/solidity/solidityProxy') +var InternalCallTree = require('../../../src/util/internalCallTree') +var EventManager = require('../../../src/lib/eventManager') +var helper = require('./helper') + +module.exports = function (st, vm, privateKey, contractBytecode, compilationResult, cb) { + vmSendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, contractBytecode, function (error, txHash) { + if (error) { + st.fail(error) + } else { + util.web3.getTransaction(txHash, function (error, tx) { + if (error) { + st.fail(error) + } else { + tx.to = traceHelper.contractCreationToken('0') + var traceManager = new TraceManager() + var codeManager = new CodeManager(traceManager) + codeManager.clear() + var solidityProxy = new SolidityProxy(traceManager, codeManager) + solidityProxy.reset(compilationResult) + var debuggerEvent = new EventManager() + var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalsVariables: true }) + callTree.event.register('callTreeReady', (scopes, scopeStarts) => { + helper.decodeLocals(st, 10, traceManager, callTree, function (locals) { + try { + st.equals(locals['sender'], '0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db') + st.equals(Object.keys(locals).length, 1) + } catch (e) { + st.fail(e.message) + } + }) + + helper.decodeLocals(st, 4, traceManager, callTree, function (locals) { + try { + st.equals(locals['sender'], '0x0000000000000000000000000000000000000000') + st.equals(Object.keys(locals).length, 1) + } catch (e) { + st.fail(e.message) + } + cb() + }) + }) + traceManager.resolveTrace(tx, (error, result) => { + if (error) { + st.fail(error) + } else { + debuggerEvent.trigger('newTraceLoaded', [traceManager.trace]) + } + }) + } + }) + } + }) +} diff --git a/test/solidity/localsTests/helper.js b/test/solidity/localsTests/helper.js new file mode 100644 index 0000000000..dcd24a7b99 --- /dev/null +++ b/test/solidity/localsTests/helper.js @@ -0,0 +1,24 @@ +'use strict' +var localDecoder = require('../../../src/solidity/localDecoder') + +/* + Decode local variable +*/ +function decodeLocal (st, index, traceManager, callTree, verifier) { + traceManager.waterfall([ + traceManager.getStackAt, + traceManager.getMemoryAt], + index, + function (error, result) { + if (!error) { + var locals = localDecoder.solidityLocals(index, callTree, result[0].value, result[1].value) + verifier(locals) + } else { + st.fail(error) + } + }) +} + +module.exports = { + decodeLocals: decodeLocal +} diff --git a/test/solidity/localsTests/int.js b/test/solidity/localsTests/int.js new file mode 100644 index 0000000000..969040dc9b --- /dev/null +++ b/test/solidity/localsTests/int.js @@ -0,0 +1,98 @@ +'use strict' +var TraceManager = require('../../../src/trace/traceManager') +var CodeManager = require('../../../src/code/codeManager') +var vmSendTx = require('./vmCall') +var traceHelper = require('../../../src/helpers/traceHelper') +var util = require('../../../src/helpers/global') +var SolidityProxy = require('../../../src/solidity/solidityProxy') +var InternalCallTree = require('../../../src/util/internalCallTree') +var EventManager = require('../../../src/lib/eventManager') +var helper = require('./helper') + +module.exports = function (st, vm, privateKey, contractBytecode, compilationResult, cb) { + vmSendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, contractBytecode, function (error, txHash) { + if (error) { + st.fail(error) + } else { + util.web3.getTransaction(txHash, function (error, tx) { + if (error) { + st.fail(error) + } else { + tx.to = traceHelper.contractCreationToken('0') + var traceManager = new TraceManager() + var codeManager = new CodeManager(traceManager) + codeManager.clear() + var solidityProxy = new SolidityProxy(traceManager, codeManager) + solidityProxy.reset(compilationResult) + var debuggerEvent = new EventManager() + var callTree = new InternalCallTree(debuggerEvent, traceManager, solidityProxy, codeManager, { includeLocalsVariables: true }) + callTree.event.register('callTreeReady', (scopes, scopeStarts) => { + st.equals(scopeStarts[0], '') + st.equals(scopeStarts[97], '1') + st.equals(scopeStarts[112], '1.1') + st.equals(scopeStarts[135], '2') + st.equals(scopeStarts[154], '3') + st.equals(scopeStarts[169], '3.1') + st.equals(scopes[''].locals['ui8'].type.typeName, 'uint') + st.equals(scopes[''].locals['ui16'].type.typeName, 'uint') + st.equals(scopes[''].locals['ui32'].type.typeName, 'uint') + st.equals(scopes[''].locals['ui64'].type.typeName, 'uint') + st.equals(scopes[''].locals['ui128'].type.typeName, 'uint') + st.equals(scopes[''].locals['ui256'].type.typeName, 'uint') + st.equals(scopes[''].locals['ui'].type.typeName, 'uint') + st.equals(scopes[''].locals['i8'].type.typeName, 'int') + st.equals(scopes[''].locals['i16'].type.typeName, 'int') + st.equals(scopes[''].locals['i32'].type.typeName, 'int') + st.equals(scopes[''].locals['i64'].type.typeName, 'int') + st.equals(scopes[''].locals['i128'].type.typeName, 'int') + st.equals(scopes[''].locals['i256'].type.typeName, 'int') + st.equals(scopes[''].locals['i'].type.typeName, 'int') + st.equals(scopes[''].locals['ishrink'].type.typeName, 'int') + st.equals(scopes['1'].locals['ui8'].type.typeName, 'uint') + st.equals(scopes['1.1'].locals['ui81'].type.typeName, 'uint') + st.equals(scopes['2'].locals['ui81'].type.typeName, 'uint') + st.equals(scopes['3'].locals['ui8'].type.typeName, 'uint') + st.equals(scopes['3.1'].locals['ui81'].type.typeName, 'uint') + + helper.decodeLocals(st, 125, traceManager, callTree, function (locals) { + st.equals(Object.keys(locals).length, 16) + st.equals(locals['ui8'], '130') + st.equals(locals['ui16'], '456') + st.equals(locals['ui32'], '4356') + st.equals(locals['ui64'], '3543543543') + st.equals(locals['ui128'], '234567') + st.equals(locals['ui256'], '115792089237316195423570985008687907853269984665640564039457584007880697216513') + st.equals(locals['ui'], '123545666') + st.equals(locals['i8'], '-45') + st.equals(locals['i16'], '-1234') + st.equals(locals['i32'], '3455') + st.equals(locals['i64'], '-35566') + st.equals(locals['i128'], '-444444') + st.equals(locals['i256'], '3434343') + st.equals(locals['i'], '-32432423423') + st.equals(locals['ishrink'], '2') + }) + + helper.decodeLocals(st, 177, traceManager, callTree, function (locals) { + try { + st.equals(locals['ui8'], '123') + st.equals(Object.keys(locals).length, 1) + } catch (e) { + st.fail(e.message) + } + cb() + }) + }) + traceManager.resolveTrace(tx, (error, result) => { + if (error) { + st.fail(error) + } else { + debuggerEvent.trigger('newTraceLoaded', [traceManager.trace]) + } + }) + } + }) + } + }) +} + diff --git a/test/solidity/localsTests/vmCall.js b/test/solidity/localsTests/vmCall.js new file mode 100644 index 0000000000..6f9fb83f06 --- /dev/null +++ b/test/solidity/localsTests/vmCall.js @@ -0,0 +1,30 @@ +'use strict' +var utileth = require('ethereumjs-util') +var Tx = require('ethereumjs-tx') +var Block = require('ethereumjs-block') +var BN = require('ethereumjs-util').BN + +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: new Buffer(data, 'hex') + }) + tx.sign(from.privateKey) + var block = new Block({ + header: { + timestamp: new Date().getTime() / 1000 | 0, + number: 0 + }, + transactions: [], + uncleHeaders: [] + }) + vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}, function (error, result) { + cb(error, utileth.bufferToHex(tx.hash())) + }) +} + +module.exports = sendTx