Merge pull request #136 from ethereum/typeDecoder

Storage decoder
pull/7/head
chriseth 8 years ago committed by GitHub
commit 1fa65e79ad
  1. 4
      src/index.js
  2. 146
      src/solidity/decodeInfo.js
  3. 82
      src/solidity/stateDecoder.js
  4. 13
      src/solidity/types/Address.js
  5. 25
      src/solidity/types/ArrayType.js
  6. 13
      src/solidity/types/Bool.js
  7. 13
      src/solidity/types/DynamicByteArray.js
  8. 19
      src/solidity/types/Enum.js
  9. 13
      src/solidity/types/FixedByteArray.js
  10. 13
      src/solidity/types/Int.js
  11. 13
      src/solidity/types/StringType.js
  12. 14
      src/solidity/types/Struct.js
  13. 13
      src/solidity/types/Uint.js
  14. 104
      test/decodeInfo.js
  15. 80
      test/solidity/contracts.js
  16. 63
      test/solidity/decodeInfo.js
  17. 57
      test/solidity/storageLocation.js
  18. 3
      test/tests.js

@ -8,6 +8,7 @@ var disassembler = require('./code/disassembler')
var SourceMappingDecoder = require('./util/sourceMappingDecoder') var SourceMappingDecoder = require('./util/sourceMappingDecoder')
var AstWalker = require('./util/astWalker') var AstWalker = require('./util/astWalker')
var decodeInfo = require('./solidity/decodeInfo') var decodeInfo = require('./solidity/decodeInfo')
var stateDecoder = require('./solidity/stateDecoder')
var astHelper = require('./solidity/astHelper') var astHelper = require('./solidity/astHelper')
if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') { if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') {
@ -38,7 +39,8 @@ function modules () {
}, },
solidity: { solidity: {
decodeInfo: decodeInfo, decodeInfo: decodeInfo,
astHelper: astHelper astHelper: astHelper,
stateDecoder: stateDecoder
} }
} }
} }

@ -1,153 +1,118 @@
'use strict' 'use strict'
var AddressType = require('./types/Address')
var ArrayType = require('./types/ArrayType')
var BoolType = require('./types/Bool')
var BytesType = require('./types/DynamicByteArray')
var BytesXType = require('./types/FixedByteArray')
var EnumType = require('./types/Enum')
var StringType = require('./types/StringType')
var StructType = require('./types/Struct')
var IntType = require('./types/Int')
var UintType = require('./types/Uint')
/** /**
* Uint decode the given @arg type * Uint decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g uint256, uint32) * @param {String} type - type given by the AST (e.g uint256, uint32)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName} * @return {Object} returns decoded info about the current type: { storageBytes, typeName}
*/ */
function Uint (type) { function Uint (type) {
type === 'uint' ? 'uint256' : type type === 'uint' ? 'uint256' : type
return { var storageBytes = parseInt(type.replace('uint', '')) / 8
needsFreeStorageSlot: false, return new UintType(storageBytes)
storageBytes: parseInt(type.replace('uint', '')) / 8,
typeName: type
}
} }
/** /**
* Int decode the given @arg type * Int decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g int256, int32) * @param {String} type - type given by the AST (e.g int256, int32)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName} * @return {Object} returns decoded info about the current type: { storageBytes, typeName}
*/ */
function Int (type) { function Int (type) {
type === 'int' ? 'int256' : type type === 'int' ? 'int256' : type
return { var storageBytes = parseInt(type.replace('int', '')) / 8
needsFreeStorageSlot: false, return new IntType(storageBytes)
storageBytes: parseInt(type.replace('int', '')) / 8,
typeName: type
}
} }
/** /**
* Address decode the given @arg type * Address decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g address) * @param {String} type - type given by the AST (e.g address)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName} * @return {Object} returns decoded info about the current type: { storageBytes, typeName}
*/ */
function Address (type) { function Address (type) {
return { return new AddressType()
needsFreeStorageSlot: false,
storageBytes: 20,
typeName: 'address'
}
} }
/** /**
* Bool decode the given @arg type * Bool decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g bool) * @param {String} type - type given by the AST (e.g bool)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName} * @return {Object} returns decoded info about the current type: { storageBytes, typeName}
*/ */
function Bool (type) { function Bool (type) {
return { return new BoolType()
needsFreeStorageSlot: false,
storageBytes: 1,
typeName: 'bool'
}
} }
/** /**
* DynamicByteArray decode the given @arg type * DynamicByteArray decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g bytes storage ref) * @param {String} type - type given by the AST (e.g bytes storage ref)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName} * @return {Object} returns decoded info about the current type: { storageBytes, typeName}
*/ */
function DynamicByteArray (type) { function DynamicByteArray (type) {
return { return new BytesType()
needsFreeStorageSlot: true,
storageBytes: 32,
typeName: 'bytes'
}
} }
/** /**
* FixedByteArray decode the given @arg type * FixedByteArray decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g bytes16) * @param {String} type - type given by the AST (e.g bytes16)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName} * @return {Object} returns decoded info about the current type: { storageBytes, typeName}
*/ */
function FixedByteArray (type) { function FixedByteArray (type) {
return { var storageBytes = parseInt(type.replace('bytes', ''))
needsFreeStorageSlot: false, return new BytesXType(storageBytes)
storageBytes: parseInt(type.replace('bytes', '')),
typeName: type
}
} }
/** /**
* StringType decode the given @arg type * StringType decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g string storage ref) * @param {String} type - type given by the AST (e.g string storage ref)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName} * @return {Object} returns decoded info about the current type: { storageBytes, typeName}
*/ */
function StringType (type) { function String (type) {
return { return new StringType()
needsFreeStorageSlot: true,
storageBytes: 32,
typeName: 'string'
}
} }
/** /**
* ArrayType decode the given @arg type * ArrayType decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g int256[] storage ref, int256[] storage ref[] storage ref) * @param {String} type - type given by the AST (e.g int256[] storage ref, int256[] storage ref[] storage ref)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName, arraySize, subArray} * @return {Object} returns decoded info about the current type: { storageBytes, typeName, arraySize, subArray}
*/ */
function ArrayType (type, stateDefinitions) { function Array (type, stateDefinitions) {
var arraySize var arraySize
var storageBytes
var match = type.match(/(.*)\[(.*?)\]( storage ref| storage pointer| memory| calldata)?$/) var match = type.match(/(.*)\[(.*?)\]( storage ref| storage pointer| memory| calldata)?$/)
if (!match || match.length < 3) { if (!match || match.length < 3) {
console.log('unable to parse type ' + type) console.log('unable to parse type ' + type)
return null return null
} }
arraySize = match[2] === '' ? 'dynamic' : parseInt(match[2]) arraySize = match[2] === '' ? 'dynamic' : parseInt(match[2])
var underlyingType = parseType(match[1], stateDefinitions)
var underlyingType = decode(match[1], stateDefinitions)
if (underlyingType === null) { if (underlyingType === null) {
console.log('unable to parse type ' + type) console.log('unable to parse type ' + type)
return null return null
} }
return new ArrayType(underlyingType, arraySize)
if (arraySize === 'dynamic') {
storageBytes = 32
} else {
storageBytes = underlyingType.storageBytes
if (storageBytes > 32) {
storageBytes = 32 * arraySize * Math.ceil(storageBytes / 32)
} else {
storageBytes = 32 * (arraySize / Math.floor(32 / storageBytes))
}
}
return {
needsFreeStorageSlot: true,
storageBytes: storageBytes,
typeName: type,
arraySize: arraySize,
underlyingType: underlyingType
}
} }
/** /**
* Enum decode the given @arg type * Enum decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g enum enumDef) * @param {String} type - type given by the AST (e.g enum enumDef)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName, enum} * @return {Object} returns decoded info about the current type: { storageBytes, typeName, enum}
*/ */
function Enum (type, stateDefinitions) { function Enum (type, stateDefinitions) {
var enumDef = getEnum(type, stateDefinitions) var enumDef = getEnum(type, stateDefinitions)
@ -155,25 +120,14 @@ function Enum (type, stateDefinitions) {
console.log('unable to retrieve decode info of ' + type) console.log('unable to retrieve decode info of ' + type)
return null return null
} }
var length = enumDef.children.length return new EnumType(enumDef)
var storageBytes = 0
while (length > 1) {
length = length / 256
storageBytes++
}
return {
needsFreeStorageSlot: false,
storageBytes: storageBytes,
typeName: type,
enum: enumDef
}
} }
/** /**
* Struct decode the given @arg type * Struct decode the given @arg type
* *
* @param {String} type - type given by the AST (e.g struct structDef storage ref) * @param {String} type - type given by the AST (e.g struct structDef storage ref)
* @return {Object} returns decoded info about the current type: { needsFreeStorageSlot, storageBytes, typeName, members} * @return {Object} returns decoded info about the current type: { storageBytes, typeName, members}
*/ */
function Struct (type, stateDefinitions) { function Struct (type, stateDefinitions) {
var match = type.match(/struct (.*?)( storage ref| storage pointer| memory| calldata)?$/) var match = type.match(/struct (.*?)( storage ref| storage pointer| memory| calldata)?$/)
@ -182,12 +136,7 @@ function Struct (type, stateDefinitions) {
} }
var memberDetails = getStructMembers(match[1], stateDefinitions) // type is used to extract the ast struct definition var memberDetails = getStructMembers(match[1], stateDefinitions) // type is used to extract the ast struct definition
if (!memberDetails) return null if (!memberDetails) return null
return { return new StructType(memberDetails)
needsFreeStorageSlot: true,
storageBytes: memberDetails.storageBytes,
typeName: type,
members: memberDetails.members
}
} }
/** /**
@ -200,7 +149,7 @@ function Struct (type, stateDefinitions) {
function getEnum (type, stateDefinitions) { function getEnum (type, stateDefinitions) {
for (var k in stateDefinitions) { for (var k in stateDefinitions) {
var dec = stateDefinitions[k] var dec = stateDefinitions[k]
if (type === 'enum ' + dec.attributes.name) { if (dec.attributes && dec.attributes.name && type === 'enum ' + dec.attributes.name) {
return dec return dec
} }
} }
@ -222,15 +171,12 @@ function getStructMembers (typeName, stateDefinitions) {
if (dec.name === 'StructDefinition' && typeName === dec.attributes.name) { if (dec.name === 'StructDefinition' && typeName === dec.attributes.name) {
for (var i in dec.children) { for (var i in dec.children) {
var member = dec.children[i] var member = dec.children[i]
var decoded = decode(member.attributes.type, stateDefinitions) var decoded = parseType(member.attributes.type, stateDefinitions)
if (!decoded) { if (!decoded) {
console.log('unable to retrieve decode info of ' + member.attributes.type) console.log('unable to retrieve decode info of ' + member.attributes.type)
return null return null
} }
members.push(decoded) members.push(decoded)
if (decoded.needsFreeStorageSlot) {
storageBytes = Math.ceil(storageBytes / 32) * 32
}
storageBytes += decoded.storageBytes storageBytes += decoded.storageBytes
} }
break break
@ -266,15 +212,15 @@ function typeClass (fullType) {
* @param {Object} stateDefinitions - all state stateDefinitions given by the AST (including struct and enum type declaration) * @param {Object} stateDefinitions - all state stateDefinitions given by the AST (including struct and enum type declaration)
* @return {Object} - return the corresponding decoder or null on error * @return {Object} - return the corresponding decoder or null on error
*/ */
function decode (type, stateDefinitions) { function parseType (type, stateDefinitions) {
var decodeInfos = { var decodeInfos = {
'address': Address, 'address': Address,
'array': ArrayType, 'array': Array,
'bool': Bool, 'bool': Bool,
'bytes': DynamicByteArray, 'bytes': DynamicByteArray,
'bytesX': FixedByteArray, 'bytesX': FixedByteArray,
'enum': Enum, 'enum': Enum,
'string': StringType, 'string': String,
'struct': Struct, 'struct': Struct,
'int': Int, 'int': Int,
'uint': Uint 'uint': Uint
@ -288,15 +234,15 @@ function decode (type, stateDefinitions) {
} }
module.exports = { module.exports = {
decode: decode, parseType: parseType,
Uint: Uint, Uint: Uint,
Address: Address, Address: Address,
Bool: Bool, Bool: Bool,
DynamicByteArray: DynamicByteArray, DynamicByteArray: DynamicByteArray,
FixedByteArray: FixedByteArray, FixedByteArray: FixedByteArray,
Int: Int, Int: Int,
StringType: StringType, String: String,
ArrayType: ArrayType, Array: Array,
Enum: Enum, Enum: Enum,
Struct: Struct Struct: Struct
} }

@ -0,0 +1,82 @@
var astHelper = require('./astHelper')
var decodeInfo = require('./decodeInfo')
/**
* decode the contract state storage
*
* @param {Array} storage location - location of all state variables
* @param {Map} storageContent - storage
* @return {Map} - decoded state variable
*/
function decodeState (stateVars, storageContent) {
var ret = {}
for (var k in stateVars) {
var stateVar = stateVars[k]
ret[stateVar.name] = stateVar.type.decodeFromStorage(stateVar.location, storageContent)
}
return ret
}
/**
* return all storage location variables of the given @arg contractName
*
* @param {String} contractName - name of the contract
* @param {Object} sourcesList - sources list
* @return {Object} - return the location of all contract variables in the storage
*/
function extractStateVariables (contractName, sourcesList) {
var stateDefinitions = astHelper.extractStateVariables(contractName, sourcesList)
var ret = []
if (!stateDefinitions) {
return ret
}
var location = {
offset: 0,
slot: 0
}
for (var k in stateDefinitions) {
var variable = stateDefinitions[k]
if (variable.name === 'VariableDeclaration') {
var type = decodeInfo.parseType(variable.attributes.type, stateDefinitions)
if (location.offset + type.storageBytes > 32) {
location.slot++
location.offset = 0
}
ret.push({
name: variable.attributes.name,
type: type,
location: {
offset: location.offset,
slot: location.slot
}
})
if (type.storageSlots === 1 && location.offset + type.storageBytes <= 32) {
location.offset += type.storageBytes
} else {
location.slot += type.storageSlots
location.offset = 0
}
}
}
return ret
}
/**
* return the state of the given @a contractName as a json object
*
* @param {Map} storageContent - contract storage
* @param {astList} astList - AST nodes of all the sources
* @param {String} contractName - contract for which state var should be resolved
* @return {Map} - return the state of the contract
*/
function solidityState (storageContent, astList, contractName) {
var stateVars = extractStateVariables(contractName, astList)
return decodeState(stateVars, storageContent)
}
module.exports = {
solidityState: solidityState,
extractStateVariables: extractStateVariables,
decodeState: decodeState
}

@ -0,0 +1,13 @@
'use strict'
function Address () {
this.storageSlots = 1
this.storageBytes = 20
this.typeName = 'address'
}
Address.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = Address

@ -0,0 +1,25 @@
'use strict'
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)
} else {
this.storageSlots = arraySize * underlyingType.storageSlots
}
}
}
ArrayType.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = ArrayType

