Commit 7dd80d33 authored by yann300's avatar yann300 Committed by GitHub

Merge pull request #159 from ethereum/decodeLocals

Add DecodeFromMemory to Solidity Types
parents 7074e733 014fe46a
This diff is collapsed.
......@@ -6,10 +6,11 @@ function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory) {
return { 'error': 'Can\'t display locals. reason: compilation result might not have been provided' }
}
var locals = {}
memory = formatMemory(memory)
for (var local in scope.locals) {
let variable = scope.locals[local]
if (variable.type.decodeLocals) {
locals[variable.name] = variable.type.decodeLocals(variable.stackHeight, stack, memory)
if (variable.type.decodeFromStack) {
locals[variable.name] = variable.type.decodeFromStack(variable.stackDepth, stack, memory)
} else {
locals[variable.name] = ''
}
......@@ -17,6 +18,13 @@ function solidityLocals (vmtraceIndex, internalTreeCall, stack, memory) {
return locals
}
function formatMemory (memory) {
if (memory instanceof Array) {
memory = memory.join('').replace(/0x/g, '')
}
return memory
}
module.exports = {
solidityLocals: solidityLocals
}
......@@ -113,7 +113,12 @@ class SolidityProxy {
*/
ast (sourceLocation) {
var file = this.sourceList[sourceLocation.file]
return this.sources[file].AST
if (this.sources[file]) {
return this.sources[file].AST
} else {
console.log('AST not found for file id ' + sourceLocation.file)
return null
}
}
}
......
......@@ -12,7 +12,7 @@ function decodeState (stateVars, storageContent) {
var ret = {}
for (var k in stateVars) {
var stateVar = stateVars[k]
ret[stateVar.name] = stateVar.type.decodeFromStorage(stateVar.location, storageContent)
ret[stateVar.name] = stateVar.type.decodeFromStorage(stateVar.storagelocation, storageContent)
}
return ret
}
......
'use strict'
var util = require('./util')
var ValueType = require('./ValueType')
function Address () {
this.storageSlots = 1
this.storageBytes = 20
this.typeName = 'address'
}
class Address extends ValueType {
constructor () {
super(1, 20, 'address')
}
Address.prototype.decodeFromStorage = function (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes)
return '0x' + value.toUpperCase()
decodeValue (value) {
if (!value) {
return '0x0000000000000000000000000000000000000000'
} else {
return '0x' + util.extractHexByteSlice(value, this.storageBytes, 0).toUpperCase()
}
}
}
module.exports = Address
'use strict'
var util = require('./util')
var BN = require('ethereumjs-util').BN
var RefType = require('./RefType')
function ArrayType (underlyingType, arraySize) {
this.typeName = 'array'
this.storageBytes = 32
this.underlyingType = underlyingType
this.arraySize = arraySize
this.storageSlots = null
if (arraySize === 'dynamic') {
this.storageSlots = 1
} else {
if (underlyingType.storageBytes < 32) {
var itemPerSlot = Math.floor(32 / underlyingType.storageBytes)
this.storageSlots = Math.ceil(arraySize / itemPerSlot)
class ArrayType extends RefType {
constructor (underlyingType, arraySize, location) {
var storageSlots = null
if (arraySize === 'dynamic') {
storageSlots = 1
} else {
this.storageSlots = arraySize * underlyingType.storageSlots
if (underlyingType.storageBytes < 32) {
var itemPerSlot = Math.floor(32 / underlyingType.storageBytes)
storageSlots = Math.ceil(arraySize / itemPerSlot)
} else {
storageSlots = arraySize * underlyingType.storageSlots
}
}
super(storageSlots, 32, 'array', location)
this.underlyingType = underlyingType
this.arraySize = arraySize
}
}
ArrayType.prototype.decodeFromStorage = function (location, storageContent) {
var ret = []
var size = null
var slotValue = util.extractHexValue(location, storageContent, this.storageBytes)
var currentLocation = {
offset: 0,
slot: location.slot
}
if (this.arraySize === 'dynamic') {
size = util.toBN('0x' + slotValue)
currentLocation.slot = util.sha3(location.slot)
} else {
size = new BN(this.arraySize)
}
var k = util.toBN(0)
for (; k.lt(size) && k.ltn(300); k.iaddn(1)) {
ret.push(this.underlyingType.decodeFromStorage(currentLocation, storageContent))
if (this.underlyingType.storageSlots === 1 && location.offset + this.underlyingType.storageBytes <= 32) {
currentLocation.offset += this.underlyingType.storageBytes
if (currentLocation.offset + this.underlyingType.storageBytes > 32) {
decodeFromStorage (location, storageContent) {
var ret = []
var size = null
var slotValue = util.extractHexValue(location, storageContent, this.storageBytes)
var currentLocation = {
offset: 0,
slot: location.slot
}
if (this.arraySize === 'dynamic') {
size = util.toBN('0x' + slotValue)
currentLocation.slot = util.sha3(location.slot)
} else {
size = new BN(this.arraySize)
}
var k = util.toBN(0)
for (; k.lt(size) && k.ltn(300); k.iaddn(1)) {
ret.push(this.underlyingType.decodeFromStorage(currentLocation, storageContent))
if (this.underlyingType.storageSlots === 1 && location.offset + this.underlyingType.storageBytes <= 32) {
currentLocation.offset += this.underlyingType.storageBytes
if (currentLocation.offset + this.underlyingType.storageBytes > 32) {
currentLocation.offset = 0
currentLocation.slot = '0x' + util.add(currentLocation.slot, 1).toString(16)
}
} else {
currentLocation.slot = '0x' + util.add(currentLocation.slot, this.underlyingType.storageSlots).toString(16)
currentLocation.offset = 0
currentLocation.slot = '0x' + util.add(currentLocation.slot, 1).toString(16)
}
} else {
currentLocation.slot = '0x' + util.add(currentLocation.slot, this.underlyingType.storageSlots).toString(16)
currentLocation.offset = 0
}
return {
value: ret,
length: '0x' + size.toString(16)
}
}
return {
value: ret,
length: '0x' + size.toString(16)
decodeFromMemoryInternal (offset, memory) {
var ret = []
var length = this.arraySize
if (this.arraySize === 'dynamic') {
length = memory.substr(2 * offset, 64)
length = parseInt(length, 16)
offset = offset + 32
}
for (var k = 0; k < length; k++) {
var contentOffset = offset
ret.push(this.underlyingType.decodeFromMemory(contentOffset, memory))
offset += 32
}
return ret
}
}
......
'use strict'
var ValueType = require('./ValueType')
var util = require('./util')
function Bool () {
this.storageSlots = 1
this.storageBytes = 1
this.typeName = 'bool'
}
class Bool extends ValueType {
constructor () {
super(1, 1, 'bool')
}
Bool.prototype.decodeFromStorage = function (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes)
return value !== '00'
decodeValue (value) {
if (!value) {
return false
} else {
value = util.extractHexByteSlice(value, this.storageBytes, 0)
return value !== '00'
}
}
}
module.exports = Bool
'use strict'
var util = require('./util')
var BN = require('ethereumjs-util').BN
var RefType = require('./RefType')
function DynamicByteArray () {
this.storageSlots = 1
this.storageBytes = 32
this.typeName = 'bytes'
}
class DynamicByteArray extends RefType {
constructor (location) {
super(1, 32, 'bytes', location)
}
DynamicByteArray.prototype.decodeFromStorage = function (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes)
var bn = new BN(value, 16)
if (bn.testn(0)) {
var length = bn.div(new BN(2))
var dataPos = new BN(util.sha3(location.slot).replace('0x', ''), 16)
var ret = ''
var currentSlot = util.readFromStorage(dataPos, storageContent)
while (length.gt(ret.length) && ret.length < 32000) {
currentSlot = currentSlot.replace('0x', '')
ret += currentSlot
dataPos = dataPos.add(new BN(1))
currentSlot = util.readFromStorage(dataPos, storageContent)
}
return {
value: '0x' + ret.replace(/(00)+$/, ''),
length: '0x' + length.toString(16)
decodeFromStorage (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes)
var bn = new BN(value, 16)
if (bn.testn(0)) {
var length = bn.div(new BN(2))
var dataPos = new BN(util.sha3(location.slot).replace('0x', ''), 16)
var ret = ''
var currentSlot = util.readFromStorage(dataPos, storageContent)
while (length.gt(ret.length) && ret.length < 32000) {
currentSlot = currentSlot.replace('0x', '')
ret += currentSlot
dataPos = dataPos.add(new BN(1))
currentSlot = util.readFromStorage(dataPos, storageContent)
}
return {
value: '0x' + ret.replace(/(00)+$/, ''),
length: '0x' + length.toString(16)
}
} else {
var size = parseInt(value.substr(value.length - 2, 2), 16) / 2
return {
value: '0x' + value.substr(0, size * 2),
length: '0x' + size.toString(16)
}
}
} else {
var size = parseInt(value.substr(value.length - 2, 2), 16) / 2
}
decodeFromMemoryInternal (offset, memory) {
offset = 2 * offset
var length = memory.substr(offset, 64)
length = 2 * parseInt(length, 16)
return {
value: '0x' + value.substr(0, size * 2),
length: '0x' + size.toString(16)
length: '0x' + length.toString(16),
value: '0x' + memory.substr(offset + 64, length)
}
}
}
......
'use strict'
var util = require('./util')
var ValueType = require('./ValueType')
function Enum (enumDef) {
this.enumDef = enumDef
this.typeName = 'enum'
this.storageSlots = 1
var length = enumDef.children.length
this.storageBytes = 0
while (length > 1) {
length = length / 256
this.storageBytes++
class Enum extends ValueType {
constructor (enumDef) {
var storageBytes = 0
var length = enumDef.children.length
while (length > 1) {
length = length / 256
storageBytes++
}
super(1, storageBytes, 'enum')
this.enumDef = enumDef
}
}
Enum.prototype.decodeFromStorage = function (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes)
value = parseInt(value, 16)
if (this.enumDef.children.length > value) {
return this.enumDef.children[value].attributes.name
} else {
return 'INVALID_ENUM<' + value + '>'
decodeValue (value) {
if (!value) {
return this.enumDef.children[0].attributes.name
} else {
value = parseInt(value, 16)
if (this.enumDef.children.length > value) {
return this.enumDef.children[value].attributes.name
} else {
return 'INVALID_ENUM<' + value + '>'
}
}
}
}
......
'use strict'
var util = require('./util')
var ValueType = require('./ValueType')
function FixedByteArray (storageBytes) {
this.storageSlots = 1
this.storageBytes = storageBytes
this.typeName = 'bytesX'
}
class FixedByteArray extends ValueType {
constructor (storageBytes) {
super(1, storageBytes, 'bytesX')
}
FixedByteArray.prototype.decodeFromStorage = function (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes)
return '0x' + value.toUpperCase()
decodeValue (value) {
return '0x' + value.substr(0, 2 * this.storageBytes).toUpperCase()
}
}
module.exports = FixedByteArray
'use strict'
var util = require('./util')
var ValueType = require('./ValueType')
function Int (storageBytes) {
this.storageSlots = 1
this.storageBytes = storageBytes
this.typeName = 'int'
}
class Int extends ValueType {
constructor (storageBytes) {
super(1, storageBytes, 'int')
}
Int.prototype.decodeFromStorage = function (location, storageContent) {
return util.decodeInt(location, storageContent, this.storageBytes, true)
decodeValue (value) {
value = util.extractHexByteSlice(value, this.storageBytes, 0)
return util.decodeIntFromHex(value, this.storageBytes, true)
}
}
module.exports = Int
'use strict'
var RefType = require('./RefType')
function Mapping () {
this.storageSlots = 1
this.storageBytes = 32
this.typeName = 'mapping'
}
class Mapping extends RefType {
constructor () {
super(1, 32, 'mapping')
}
decodeValue (value) {
return '<not implemented>'
}
decodeFromStorage (location, storageContent) {
return '<not implemented>'
}
Mapping.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented>'
decodeFromMemoryInternal (offset, memory) {
return '<not implemented>'
}
}
module.exports = Mapping
'use strict'
class RefType {
constructor (storageSlots, storageBytes, typeName, location) {
this.location = location
this.storageSlots = storageSlots
this.storageBytes = storageBytes
this.typeName = typeName
this.basicType = 'RefType'
}
/**
* decode the type from the stack
*
* @param {Int} stackDepth - position of the type in the stack
* @param {Array} stack - stack
* @param {String} - memory
* @param {Object} - storage
* @return {Object} decoded value
*/
decodeFromStack (stackDepth, stack, memory, storage) {
if (stack.length - 1 < stackDepth) {
return { error: '<decoding failed - stack underflow ' + stackDepth + '>' }
}
if (!storage) {
storage = {} // TODO this is a fallback, should manage properly locals store in storage
}
var offset = stack[stack.length - 1 - stackDepth]
offset = parseInt(offset, 16)
if (this.isInStorage()) {
return this.decodeFromStorage({ offset: 0, slot: offset }, storage)
} else if (this.isInMemory()) {
return this.decodeFromMemoryInternal(offset, memory)
} else {
return { error: '<decoding failed - no decoder for ' + this.location + '>' }
}
}
/**
* decode the type from the memory
*
* @param {Int} offset - position of the ref of the type in memory
* @param {String} memory - memory
* @return {Object} decoded value
*/
decodeFromMemory (offset, memory) {
offset = memory.substr(2 * offset, 64)
offset = parseInt(offset, 16)
return this.decodeFromMemoryInternal(offset, memory)
}
/**
* current type defined in storage
*
* @return {Bool} - return true if the type is defined in the storage
*/
isInStorage () {
return this.location.indexOf('storage') === 0
}
/**
* current type defined in memory
*
* @return {Bool} - return true if the type is defined in the memory
*/
isInMemory () {
return this.location.indexOf('memory') === 0
}
}
module.exports = RefType
'use strict'
var DynamicBytes = require('./DynamicByteArray')
function StringType () {
this.storageSlots = 1
this.storageBytes = 32
this.typeName = 'string'
this.dynamicBytes = new DynamicBytes()
class StringType extends DynamicBytes {
constructor (location) {
super(location)
this.typeName = 'string'
}
decodeFromStorage (location, storageContent) {
var decoded = super.decodeFromStorage(location, storageContent)
return format(decoded)
}
decodeFromStack (stackDepth, stack, memory) {
return super.decodeFromStack(stackDepth, stack, memory)
}
decodeFromMemoryInternal (offset, memory) {
var decoded = super.decodeFromMemoryInternal(offset, memory)
return format(decoded)
}
}
StringType.prototype.decodeFromStorage = function (location, storageContent) {
var decoded = this.dynamicBytes.decodeFromStorage(location, storageContent)
function format (decoded) {
if (decoded.error) {
return decoded
}
var value = decoded.value
value = value.replace('0x', '').replace(/(..)/g, '%$1')
var ret = {
......
'use strict'
var util = require('./util')
var RefType = require('./RefType')
function Struct (memberDetails) {
this.storageSlots = memberDetails.storageSlots
this.storageBytes = 32
this.members = memberDetails.members
this.typeName = 'struct'
}
class Struct extends RefType {
constructor (memberDetails, location) {
super(memberDetails.storageSlots, 32, 'struct', location)
this.members = memberDetails.members
}
decodeFromStorage (location, storageContent) {
var ret = {}
this.members.map(function (item, i) {
var globalLocation = {
offset: location.offset + item.storagelocation.offset,
slot: util.add(location.slot, item.storagelocation.slot)
}
ret[item.name] = item.type.decodeFromStorage(globalLocation, storageContent)
})
return ret
}
Struct.prototype.decodeFromStorage = function (location, storageContent) {
var ret = {}
this.members.map(function (item, i) {
var globalLocation = {
offset: location.offset + item.location.offset,
slot: util.add(location.slot, item.location.slot)
}
ret[item.name] = item.type.decodeFromStorage(globalLocation, storageContent)
})
return ret
decodeFromMemoryInternal (offset, memory) {
var ret = {}
this.members.map((item, i) => {
var contentOffset = offset
var member = item.type.decodeFromMemory(contentOffset, memory)
ret[item.name] = member
offset += 32
})
return ret
}
}
module.exports = Struct
'use strict'
var util = require('./util')
var ValueType = require('./ValueType')
function Uint (storageBytes) {
this.storageSlots = 1
this.storageBytes = storageBytes
this.typeName = 'uint'
}
class Uint extends ValueType {
constructor (storageBytes) {
super(1, storageBytes, 'uint')
}
Uint.prototype.decodeFromStorage = function (location, storageContent) {
return util.decodeInt(location, storageContent, this.storageBytes, false)
decodeValue (value) {
value = util.extractHexByteSlice(value, this.storageBytes, 0)
return util.decodeIntFromHex(value, this.storageBytes, false)
}
}
module.exports = Uint
'use strict'
var util = require('./util')
class ValueType {
constructor (storageSlots, storageBytes, typeName) {
this.storageSlots = storageSlots
this.storageBytes = storageBytes
this.typeName = typeName
this.basicType = 'ValueType'
}
/**
* decode the type with the @arg location from the storage
*
* @param {Object} location - containing offset and slot
* @param {Object} storageContent - storageContent (storage)
* @return {Object} - decoded value
*/
decodeFromStorage (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes)
return this.decodeValue(value)
}
/**
* decode the type from the stack
*
* @param {Int} stackDepth - position of the type in the stack
* @param {Array} stack - stack
* @param {String} - memory
* @return {Object} - decoded value
*/
decodeFromStack (stackDepth, stack, memory) {
if (stackDepth >= stack.length) {
return this.decodeValue('')
} else {
return this.decodeValue(stack[stack.length - 1 - stackDepth].replace('0x', ''))
}
}
/**
* decode the type with the @arg offset location from the memory
*
* @param {Int} stackDepth - position of the type in the stack
* @return {String} - memory
* @return {Object} - decoded value
*/
decodeFromMemory (offset, memory) {
var value = memory.substr(2 * offset, 64)
return this.decodeValue(util.extractHexByteSlice(value, this.storageBytes, 0))
}
}
module.exports = ValueType
......@@ -5,15 +5,22 @@ var BN = require('ethereumjs-util').BN
module.exports = {
readFromStorage: readFromStorage,
decodeInt: decodeInt,
decodeIntFromHex: decodeIntFromHex,
extractHexValue: extractHexValue,
extractHexByteSlice: extractHexByteSlice,
sha3: sha3,
toBN: toBN,
add: add
add: add,
extractLocation: extractLocation
}
function decodeInt (location, storageContent, byteLength, signed) {
var slotvalue = readFromStorage(location.slot, storageContent)
var value = extractHexByteSlice(slotvalue, byteLength, location.offset)
return decodeIntFromHex(value, byteLength, signed)
}
function decodeIntFromHex (value, byteLength, signed) {
var bigNumber = new BN(value, 16)
if (signed) {
bigNumber = bigNumber.fromTwos(8 * byteLength)
......@@ -85,3 +92,12 @@ function toBN (value) {
function add (value1, value2) {
return toBN(value1).add(toBN(value2))
}
function extractLocation (type) {
var match = type.match(/( storage ref| storage pointer| memory| calldata)?$/)
if (match[1] !== '') {
return match[1].trim()
} else {
return null
}
}
......@@ -31,7 +31,8 @@ function Ethdebugger () {
this.solidityProxy = new SolidityProxy(this.traceManager, this.codeManager)
var callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true })
this.callTree = callTree
this.callTree = callTree // TODO: currently used by browser solidity, we should improve the API
this.event.register('indexChanged', this, function (index) {
self.codeManager.resolveStep(index, self.tx)
})
......
......@@ -91,7 +91,7 @@ async function buildTree (tree, step, scopeId) {
try {
sourceLocation = await extractSourceLocation(tree, step)
} catch (e) {
return { outStep: step, error: 'InternalCallTree - Error resolving source location. ' + step + ' ' + e.messager }
return { outStep: step, error: 'InternalCallTree - Error resolving source location. ' + step + ' ' + e.message }
}
if (!sourceLocation) {
return { outStep: step, error: 'InternalCallTree - No source Location. ' + step }
......@@ -132,7 +132,7 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId) {
tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = {
name: variableDeclaration.attributes.name,
type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName),
stackHeight: stack.length
stackDepth: stack.length
}
}
})
......@@ -149,11 +149,11 @@ function extractSourceLocation (tree, step) {
if (!error) {
return resolve(sourceLocation)
} else {
return reject('InternalCallTree - Cannot retrieve sourcelocation for step ' + step)
return reject('InternalCallTree - Cannot retrieve sourcelocation for step ' + step + ' ' + error)
}
})
} else {
return reject('InternalCallTree - Cannot retrieve address for step ' + step)
return reject('InternalCallTree - Cannot retrieve address for step ' + step + ' ' + error)
}
})
})
......@@ -161,10 +161,15 @@ function extractSourceLocation (tree, step) {
function resolveVariableDeclaration (tree, step, sourceLocation) {
if (!tree.variableDeclarationByFile[sourceLocation.file]) {
tree.variableDeclarationByFile[sourceLocation.file] = extractVariableDeclarations(tree.solidityProxy.ast(sourceLocation), tree.astWalker)
var ast = tree.solidityProxy.ast(sourceLocation)
if (ast) {
tree.variableDeclarationByFile[sourceLocation.file] = extractVariableDeclarations(ast, tree.astWalker)
} else {
console.log('Ast not found for step ' + step + '. file ' + sourceLocation.file)
return null
}
}
var variableDeclarations = tree.variableDeclarationByFile[sourceLocation.file]
return variableDeclarations[sourceLocation.start + ':' + sourceLocation.length + ':' + sourceLocation.file]
return tree.variableDeclarationByFile[sourceLocation.file][sourceLocation.start + ':' + sourceLocation.length + ':' + sourceLocation.file]
}
function extractVariableDeclarations (ast, astWalker) {
......
......@@ -2,7 +2,7 @@
module.exports = {
contract: `
contract proxy {
contract proxy {
struct testStruct {
int one;
uint two;
......
'use strict'
module.exports = {
contract: `
contract miscLocal {
enum enumDef {
one,
two,
three,
four
}
function miscLocal () {
bool boolFalse = false;
bool boolTrue = true;
enumDef testEnum;
testEnum = enumDef.three;
address sender = msg.sender;
byte _bytes1 = hex"99";
bytes1 __bytes1 = hex"99";
bytes2 __bytes2 = hex"99AB";
bytes4 __bytes4 = hex"99FA";
bytes6 __bytes6 = hex"99";
bytes7 __bytes7 = hex"993567";
bytes8 __bytes8 = hex"99ABD417";
bytes9 __bytes9 = hex"99156744AF";
bytes13 __bytes13 = hex"991234234253";
bytes16 __bytes16 = hex"99AFAD234324";
bytes24 __bytes24 = hex"99AFAD234324";
bytes32 __bytes32 = hex"9999ABD41799ABD417";
}
}
contract miscLocal2 {
function miscLocal2 () {
bytes memory dynbytes = "dynamicbytes";
string memory smallstring = "test_test_test";
}
}
`}
'use strict'
module.exports = {
contract: `
contract structArrayLocal {
struct teststruct {
string a;
int b;
string c;
int d;
bool e;
}
enum enumdef
{
one,
two,
three
}
struct teststructArray {
string[] a;
int8[3] b;
enumdef c;
}
function structArrayLocal () {
bytes memory bytesSimple = "test_super";
teststruct memory e;
e.a = "test";
e.b = 5;
string memory f = "test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_";
e.c = "test_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_test";
e.d = 3;
e.e = true;
int[5] memory simpleArray;
simpleArray[0] = 45;
simpleArray[1] = 324324;
simpleArray[2] = -333;
simpleArray[3] = 5656;
simpleArray[4] = -1111;
string[3] memory stringArray;
stringArray[0] = "long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_";
stringArray[1] = "two";
stringArray[2] = "three";
int[][3] memory dynArray;
dynArray[0] = new int[](1);
dynArray[1] = new int[](2);
dynArray[2] = new int[](3);
dynArray[0][0] = 3423423532;
dynArray[1][0] = -342343323532;
dynArray[1][1] = 23432;
dynArray[2][0] = -432432;
dynArray[2][1] = 3423423532;
dynArray[2][2] = -432432;
teststruct[3] memory structArray;
structArray[0] = e;
structArray[1].a = "item1 a";
structArray[1].b = 20;
structArray[1].c = "item1 c";
structArray[1].d = -45;
structArray[1].e = false;
structArray[2].a = "item2 a";
structArray[2].b = 200;
structArray[2].c = "item2 c";
structArray[2].d = -450;
structArray[2].e = true;
teststructArray memory arrayStruct;
arrayStruct.a = new string[](1);
arrayStruct.a[0] = "string";
arrayStruct.b[0] = 34;
arrayStruct.b[1] = -23;
arrayStruct.b[2] = -3;
arrayStruct.c = enumdef.three;
}
}
`}
......@@ -2,121 +2,27 @@
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 miscLocal = require('./contracts/miscLocal')
var structArrayLocal = require('./contracts/structArrayLocal')
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 intLocalTest = require('./localsTests/int')
var miscLocalTest = require('./localsTests/misc')
var misc2LocalTest = require('./localsTests/misc2')
var structArrayLocalTest = require('./localsTests/structArray')
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
*/
function initVM (st, address) {
......@@ -140,25 +46,16 @@ 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(miscLocal.contract, 0)
miscLocalTest(st, vm, privateKey, output.contracts['miscLocal'].bytecode, output, function () {
output = compiler.compile(miscLocal.contract, 0)
misc2LocalTest(st, vm, privateKey, output.contracts['miscLocal2'].bytecode, output, function () {
output = compiler.compile(structArrayLocal.contract, 0)
structArrayLocalTest(st, vm, privateKey, output.contracts['structArrayLocal'].bytecode, output, function () {})
})
})
})
}
'use strict'
var localDecoder = require('../../../babelify-src/solidity/localDecoder')
/*
Decode local variable
*/
function decodeLocal (st, index, traceManager, callTree, verifier) {
try {
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)
}
})
} catch (e) {
st.fail(e.message)
}
}
module.exports = {
decodeLocals: decodeLocal
}
'use strict'
var TraceManager = require('../../../babelify-src/trace/traceManager')
var CodeManager = require('../../../babelify-src/code/codeManager')
var vmSendTx = require('./vmCall')
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 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, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
try {
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')
} catch (e) {
st.fail(e.message)
}
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])
}
})
}
})
}
})
}
'use strict'
var TraceManager = require('../../../babelify-src/trace/traceManager')
var CodeManager = require('../../../babelify-src/code/codeManager')
var vmSendTx = require('./vmCall')
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 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, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 70, traceManager, callTree, function (locals) {
try {
st.equals(locals['boolFalse'], false)
st.equals(locals['boolTrue'], true)
st.equals(locals['testEnum'], 'three')
st.equals(locals['sender'], '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB')
st.equals(locals['_bytes1'], '0x99')
st.equals(locals['__bytes1'], '0x99')
st.equals(locals['__bytes2'], '0x99AB')
st.equals(locals['__bytes4'], '0x99FA0000')
st.equals(locals['__bytes6'], '0x990000000000')
st.equals(locals['__bytes7'], '0x99356700000000')
st.equals(locals['__bytes8'], '0x99ABD41700000000')
st.equals(locals['__bytes9'], '0x99156744AF00000000')
st.equals(locals['__bytes13'], '0x99123423425300000000000000')
st.equals(locals['__bytes16'], '0x99AFAD23432400000000000000000000')
st.equals(locals['__bytes24'], '0x99AFAD234324000000000000000000000000000000000000')
st.equals(locals['__bytes32'], '0x9999ABD41799ABD4170000000000000000000000000000000000000000000000')
st.equals(Object.keys(locals).length, 16)
} catch (e) {
st.fail(e.message)
}
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
st.equals(locals['boolFalse'], false)
st.equals(locals['boolTrue'], false)
st.equals(locals['testEnum'], 'one')
st.equals(locals['sender'], '0x0000000000000000000000000000000000000000')
st.equals(locals['_bytes1'], '0x')
st.equals(locals['__bytes1'], '0x')
st.equals(locals['__bytes2'], '0x')
st.equals(locals['__bytes4'], '0x')
st.equals(locals['__bytes6'], '0x')
st.equals(locals['__bytes7'], '0x')
st.equals(locals['__bytes8'], '0x')
st.equals(locals['__bytes9'], '0x')
st.equals(locals['__bytes13'], '0x')
st.equals(locals['__bytes16'], '0x')
st.equals(locals['__bytes24'], '0x')
st.equals(locals['__bytes32'], '0x')
st.equals(Object.keys(locals).length, 16)
} catch (e) {
st.fail(e.message)
}
cb()
})
})
traceManager.resolveTrace(tx, (error, result) => {
if (error) {
st.fail(error)
} else {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}
})
}
})
}
})
}
'use strict'
var TraceManager = require('../../../babelify-src/trace/traceManager')
var CodeManager = require('../../../babelify-src/code/codeManager')
var vmSendTx = require('./vmCall')
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 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, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 72, traceManager, callTree, function (locals) {
try {
st.equals(locals['dynbytes'].value, '0x64796e616d69636279746573')
st.equals(locals['smallstring'].value, 'test_test_test')
st.equals(Object.keys(locals).length, 2)
} catch (e) {
st.fail(e.message)
}
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
st.equals(Object.keys(locals).length, 2)
} catch (e) {
st.fail(e.message)
}
cb()
})
})
traceManager.resolveTrace(tx, (error, result) => {
if (error) {
st.fail(error)
} else {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}
})
}
})
}
})
}
'use strict'
var TraceManager = require('../../../babelify-src/trace/traceManager')
var CodeManager = require('../../../babelify-src/code/codeManager')
var vmSendTx = require('./vmCall')
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 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, { includeLocalVariables: true })
callTree.event.register('callTreeBuildFailed', (error) => {
st.fail(error)
})
callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
helper.decodeLocals(st, 1814, traceManager, callTree, function (locals) {
try {
st.equals(locals['bytesSimple'].length, '0x14')
st.equals(locals['bytesSimple'].value, '0x746573745f7375706572')
st.equals(locals['e']['a'].value, 'test')
st.equals(locals['e']['a'].length, '0x8')
st.equals(locals['e']['a'].raw, '0x74657374')
st.equals(locals['e']['b'], '5')
st.equals(locals['e']['c'].length, '0x220')
st.equals(locals['e']['c'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374')
st.equals(locals['e']['c'].value, 'test_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_test')
st.equals(locals['e']['d'], '3')
st.equals(locals['f'].length, '0x1b8')
st.equals(locals['f'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f')
st.equals(locals['f'].value, 'test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_test_long_')
st.equals(locals['e']['e'], true)
st.equals(locals['simpleArray'][0], '45')
st.equals(locals['simpleArray'][1], '324324')
st.equals(locals['simpleArray'][2], '-333')
st.equals(locals['simpleArray'][3], '5656')
st.equals(locals['simpleArray'][4], '-1111')
st.equals(locals['stringArray'][0].value, 'long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_long_one_')
st.equals(locals['stringArray'][1].value, 'two')
st.equals(locals['stringArray'][2].value, 'three')
st.equals(locals['dynArray'][0][0], '3423423532')
st.equals(locals['dynArray'][1][0], '-342343323532')
st.equals(locals['dynArray'][1][1], '23432')
st.equals(locals['dynArray'][2][0], '-432432')
st.equals(locals['dynArray'][2][1], '3423423532')
st.equals(locals['dynArray'][2][2], '-432432')
st.equals(locals['structArray'][0]['a'].value, 'test')
st.equals(locals['structArray'][0]['a'].length, '0x8')
st.equals(locals['structArray'][0]['a'].raw, '0x74657374')
st.equals(locals['structArray'][0]['b'], '5')
st.equals(locals['structArray'][0]['c'].length, '0x220')
st.equals(locals['structArray'][0]['c'].raw, '0x746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374746573745f6c6f6e675f746573745f6c6f6e675f746573745f6c6f6e675f74657374')
st.equals(locals['structArray'][0]['c'].value, 'test_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_testtest_long_test_long_test_long_test')
st.equals(locals['structArray'][0]['d'], '3')
st.equals(locals['structArray'][0]['e'], true)
st.equals(locals['structArray'][1]['a'].value, 'item1 a')
st.equals(locals['structArray'][1]['b'], '20')
st.equals(locals['structArray'][1]['c'].value, 'item1 c')
st.equals(locals['structArray'][1]['d'], '-45')
st.equals(locals['structArray'][1]['e'], false)
st.equals(locals['structArray'][2]['a'].value, 'item2 a')
st.equals(locals['structArray'][2]['b'], '200')
st.equals(locals['structArray'][2]['c'].value, 'item2 c')
st.equals(locals['structArray'][2]['d'], '-450')
st.equals(locals['structArray'][2]['e'], true)
st.equals(locals['arrayStruct'].a[0].value, 'string')
st.equals(locals['arrayStruct'].b[0], '34')
st.equals(locals['arrayStruct'].b[1], '-23')
st.equals(locals['arrayStruct'].b[2], '-3')
st.equals(locals['arrayStruct'].c, 'three')
st.equals(Object.keys(locals).length, 8)
} catch (e) {
st.fail(e.message)
}
})
helper.decodeLocals(st, 7, traceManager, callTree, function (locals) {
try {
st.equals(Object.keys(locals).length, 8)
} catch (e) {
st.fail(e.message)
}
cb()
})
})
traceManager.resolveTrace(tx, (error, result) => {
if (error) {
st.fail(error)
} else {
debuggerEvent.trigger('newTraceLoaded', [traceManager.trace])
}
})
}
})
}
})
}
'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
......@@ -8,43 +8,43 @@ tape('solidity', function (t) {
t.test('storage location', function (st) {
var output = compiler.compile(contracts, 0)
var stateDec = index.solidity.stateDecoder.extractStateVariables('contractUint', output.sources)
checkLocation(st, stateDec[0].location, 0, 0)
checkLocation(st, stateDec[1].location, 1, 0)
checkLocation(st, stateDec[2].location, 2, 0)
checkLocation(st, stateDec[3].location, 3, 0)
checkLocation(st, stateDec[0].storagelocation, 0, 0)
checkLocation(st, stateDec[1].storagelocation, 1, 0)
checkLocation(st, stateDec[2].storagelocation, 2, 0)
checkLocation(st, stateDec[3].storagelocation, 3, 0)
stateDec = index.solidity.stateDecoder.extractStateVariables('contractStructAndArray', output.sources)
checkLocation(st, stateDec[0].location, 0, 0)
checkLocation(st, stateDec[1].location, 2, 0)
checkLocation(st, stateDec[2].location, 8, 0)
checkLocation(st, stateDec[0].storagelocation, 0, 0)
checkLocation(st, stateDec[1].storagelocation, 2, 0)
checkLocation(st, stateDec[2].storagelocation, 8, 0)
stateDec = index.solidity.stateDecoder.extractStateVariables('contractArray', output.sources)
checkLocation(st, stateDec[0].location, 0, 0)
checkLocation(st, stateDec[1].location, 1, 0)
checkLocation(st, stateDec[2].location, 2, 0)
checkLocation(st, stateDec[0].storagelocation, 0, 0)
checkLocation(st, stateDec[1].storagelocation, 1, 0)
checkLocation(st, stateDec[2].storagelocation, 2, 0)
stateDec = index.solidity.stateDecoder.extractStateVariables('contractSmallVariable', output.sources)
checkLocation(st, stateDec[0].location, 0, 0)
checkLocation(st, stateDec[1].location, 0, 1)
checkLocation(st, stateDec[2].location, 0, 2)
checkLocation(st, stateDec[3].location, 0, 4)
checkLocation(st, stateDec[4].location, 1, 0)
checkLocation(st, stateDec[5].location, 2, 0)
checkLocation(st, stateDec[0].storagelocation, 0, 0)
checkLocation(st, stateDec[1].storagelocation, 0, 1)
checkLocation(st, stateDec[2].storagelocation, 0, 2)
checkLocation(st, stateDec[3].storagelocation, 0, 4)
checkLocation(st, stateDec[4].storagelocation, 1, 0)
checkLocation(st, stateDec[5].storagelocation, 2, 0)
stateDec = index.solidity.stateDecoder.extractStateVariables('testSimpleStorage', output.sources)
checkLocation(st, stateDec[0].location, 0, 0)
checkLocation(st, stateDec[1].location, 1, 0)
checkLocation(st, stateDec[2].location, 2, 0)
checkLocation(st, stateDec[3].location, 3, 0)
checkLocation(st, stateDec[4].location, 4, 0)
checkLocation(st, stateDec[5].location, 8, 0)
checkLocation(st, stateDec[6].location, 9, 0)
checkLocation(st, stateDec[8].location, 17, 0)
checkLocation(st, stateDec[9].location, 17, 4)
checkLocation(st, stateDec[10].location, 17, 6)
checkLocation(st, stateDec[11].location, 17, 7)
checkLocation(st, stateDec[12].location, 18, 0)
checkLocation(st, stateDec[13].location, 21, 0)
checkLocation(st, stateDec[0].storagelocation, 0, 0)
checkLocation(st, stateDec[1].storagelocation, 1, 0)
checkLocation(st, stateDec[2].storagelocation, 2, 0)
checkLocation(st, stateDec[3].storagelocation, 3, 0)
checkLocation(st, stateDec[4].storagelocation, 4, 0)
checkLocation(st, stateDec[5].storagelocation, 8, 0)
checkLocation(st, stateDec[6].storagelocation, 9, 0)
checkLocation(st, stateDec[8].storagelocation, 17, 0)
checkLocation(st, stateDec[9].storagelocation, 17, 4)
checkLocation(st, stateDec[10].storagelocation, 17, 6)
checkLocation(st, stateDec[11].storagelocation, 17, 7)
checkLocation(st, stateDec[12].storagelocation, 18, 0)
checkLocation(st, stateDec[13].storagelocation, 21, 0)
st.end()
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment