Commit fc1fa94c authored by yann300's avatar yann300

fix tests

parent 6a077270
...@@ -37,11 +37,14 @@ function getLinearizedBaseContracts (id, contractsById) { ...@@ -37,11 +37,14 @@ function getLinearizedBaseContracts (id, contractsById) {
* *
* @param {String} contractName - contract for which state var should be resolved * @param {String} contractName - contract for which state var should be resolved
* @param {Object} sourcesList - sources list (containing root AST node) * @param {Object} sourcesList - sources list (containing root AST node)
* @param {Object} [contracts] - map of contract definitions (contains contractsById, contractsByName)
* @return {Object} - return an object containing: stateItems - list of all the children node of the @arg contractName * @return {Object} - return an object containing: stateItems - list of all the children node of the @arg contractName
* stateVariables - list of all the variable declaration of the @arg contractName * stateVariables - list of all the variable declaration of the @arg contractName
*/ */
function extractState (contractName, sourcesList) { function extractStateDefinitions (contractName, sourcesList, contracts) {
var contracts = extractContractDefinitions(sourcesList) if (!contracts) {
contracts = extractContractDefinitions(sourcesList)
}
var node = contracts.contractsByName[contractName] var node = contracts.contractsByName[contractName]
if (node) { if (node) {
var stateItems = [] var stateItems = []
...@@ -59,15 +62,32 @@ function extractState (contractName, sourcesList) { ...@@ -59,15 +62,32 @@ function extractState (contractName, sourcesList) {
} }
} }
return { return {
stateItems: stateItems, stateDefinitions: stateItems,
stateVariables: stateVar stateVariables: stateVar
} }
} }
return null return null
} }
/**
* return state var and type definition of all the contracts from the given @args sourcesList
*
* @param {Object} sourcesList - sources list (containing root AST node)
* @return {Object} - returns a mapping between contract name and contract state
*/
function extractStatesDefinitions (sourcesList) {
var contracts = extractContractDefinitions(sourcesList)
var ret = {}
for (var contract in contracts.contractsById) {
var name = contracts.contractsById[contract].attributes.name
ret[name] = extractStateDefinitions(name, sourcesList, contracts)
}
return ret
}
module.exports = { module.exports = {
extractState: extractState, extractStatesDefinitions: extractStatesDefinitions,
extractStateDefinitions: extractStateDefinitions,
extractContractDefinitions: extractContractDefinitions, extractContractDefinitions: extractContractDefinitions,
getLinearizedBaseContracts: getLinearizedBaseContracts getLinearizedBaseContracts: getLinearizedBaseContracts
} }
...@@ -90,9 +90,11 @@ function String (type) { ...@@ -90,9 +90,11 @@ function String (type) {
* 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)
* @param {Object} stateDefinitions - all state definitions given by the AST (including struct and enum type declaration) for all contracts
* @param {String} contractName - contract the @args typeName belongs to
* @return {Object} returns decoded info about the current type: { storageBytes, typeName, arraySize, subArray} * @return {Object} returns decoded info about the current type: { storageBytes, typeName, arraySize, subArray}
*/ */
function Array (type, stateDefinitions) { function Array (type, stateDefinitions, contractName) {
var arraySize var arraySize
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) {
...@@ -100,7 +102,7 @@ function Array (type, stateDefinitions) { ...@@ -100,7 +102,7 @@ function Array (type, stateDefinitions) {
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 = parseType(match[1], stateDefinitions, contractName)
if (underlyingType === null) { if (underlyingType === null) {
console.log('unable to parse type ' + type) console.log('unable to parse type ' + type)
return null return null
...@@ -112,10 +114,13 @@ function Array (type, stateDefinitions) { ...@@ -112,10 +114,13 @@ function Array (type, stateDefinitions) {
* 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)
* @param {Object} stateDefinitions - all state definitions given by the AST (including struct and enum type declaration) for all contracts
* @param {String} contractName - contract the @args typeName belongs to
* @return {Object} returns decoded info about the current type: { storageBytes, typeName, enum} * @return {Object} returns decoded info about the current type: { storageBytes, typeName, enum}
*/ */
function Enum (type, stateDefinitions) { function Enum (type, stateDefinitions, contractName) {
var enumDef = getEnum(type, stateDefinitions) var match = type.match(/enum (.*)/)
var enumDef = getEnum(match[1], stateDefinitions, contractName)
if (enumDef === null) { if (enumDef === null) {
console.log('unable to retrieve decode info of ' + type) console.log('unable to retrieve decode info of ' + type)
return null return null
...@@ -127,14 +132,16 @@ function Enum (type, stateDefinitions) { ...@@ -127,14 +132,16 @@ function Enum (type, stateDefinitions) {
* 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)
* @param {Object} stateDefinitions - all state definitions given by the AST (including struct and enum type declaration) for all contracts
* @param {String} contractName - contract the @args typeName belongs to
* @return {Object} returns decoded info about the current type: { storageBytes, typeName, members} * @return {Object} returns decoded info about the current type: { storageBytes, typeName, members}
*/ */
function Struct (type, stateDefinitions) { function Struct (type, stateDefinitions, contractName) {
var match = type.match(/struct (.*?)( storage ref| storage pointer| memory| calldata)?$/) var match = type.match(/struct (.*?)( storage ref| storage pointer| memory| calldata)?$/)
if (!match) { if (!match) {
return null return null
} }
var memberDetails = getStructMembers(match[1], stateDefinitions) // type is used to extract the ast struct definition var memberDetails = getStructMembers(match[1], stateDefinitions, contractName) // type is used to extract the ast struct definition
if (!memberDetails) return null if (!memberDetails) return null
return new StructType(memberDetails) return new StructType(memberDetails)
} }
...@@ -143,16 +150,25 @@ function Struct (type, stateDefinitions) { ...@@ -143,16 +150,25 @@ function Struct (type, stateDefinitions) {
* retrieve enum declaration of the given @arg type * retrieve enum declaration of 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)
* @param {Object} stateDefinitions - all state declarations given by the AST (including struct and enum type declaration) * @param {Object} stateDefinitions - all state declarations given by the AST (including struct and enum type declaration) for all contracts
* @param {String} contractName - contract the @args typeName belongs to
* @return {Array} - containing all value declaration of the current enum type * @return {Array} - containing all value declaration of the current enum type
*/ */
function getEnum (type, stateDefinitions) { function getEnum (type, stateDefinitions, contractName) {
for (var k in stateDefinitions) { var split = type.split('.')
var dec = stateDefinitions[k] if (!split.length) {
if (dec.attributes && dec.attributes.name && type === 'enum ' + dec.attributes.name) { type = contractName + '.' + type
} else {
contractName = split[0]
}
var state = stateDefinitions[contractName]
if (state) {
for (var dec of state.stateDefinitions) {
if (dec.attributes && dec.attributes.name && type === contractName + '.' + dec.attributes.name) {
return dec return dec
} }
} }
}
return null return null
} }
...@@ -160,20 +176,29 @@ function getEnum (type, stateDefinitions) { ...@@ -160,20 +176,29 @@ function getEnum (type, stateDefinitions) {
* retrieve memebers declared in the given @arg tye * retrieve memebers declared in the given @arg tye
* *
* @param {String} typeName - name of the struct type (e.g struct <name>) * @param {String} typeName - name of the struct type (e.g struct <name>)
* @param {Object} stateDefinitions - all state definition given by the AST (including struct and enum type declaration) * @param {Object} stateDefinitions - all state definition given by the AST (including struct and enum type declaration) for all contracts
* @param {String} contractName - contract the @args typeName belongs to
* @return {Array} containing all members of the current struct type * @return {Array} containing all members of the current struct type
*/ */
function getStructMembers (typeName, stateDefinitions) { function getStructMembers (type, stateDefinitions, contractName) {
for (var k in stateDefinitions) { var split = type.split('.')
var dec = stateDefinitions[k] if (!split.length) {
if (dec.name === 'StructDefinition' && typeName === dec.attributes.name) { type = contractName + '.' + type
var offsets = computeOffsets(dec.children, stateDefinitions) } else {
contractName = split[0]
}
var state = stateDefinitions[contractName]
if (state) {
for (var dec of state.stateDefinitions) {
if (dec.name === 'StructDefinition' && type === contractName + '.' + dec.attributes.name) {
var offsets = computeOffsets(dec.children, stateDefinitions, contractName)
return { return {
members: offsets.typesOffsets, members: offsets.typesOffsets,
storageSlots: offsets.endLocation.slot storageSlots: offsets.endLocation.slot
} }
} }
} }
}
return null return null
} }
...@@ -198,10 +223,11 @@ function typeClass (fullType) { ...@@ -198,10 +223,11 @@ function typeClass (fullType) {
* parse the type and return an object representing the type * parse the type and return an object representing the type
* *
* @param {Object} type - type name given by the ast node * @param {Object} type - type name given by the ast node
* @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) for all contracts
* @param {String} contractName - contract the @args typeName belongs to
* @return {Object} - return the corresponding decoder or null on error * @return {Object} - return the corresponding decoder or null on error
*/ */
function parseType (type, stateDefinitions) { function parseType (type, stateDefinitions, contractName) {
var decodeInfos = { var decodeInfos = {
'address': Address, 'address': Address,
'array': Array, 'array': Array,
...@@ -219,17 +245,18 @@ function parseType (type, stateDefinitions) { ...@@ -219,17 +245,18 @@ function parseType (type, stateDefinitions) {
console.log('unable to retrieve decode info of ' + type) console.log('unable to retrieve decode info of ' + type)
return null return null
} }
return decodeInfos[currentType](type, stateDefinitions) return decodeInfos[currentType](type, stateDefinitions, contractName)
} }
/** /**
* compute offset (slot offset and byte offset of the @arg list of types) * compute offset (slot offset and byte offset of the @arg list of types)
* *
* @param {Array} types - list of types * @param {Array} types - list of types
* @param {Object} stateItems - all state definitions given by the AST (including struct and enum type declaration) * @param {Object} stateDefinitions - all state definitions given by the AST (including struct and enum type declaration) for all contracts
* @param {String} contractName - contract the @args typeName belongs to
* @return {Array} - return an array of types item: {name, type, location}. location defines the byte offset and slot offset * @return {Array} - return an array of types item: {name, type, location}. location defines the byte offset and slot offset
*/ */
function computeOffsets (types, stateItems, cb) { function computeOffsets (types, stateDefinitions, contractName) {
var ret = [] var ret = []
var location = { var location = {
offset: 0, offset: 0,
...@@ -237,7 +264,7 @@ function computeOffsets (types, stateItems, cb) { ...@@ -237,7 +264,7 @@ function computeOffsets (types, stateItems, cb) {
} }
for (var i in types) { for (var i in types) {
var variable = types[i] var variable = types[i]
var type = parseType(variable.attributes.type, stateItems) var type = parseType(variable.attributes.type, stateDefinitions, contractName)
if (!type) { if (!type) {
console.log('unable to retrieve decode info of ' + variable.attributes.type) console.log('unable to retrieve decode info of ' + variable.attributes.type)
return null return null
......
...@@ -25,12 +25,12 @@ function decodeState (stateVars, storageContent) { ...@@ -25,12 +25,12 @@ function decodeState (stateVars, storageContent) {
* @return {Object} - return the location of all contract variables in the storage * @return {Object} - return the location of all contract variables in the storage
*/ */
function extractStateVariables (contractName, sourcesList) { function extractStateVariables (contractName, sourcesList) {
var state = astHelper.extractState(contractName, sourcesList) var states = astHelper.extractStatesDefinitions(sourcesList)
var ret = [] if (!states[contractName]) {
if (!state) { return []
return ret
} }
var offsets = decodeInfo.computeOffsets(state.stateVariables, state.stateItems) var types = states[contractName].stateVariables
var offsets = decodeInfo.computeOffsets(types, states, contractName)
return offsets.typesOffsets return offsets.typesOffsets
} }
......
'use strict'
module.exports = `
contract simpleContract {
struct structDef {
uint8 ui;
string str;
}
enum enumDef {
first,
second,
third
}
structDef structDec;
structDef[3] array;
enumDef enumDec;
}
contract test1 {
struct str {
}
}
contract test2 {
test1.str a;
}
`
...@@ -3,55 +3,78 @@ var tape = require('tape') ...@@ -3,55 +3,78 @@ var tape = require('tape')
var compiler = require('solc') var compiler = require('solc')
var index = require('../../src/index') var index = require('../../src/index')
var contracts = require('./contracts/miscContracts') var contracts = require('./contracts/miscContracts')
var simplecontracts = require('./contracts/simpleContract')
tape('solidity', function (t) { tape('solidity', function (t) {
t.test('astHelper, decodeInfo', function (st) { t.test('astHelper, decodeInfo', function (st) {
var output = compiler.compile(contracts, 0) var output = compiler.compile(contracts, 0)
var stateDec = index.solidity.astHelper.extractState('contractUint', output.sources).stateItems var state = index.solidity.astHelper.extractStateDefinitions('contractUint', output.sources)
var decodeInfo = index.solidity.decodeInfo.parseType(stateDec[0].attributes.type, stateDec) var states = index.solidity.astHelper.extractStatesDefinitions(output.sources)
var stateDef = state.stateDefinitions
var decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint') checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[3].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[4].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractUint')
checkDecodeInfo(st, decodeInfo, 1, 16, 'bytesX') checkDecodeInfo(st, decodeInfo, 1, 16, 'bytesX')
stateDec = index.solidity.astHelper.extractState('contractStructAndArray', output.sources).stateItems state = index.solidity.astHelper.extractStateDefinitions('contractStructAndArray', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec) stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractStructAndArray')
checkDecodeInfo(st, decodeInfo, 2, 32, 'struct') checkDecodeInfo(st, decodeInfo, 2, 32, 'struct')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractStructAndArray')
checkDecodeInfo(st, decodeInfo, 6, 32, 'array') checkDecodeInfo(st, decodeInfo, 6, 32, 'array')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[3].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractStructAndArray')
checkDecodeInfo(st, decodeInfo, 2, 32, 'array') checkDecodeInfo(st, decodeInfo, 2, 32, 'array')
stateDec = index.solidity.astHelper.extractState('contractArray', output.sources).stateItems state = index.solidity.astHelper.extractStateDefinitions('contractArray', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[0].attributes.type, stateDec) stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractArray')
checkDecodeInfo(st, decodeInfo, 1, 32, 'array') checkDecodeInfo(st, decodeInfo, 1, 32, 'array')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractArray')
checkDecodeInfo(st, decodeInfo, 1, 32, 'array') checkDecodeInfo(st, decodeInfo, 1, 32, 'array')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractArray')
checkDecodeInfo(st, decodeInfo, 4, 32, 'array') checkDecodeInfo(st, decodeInfo, 4, 32, 'array')
stateDec = index.solidity.astHelper.extractState('contractEnum', output.sources).stateItems state = index.solidity.astHelper.extractStateDefinitions('contractEnum', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec) stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractEnum')
checkDecodeInfo(st, decodeInfo, 1, 2, 'enum') checkDecodeInfo(st, decodeInfo, 1, 2, 'enum')
stateDec = index.solidity.astHelper.extractState('contractSmallVariable', output.sources).stateItems state = index.solidity.astHelper.extractStateDefinitions('contractSmallVariable', output.sources)
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[0].attributes.type, stateDec) stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 1, 'int') checkDecodeInfo(st, decodeInfo, 1, 1, 'int')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint') checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 2, 'uint') checkDecodeInfo(st, decodeInfo, 1, 2, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[3].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 4, 'int') checkDecodeInfo(st, decodeInfo, 1, 4, 'int')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[4].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.parseType(stateDec[5].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.parseType(stateDef[5].attributes.type, states, 'contractSmallVariable')
checkDecodeInfo(st, decodeInfo, 1, 2, 'int') checkDecodeInfo(st, decodeInfo, 1, 2, 'int')
output = compiler.compile(simplecontracts, 0)
state = index.solidity.astHelper.extractStateDefinitions('simpleContract', output.sources)
states = index.solidity.astHelper.extractStatesDefinitions(output.sources)
stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[2].attributes.type, states, 'simpleContract')
checkDecodeInfo(st, decodeInfo, 2, 32, 'struct')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[3].attributes.type, states, 'simpleContract')
checkDecodeInfo(st, decodeInfo, 6, 32, 'array')
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[4].attributes.type, states, 'simpleContract')
checkDecodeInfo(st, decodeInfo, 1, 1, 'enum')
state = index.solidity.astHelper.extractStateDefinitions('test2', output.sources)
stateDef = state.stateDefinitions
decodeInfo = index.solidity.decodeInfo.parseType(stateDef[0].attributes.type, states, 'test1')
checkDecodeInfo(st, decodeInfo, 0, 32, 'struct')
st.end() 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