@ -0,0 +1,13 @@
'use strict'
function Bool () {
this.storageSlots = 1
this.storageBytes = 1
this.typeName = 'bool'
}
Bool.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = Bool

@ -0,0 +1,13 @@
'use strict'
function DynamicByteArray () {
this.storageSlots = 1
this.storageBytes = 32
this.typeName = 'bytes'
}
DynamicByteArray.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = DynamicByteArray

@ -0,0 +1,19 @@
'use strict'
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++
}
}
Enum.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = Enum

@ -0,0 +1,13 @@
'use strict'
function FixedByteArray (storageBytes) {
this.storageSlots = 1
this.storageBytes = storageBytes
this.typeName = 'bytesX'
}
FixedByteArray.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = FixedByteArray

@ -0,0 +1,13 @@
'use strict'
function Int (storageBytes) {
this.storageSlots = 1
this.storageBytes = storageBytes
this.typeName = 'int'
}
Int.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = Int

@ -0,0 +1,13 @@
'use strict'
function StringType () {
this.storageSlots = 1
this.storageBytes = 32
this.typeName = 'string'
}
StringType.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = StringType

@ -0,0 +1,14 @@
'use strict'
function Struct (memberDetails) {
this.storageSlots = Math.ceil(memberDetails.storageBytes / 32)
this.storageBytes = 32
this.members = memberDetails.members
this.typeName = 'struct'
}
Struct.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = Struct

