Commit e7c45d29 authored by yann300's avatar yann300

use es6 class for type

parent d2da5fd6
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
var ValueType = require('./ValueType')
function Address () { class Address extends ValueType {
this.storageSlots = 1 constructor () {
this.storageBytes = 20 super(1, 20, 'address')
this.typeName = 'address' }
}
Address.prototype.decodeFromStorage = function (location, storageContent) { decodeFromStorage (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes) var value = util.extractHexValue(location, storageContent, this.storageBytes)
return '0x' + value.toUpperCase() return '0x' + value.toUpperCase()
} }
Address.prototype.decodeLocals = function (stackDepth, stack, memory) { decodeLocals (stackDepth, stack, memory) {
if (stackDepth >= stack.length) { if (stackDepth >= stack.length) {
return '0x0000000000000000000000000000000000000000' return '0x0000000000000000000000000000000000000000'
} else { } else {
return '0x' + util.extractHexByteSlice(stack[stack.length - 1 - stackDepth], this.storageBytes, 0) return '0x' + util.extractHexByteSlice(stack[stack.length - 1 - stackDepth], this.storageBytes, 0)
}
} }
}
Address.prototype.decodeFromMemory = function (offset, memory) { decodeFromMemory (offset, memory) {
var value = memory.substr(offset, 64) var value = memory.substr(offset, 64)
value = util.extractHexByteSlice(value, this.storageBytes, 0) value = util.extractHexByteSlice(value, this.storageBytes, 0)
return value return value
}
} }
module.exports = Address module.exports = Address
...@@ -2,84 +2,88 @@ ...@@ -2,84 +2,88 @@
var util = require('./util') var util = require('./util')
var BN = require('ethereumjs-util').BN var BN = require('ethereumjs-util').BN
function ArrayType (underlyingType, arraySize) { class ArrayType {
this.typeName = 'array'
this.storageBytes = 32 constructor (underlyingType, arraySize) {
this.underlyingType = underlyingType this.typeName = 'array'
this.arraySize = arraySize this.storageBytes = 32
this.storageSlots = null this.underlyingType = underlyingType
if (arraySize === 'dynamic') { this.arraySize = arraySize
this.storageSlots = 1 this.storageSlots = null
} else { if (arraySize === 'dynamic') {
if (underlyingType.storageBytes < 32) { this.storageSlots = 1
var itemPerSlot = Math.floor(32 / underlyingType.storageBytes)
this.storageSlots = Math.ceil(arraySize / itemPerSlot)
} else { } else {
this.storageSlots = arraySize * underlyingType.storageSlots if (underlyingType.storageBytes < 32) {
var itemPerSlot = Math.floor(32 / underlyingType.storageBytes)
this.storageSlots = Math.ceil(arraySize / itemPerSlot)
} else {
this.storageSlots = arraySize * underlyingType.storageSlots
}
} }
} }
}
ArrayType.prototype.decodeFromStorage = function (location, storageContent) { decodeFromStorage (location, storageContent) {
var ret = [] var ret = []
var size = null var size = null
var slotValue = util.extractHexValue(location, storageContent, this.storageBytes) var slotValue = util.extractHexValue(location, storageContent, this.storageBytes)
var currentLocation = { var currentLocation = {
offset: 0, offset: 0,
slot: location.slot slot: location.slot
} }
if (this.arraySize === 'dynamic') { if (this.arraySize === 'dynamic') {
size = util.toBN('0x' + slotValue) size = util.toBN('0x' + slotValue)
currentLocation.slot = util.sha3(location.slot) currentLocation.slot = util.sha3(location.slot)
} else { } else {
size = new BN(this.arraySize) size = new BN(this.arraySize)
} }
var k = util.toBN(0) var k = util.toBN(0)
for (; k.lt(size) && k.ltn(300); k.iaddn(1)) { for (; k.lt(size) && k.ltn(300); k.iaddn(1)) {
ret.push(this.underlyingType.decodeFromStorage(currentLocation, storageContent)) ret.push(this.underlyingType.decodeFromStorage(currentLocation, storageContent))
if (this.underlyingType.storageSlots === 1 && location.offset + this.underlyingType.storageBytes <= 32) { if (this.underlyingType.storageSlots === 1 && location.offset + this.underlyingType.storageBytes <= 32) {
currentLocation.offset += this.underlyingType.storageBytes currentLocation.offset += this.underlyingType.storageBytes
if (currentLocation.offset + this.underlyingType.storageBytes > 32) { 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.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) return {
currentLocation.offset = 0 value: ret,
length: '0x' + size.toString(16)
} }
} }
return {
value: ret,
length: '0x' + size.toString(16)
}
}
ArrayType.prototype.decodeLocals = function (stackDepth, stack, memory) { decodeLocals (stackDepth, stack, memory) {
if (stack.length - 1 < stackDepth) { if (stack.length - 1 < stackDepth) {
return [] return []
} else { // TODO manage decoding locals from storage } else { // TODO manage decoding locals from storage
var offset = stack[stack.length - 1 - stackDepth] var offset = stack[stack.length - 1 - stackDepth]
offset = 2 * parseInt(offset, 16) offset = 2 * parseInt(offset, 16)
return this.decodeFromMemory(offset, memory) return this.decodeFromMemory(offset, memory)
}
} }
}
ArrayType.prototype.decodeFromMemory = function (offset, memory) { decodeFromMemory (offset, memory) {
var ret = [] var ret = []
var length = extractLength(this, offset, memory) var length = extractLength(this, offset, memory)
if (this.arraySize === 'dynamic') { if (this.arraySize === 'dynamic') {
offset = offset + 64 offset = offset + 64
} }
for (var k = 0; k < length; k++) { for (var k = 0; k < length; k++) {
var contentOffset = offset var contentOffset = offset
if (this.underlyingType.typeName === 'bytes' || this.underlyingType.typeName === 'string' || this.underlyingType.typeName === 'array' || this.underlyingType.typeName === 'struct') { if (this.underlyingType.typeName === 'bytes' || this.underlyingType.typeName === 'string' || this.underlyingType.typeName === 'array' || this.underlyingType.typeName === 'struct') {
contentOffset = memory.substr(offset, 64) contentOffset = memory.substr(offset, 64)
contentOffset = 2 * parseInt(contentOffset, 16) contentOffset = 2 * parseInt(contentOffset, 16)
}
ret.push(this.underlyingType.decodeFromMemory(contentOffset, memory))
offset += 64
} }
ret.push(this.underlyingType.decodeFromMemory(contentOffset, memory)) return ret
offset += 64
} }
return ret
} }
function extractLength (type, offset, memory) { function extractLength (type, offset, memory) {
......
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
var ValueType = require('./ValueType')
function Bool () { class Bool extends ValueType {
this.storageSlots = 1 constructor () {
this.storageBytes = 1 super(1, 1, 'bool')
this.typeName = 'bool' }
} }
Bool.prototype.decodeFromStorage = function (location, storageContent) { Bool.prototype.decodeFromStorage = function (location, storageContent) {
......
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
var BN = require('ethereumjs-util').BN var BN = require('ethereumjs-util').BN
var ValueType = require('./ValueType')
function DynamicByteArray () { class DynamicByteArray extends ValueType {
this.storageSlots = 1 constructor () {
this.storageBytes = 32 super(1, 32, 'bytes')
this.typeName = 'bytes'
}
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)
}
} 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)
}
} }
}
DynamicByteArray.prototype.decodeLocals = function (stackDepth, stack, memory) { decodeFromStorage (location, storageContent) {
if (stack.length - 1 < stackDepth) { var value = util.extractHexValue(location, storageContent, this.storageBytes)
return { var bn = new BN(value, 16)
value: '0x', if (bn.testn(0)) {
length: '0x0' 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 offset = stack[stack.length - 1 - stackDepth]
offset = 2 * parseInt(offset, 16)
return this.decodeFromMemory(offset, memory)
} }
}
DynamicByteArray.prototype.decodeFromMemory = function (offset, memory) { decodeLocals (stackDepth, stack, memory) {
var length = memory.substr(offset, 64) if (stack.length - 1 < stackDepth) {
length = 2 * parseInt(length, 16) return {
return { value: '0x',
length: '0x' + length.toString(16), length: '0x0'
value: '0x' + memory.substr(offset + 64, length) }
} else {
var offset = stack[stack.length - 1 - stackDepth]
offset = 2 * parseInt(offset, 16)
return this.decodeFromMemory(offset, memory)
}
} }
}
DynamicByteArray.prototype.decodeLocals = function (stackDepth, stack, memory) { decodeFromMemory (offset, memory) {
if (stack.length - 1 < stackDepth) { var length = memory.substr(offset, 64)
length = 2 * parseInt(length, 16)
return { return {
value: '0x', length: '0x' + length.toString(16),
length: '0x0' value: '0x' + memory.substr(offset + 64, length)
} }
} else {
var offset = stack[stack.length - 1 - stackDepth]
offset = 2 * parseInt(offset, 16)
return this.decodeFromMemory(offset, memory)
}
}
DynamicByteArray.prototype.decodeFromMemory = function (offset, memory) {
var length = memory.substr(offset, 64)
length = 2 * parseInt(length, 16)
return {
length: '0x' + length.toString(16),
value: '0x' + memory.substr(offset + 64, length)
} }
} }
......
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
var ValueType = require('./ValueType')
function Enum (enumDef) { class Enum extends ValueType {
this.enumDef = enumDef constructor (enumDef) {
this.typeName = 'enum' var storageBytes = 0
this.storageSlots = 1 var length = enumDef.children.length
var length = enumDef.children.length while (length > 1) {
this.storageBytes = 0 length = length / 256
while (length > 1) { storageBytes++
length = length / 256 }
this.storageBytes++ super(1, storageBytes, 'enum')
this.enumDef = enumDef
} }
} }
......
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
var ValueType = require('./ValueType')
function FixedByteArray (storageBytes) { class FixedByteArray extends ValueType {
this.storageSlots = 1 constructor (storageBytes) {
this.storageBytes = storageBytes super(1, storageBytes, 'bytesX')
this.typeName = 'bytesX' }
}
FixedByteArray.prototype.decodeFromStorage = function (location, storageContent) { decodeFromStorage (location, storageContent) {
var value = util.extractHexValue(location, storageContent, this.storageBytes) var value = util.extractHexValue(location, storageContent, this.storageBytes)
return '0x' + value.toUpperCase() return '0x' + value.toUpperCase()
} }
FixedByteArray.prototype.decodeLocals = function (stackDepth, stack, memory) { decodeLocals (stackDepth, stack, memory) {
if (stack.length - 1 < stackDepth) { if (stack.length - 1 < stackDepth) {
return '0x' return '0x'
} else { } else {
var value = stack[stack.length - 1 - stackDepth] var value = stack[stack.length - 1 - stackDepth]
return '0x' + value.substr(2, 2 * this.storageBytes).toUpperCase() return '0x' + value.substr(2, 2 * this.storageBytes).toUpperCase()
}
} }
}
FixedByteArray.prototype.decodeFromMemory = function (offset, memory) { decodeFromMemory (offset, memory) {
var value = memory.substr(offset, 64) var value = memory.substr(offset, 64)
return util.extractHexByteSlice(value, this.storageBytes, 0).toUpperCase() return util.extractHexByteSlice(value, this.storageBytes, 0).toUpperCase()
}
} }
module.exports = FixedByteArray module.exports = FixedByteArray
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
var ValueType = require('./ValueType')
function Int (storageBytes) { class Int extends ValueType {
this.storageSlots = 1 constructor (storageBytes) {
this.storageBytes = storageBytes super(1, storageBytes, 'int')
this.typeName = 'int' }
} }
Int.prototype.decodeFromStorage = function (location, storageContent) { Int.prototype.decodeFromStorage = function (location, storageContent) {
......
'use strict' 'use strict'
function Mapping () { class Mapping {
this.storageSlots = 1 constructor () {
this.storageBytes = 32 this.storageSlots = 1
this.typeName = 'mapping' this.storageBytes = 32
} this.typeName = 'mapping'
}
Mapping.prototype.decodeFromStorage = function (location, storageContent) { decodeFromStorage (location, storageContent) {
return '<not implemented>' return '<not implemented>'
}
} }
module.exports = Mapping module.exports = Mapping
'use strict' 'use strict'
var DynamicBytes = require('./DynamicByteArray') var DynamicBytes = require('./DynamicByteArray')
function StringType () { class StringType extends DynamicBytes {
this.storageSlots = 1 constructor () {
this.storageBytes = 32 super()
this.typeName = 'string' this.typeName = 'string'
this.dynamicBytes = new DynamicBytes() }
}
StringType.prototype.decodeFromStorage = function (location, storageContent) {
var decoded = this.dynamicBytes.decodeFromStorage(location, storageContent)
return format(decoded)
}
StringType.prototype.decodeLocals = function (stackDepth, stack, memory) { decodeFromStorage (location, storageContent) {
var decoded = this.dynamicBytes.decodeLocals(stackDepth, stack, memory) var decoded = super.decodeFromStorage(location, storageContent)
return format(decoded) return format(decoded)
} }
StringType.prototype.decodeFromMemory = function (offset, memory) { decodeLocals (stackDepth, stack, memory) {
var decoded = this.dynamicBytes.decodeFromMemory(offset, memory) var decoded = super.decodeLocals(stackDepth, stack, memory)
return format(decoded) return format(decoded)
} }
StringType.prototype.decodeFromMemory = function (offset, memory) { decodeFromMemory (offset, memory) {
var decoded = this.dynamicBytes.decodeFromMemory(offset, memory) var decoded = super.decodeFromMemory(offset, memory)
return format(decoded) return format(decoded)
}
} }
function format (decoded) { function format (decoded) {
......
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
function Struct (memberDetails) { class Struct {
this.storageSlots = memberDetails.storageSlots constructor (memberDetails) {
this.storageBytes = 32 this.storageSlots = memberDetails.storageSlots
this.members = memberDetails.members this.storageBytes = 32
this.typeName = 'struct' this.members = memberDetails.members
} this.typeName = 'struct'
}
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
}
Struct.prototype.decodeLocals = function (stackDepth, stack, memory) { decodeFromStorage (location, storageContent) {
if (stack.length - 1 < stackDepth) { var ret = {}
return {} this.members.map(function (item, i) {
} else { // TODO manage decoding locals from storage var globalLocation = {
var offset = stack[stack.length - 1 - stackDepth] offset: location.offset + item.location.offset,
offset = 2 * parseInt(offset, 16) slot: util.add(location.slot, item.location.slot)
return this.decodeFromMemory(offset, memory) }
ret[item.name] = item.type.decodeFromStorage(globalLocation, storageContent)
})
return ret
} }
}
Struct.prototype.decodeFromMemory = function (offset, memory) { decodeLocals (stackDepth, stack, memory) {
var ret = {} if (stack.length - 1 < stackDepth) {
this.members.map(function (item, i) { return {}
var contentOffset = offset } else { // TODO manage decoding locals from storage
if (item.type.typeName === 'bytes' || item.type.typeName === 'string' || item.type.typeName === 'array' || item.type.typeName === 'struct') { var offset = stack[stack.length - 1 - stackDepth]
contentOffset = memory.substr(offset, 64) offset = 2 * parseInt(offset, 16)
contentOffset = 2 * parseInt(contentOffset, 16) return this.decodeFromMemory(offset, memory)
} }
var member = item.type.decodeFromMemory(contentOffset, memory)
ret[item.name] = member
offset += 64
})
return ret
}
Struct.prototype.decodeLocals = function (stackDepth, stack, memory) {
if (stack.length - 1 < stackDepth) {
return {}
} else { // TODO manage decoding locals from storage
var offset = stack[stack.length - 1 - stackDepth]
offset = 2 * parseInt(offset, 16)
return this.decodeFromMemory(offset, memory)
} }
}
Struct.prototype.decodeFromMemory = function (offset, memory) { decodeFromMemory (offset, memory) {
var ret = {} var ret = {}
this.members.map(function (item, i) { this.members.map(function (item, i) {
var contentOffset = offset var contentOffset = offset
if (item.type.typeName === 'bytes' || item.type.typeName === 'string' || item.type.typeName === 'array' || item.type.typeName === 'struct') { if (item.type.typeName === 'bytes' || item.type.typeName === 'string' || item.type.typeName === 'array' || item.type.typeName === 'struct') {
contentOffset = memory.substr(offset, 64) contentOffset = memory.substr(offset, 64)
contentOffset = 2 * parseInt(contentOffset, 16) contentOffset = 2 * parseInt(contentOffset, 16)
} }
var member = item.type.decodeFromMemory(contentOffset, memory) var member = item.type.decodeFromMemory(contentOffset, memory)
ret[item.name] = member ret[item.name] = member
offset += 64 offset += 64
}) })
return ret return ret
}
} }
module.exports = Struct module.exports = Struct
'use strict' 'use strict'
var util = require('./util') var util = require('./util')
var ValueType = require('./ValueType')
function Uint (storageBytes) { class Uint extends ValueType {
this.storageSlots = 1 constructor (storageBytes) {
this.storageBytes = storageBytes super(1, storageBytes, 'uint')
this.typeName = 'uint' }
} }
Uint.prototype.decodeFromStorage = function (location, storageContent) { Uint.prototype.decodeFromStorage = function (location, storageContent) {
......
'use strict'
class ValueType {
constructor (storageSlots, storageBytes, typeName) {
this.storageSlots = storageSlots
this.storageBytes = storageBytes
this.typeName = typeName
}
}
module.exports = ValueType
...@@ -132,7 +132,7 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId) { ...@@ -132,7 +132,7 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId) {
tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = { tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = {
name: variableDeclaration.attributes.name, name: variableDeclaration.attributes.name,
type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName), type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName),
stackDepth: stack.stackDepth stackDepth: stack.length
} }
} }
}) })
......
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