@ -0,0 +1,13 @@
'use strict'
function Uint (storageBytes) {
this.storageSlots = 1
this.storageBytes = storageBytes
this.typeName = 'uint'
}
Uint.prototype.decodeFromStorage = function (location, storageContent) {
return '<not implemented yet>'
}
module.exports = Uint

@ -1,104 +0,0 @@
'use strict'
var tape = require('tape')
var compiler = require('solc')
var index = require('../src/index')
tape('solidity', function (t) {
t.test('astHelper, decodeInfo', function (st) {
var output = compiler.compile(contracts, 0)
var stateDec = index.solidity.astHelper.extractStateVariables('contractUint', output.sources)
var decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 1, 'uint8')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 32, 'uint256')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 32, 'uint256')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[4].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 16, 'bytes16')
stateDec = index.solidity.astHelper.extractStateVariables('contractStructAndArray', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 64, 'struct structDef storage ref')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 192, 'struct structDef storage ref[3] storage ref')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 64, 'bytes12[4] storage ref')
stateDec = index.solidity.astHelper.extractStateVariables('contractArray', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 4 * 5, 'uint32[5] storage ref')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 32, 'int8[] storage ref')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 4 * 32, 'int16[] storage ref[3] storage ref[] storage ref[4] storage ref')
stateDec = index.solidity.astHelper.extractStateVariables('contractEnum', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 2, 'enum enumDef')
stateDec = index.solidity.astHelper.extractStateVariables('contractSmallVariable', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 1, 'int8')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 1, 'uint8')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 2, 'uint16')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 4, 'int32')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[4].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 32, 'uint256')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[5].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 2, 'int16')
st.end()
})
})
function checkDecodeInfo (st, decodeInfo, freeSlot, storageBytes, typeName, name) {
st.equal(decodeInfo.needsFreeStorageSlot, freeSlot)
st.equal(decodeInfo.storageBytes, storageBytes)
st.equal(decodeInfo.typeName, typeName)
}
var contracts = `
contract baseContract {
uint8 u;
}
contract contractUint is baseContract {
uint256 ui;
uint ui1;
bytes16 b;
}
contract contractStructAndArray {
struct structDef {
uint8 ui;
string str;
}
structDef structDec;
structDef[3] array;
bytes12[4] bytesArray;
}
contract contractArray {
uint32[5] i32st;
int8[] i8dyn;
int16[][3][][4] i16dyn;
}
contract contractEnum {
enum enumDef {item0,item1,item2,item3,item4,item5,item6,item7,item8,item9,item10,item11,item12,item13,item14,item15,item16,item17,item18,item19,item20,item21,item22,item23,item24,item25,item26,item27,item28,item29,item30,item31,item32,item33,item34,item35,item36,item37,item38,item39,item40,item41,item42,item43,item44,item45,item46,item47,item48,item49,item50,item51,item52,item53,item54,item55,item56,item57,item58,item59,item60,item61,item62,item63,item64,item65,item66,item67,item68,item69,item70,item71,item72,item73,item74,item75,item76,item77,item78,item79,item80,item81,item82,item83,item84,item85,item86,item87,item88,item89,item90,item91,item92,item93,item94,item95,item96,item97,item98,item99,item100,item101,item102,item103,item104,item105,item106,item107,item108,item109,item110,item111,item112,item113,item114,item115,item116,item117,item118,item119,item120,item121,item122,item123,item124,item125,item126,item127,item128,item129,item130,item131,item132,item133,item134,item135,item136,item137,item138,item139,item140,item141,item142,item143,item144,item145,item146,item147,item148,item149,item150,item151,item152,item153,item154,item155,item156,item157,item158,item159,item160,item161,item162,item163,item164,item165,item166,item167,item168,item169,item170,item171,item172,item173,item174,item175,item176,item177,item178,item179,item180,item181,item182,item183,item184,item185,item186,item187,item188,item189,item190,item191,item192,item193,item194,item195,item196,item197,item198,item199,item200,item201,item202,item203,item204,item205,item206,item207,item208,item209,item210,item211,item212,item213,item214,item215,item216,item217,item218,item219,item220,item221,item222,item223,item224,item225,item226,item227,item228,item229,item230,item231,item232,item233,item234,item235,item236,item237,item238,item239,item240,item241,item242,item243,item244,item245,item246,item247,item248,item249,item250,item251,item252,item253,item254,item255,item256,item257,item258,item259,item260,item261,item262,item263,item264,item265,item266,item267,item268,item269,item270,item271,item272,item273,item274,item275,item276,item277,item278,item279,item280,item281,item282,item283,item284,item285,item286,item287,item288,item289,item290,item291,item292,item293,item294,item295,item296,item297,item298,item299,item100000000}
enumDef enum1;
}
contract contractSmallVariable {
int8 i8;
uint8 iu8;
uint16 iu18;
int32 i32;
uint ui32;
int16 i16;
}
`

@ -0,0 +1,80 @@
'use strict'
module.exports = `
contract baseContract {
uint8 u;
}
contract contractUint is baseContract {
uint256 ui;
uint ui1;
bytes16 b;
}
contract contractStructAndArray {
struct structDef {
uint8 ui;
string str;
}
structDef structDec;
structDef[3] array;
bytes12[4] bytesArray;
}
contract contractArray {
uint32[5] i32st;
int8[] i8dyn;
int16[][3][][4] i16dyn;
}
contract contractEnum {
enum enumDef {item0,item1,item2,item3,item4,item5,item6,item7,item8,item9,item10,item11,item12,item13,item14,item15,item16,item17,item18,item19,item20,item21,item22,item23,item24,item25,item26,item27,item28,item29,item30,item31,item32,item33,item34,item35,item36,item37,item38,item39,item40,item41,item42,item43,item44,item45,item46,item47,item48,item49,item50,item51,item52,item53,item54,item55,item56,item57,item58,item59,item60,item61,item62,item63,item64,item65,item66,item67,item68,item69,item70,item71,item72,item73,item74,item75,item76,item77,item78,item79,item80,item81,item82,item83,item84,item85,item86,item87,item88,item89,item90,item91,item92,item93,item94,item95,item96,item97,item98,item99,item100,item101,item102,item103,item104,item105,item106,item107,item108,item109,item110,item111,item112,item113,item114,item115,item116,item117,item118,item119,item120,item121,item122,item123,item124,item125,item126,item127,item128,item129,item130,item131,item132,item133,item134,item135,item136,item137,item138,item139,item140,item141,item142,item143,item144,item145,item146,item147,item148,item149,item150,item151,item152,item153,item154,item155,item156,item157,item158,item159,item160,item161,item162,item163,item164,item165,item166,item167,item168,item169,item170,item171,item172,item173,item174,item175,item176,item177,item178,item179,item180,item181,item182,item183,item184,item185,item186,item187,item188,item189,item190,item191,item192,item193,item194,item195,item196,item197,item198,item199,item200,item201,item202,item203,item204,item205,item206,item207,item208,item209,item210,item211,item212,item213,item214,item215,item216,item217,item218,item219,item220,item221,item222,item223,item224,item225,item226,item227,item228,item229,item230,item231,item232,item233,item234,item235,item236,item237,item238,item239,item240,item241,item242,item243,item244,item245,item246,item247,item248,item249,item250,item251,item252,item253,item254,item255,item256,item257,item258,item259,item260,item261,item262,item263,item264,item265,item266,item267,item268,item269,item270,item271,item272,item273,item274,item275,item276,item277,item278,item279,item280,item281,item282,item283,item284,item285,item286,item287,item288,item289,item290,item291,item292,item293,item294,item295,item296,item297,item298,item299,item100000000}
enumDef enum1;
}
contract contractSmallVariable {
int8 i8;
uint8 iu8;
uint16 iu18;
int32 i32;
uint ui32;
int16 i16;
}
contract testSimpleStorage1 {
uint32 uibase1;
}
contract testSimpleStorage is testSimpleStorage1 {
uint ui1;
uint ui2;
uint[1] ui3;
uint[][1][4] ui4;
int16 i16;
struct structDef {
uint ui;
string str;
}
structDef structDec;
structDef[3] arrayStructDec;
int32 i32;
int16 i16_2;
enum enumDef {
first,
second,
third
}
enumDef enumDec;
bool boolean;
uint[][2][][3] ui5;
string _string;
}
`

@ -0,0 +1,63 @@
'use strict'
var tape = require('tape')
var compiler = require('solc')
var index = require('../../src/index')
var contracts = require('./contracts')
tape('solidity', function (t) {
t.test('astHelper, decodeInfo', function (st) {
var output = compiler.compile(contracts, 0)
var stateDec = index.solidity.astHelper.extractStateVariables('contractUint', output.sources)
var decodeInfo = index.solidity.decodeInfo.parseType(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[4].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 16, 'bytesX')
stateDec = index.solidity.astHelper.extractStateVariables('contractStructAndArray', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 2, 32, 'struct')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 6, 32, 'array')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 2, 32, 'array')
stateDec = index.solidity.astHelper.extractStateVariables('contractArray', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 32, 'array')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 32, 'array')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 4, 32, 'array')
stateDec = index.solidity.astHelper.extractStateVariables('contractEnum', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 2, 'enum')
stateDec = index.solidity.astHelper.extractStateVariables('contractSmallVariable', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 1, 'int')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 2, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 4, 'int')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[4].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[5].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, 1, 2, 'int')
st.end()
})
})
function checkDecodeInfo (st, decodeInfo, storageSlots, storageBytes, typeName) {
st.equal(decodeInfo.storageSlots, storageSlots)
st.equal(decodeInfo.storageBytes, storageBytes)
st.equal(decodeInfo.typeName, typeName)
}

@ -0,0 +1,57 @@
'use strict'
var tape = require('tape')
var compiler = require('solc')
var index = require('../../src/index')
var contracts = require('./contracts')
tape('solidity', function (t) {
t.test('astHelper, decodeInfo', 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)
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)
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)
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)
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)
st.end()
})
})
function checkLocation (st, location, slot, offset) {
st.equal(location.offset, offset)
st.equal(location.slot, slot)
}

@ -7,4 +7,5 @@ require('./astwalker.js')
require('./disassembler.js') require('./disassembler.js')
require('./eventManager.js') require('./eventManager.js')
require('./sourceMappingDecoder.js') require('./sourceMappingDecoder.js')
require('./decodeInfo.js') require('./solidity/decodeInfo.js')
require('./solidity/storageLocation.js')

Loading…
Cancel
Save