From 54060ecde06064f8fe449e0d55259268bcc4c620 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 16 Nov 2016 00:30:03 +0100 Subject: [PATCH 1/3] fix struct type --- src/solidity/decodeInfo.js | 27 +++++++++++++++++++++------ src/solidity/types/Struct.js | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/solidity/decodeInfo.js b/src/solidity/decodeInfo.js index 515041b1d3..fe26c1b0af 100644 --- a/src/solidity/decodeInfo.js +++ b/src/solidity/decodeInfo.js @@ -165,26 +165,41 @@ function getEnum (type, stateDefinitions) { */ function getStructMembers (typeName, stateDefinitions) { var members = [] - var storageBytes = 0 for (var k in stateDefinitions) { var dec = stateDefinitions[k] if (dec.name === 'StructDefinition' && typeName === dec.attributes.name) { + var location = { + offset: 0, + slot: 0 + } for (var i in dec.children) { var member = dec.children[i] - var decoded = parseType(member.attributes.type, stateDefinitions) - if (!decoded) { + var type = parseType(member.attributes.type, stateDefinitions) + if (location.offset + type.storageBytes > 32) { + location.slot++ + location.offset = 0 + } + if (!type) { console.log('unable to retrieve decode info of ' + member.attributes.type) return null } - members.push(decoded) - storageBytes += decoded.storageBytes + members.push(type) + if (type.storageSlots === 1 && location.offset + type.storageBytes <= 32) { + location.offset += type.storageBytes + } else { + location.slot += type.storageSlots + location.offset = 0 + } + } + if (location.offset > 0) { + location.slot++ } break } } return { members: members, - storageBytes: storageBytes + storageBytes: location.slot } } diff --git a/src/solidity/types/Struct.js b/src/solidity/types/Struct.js index f44f9b5e1f..138694104f 100644 --- a/src/solidity/types/Struct.js +++ b/src/solidity/types/Struct.js @@ -1,7 +1,7 @@ 'use strict' function Struct (memberDetails) { - this.storageSlots = Math.ceil(memberDetails.storageBytes / 32) + this.storageSlots = memberDetails.storageBytes this.storageBytes = 32 this.members = memberDetails.members this.typeName = 'struct' From 3ea4abeb7b2ace5d4caa2f28d38ec3c958e393b3 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 16 Nov 2016 12:02:07 +0100 Subject: [PATCH 2/3] refactor computeoffsets --- src/solidity/astHelper.js | 19 +++++--- src/solidity/decodeInfo.js | 85 +++++++++++++++++++++++------------- src/solidity/stateDecoder.js | 36 ++------------- test/solidity/decodeInfo.js | 10 ++--- 4 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/solidity/astHelper.js b/src/solidity/astHelper.js index 8c0c73a405..90ab05046d 100644 --- a/src/solidity/astHelper.js +++ b/src/solidity/astHelper.js @@ -37,28 +37,37 @@ function getLinearizedBaseContracts (id, contractsById) { * * @param {String} contractName - contract for which state var should be resolved * @param {Object} sourcesList - sources list (containing root AST node) - * @return {Array} - return an array of AST node of all state variables (including inherited) (this will include all enum/struct declarations) + * @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 */ -function extractStateVariables (contractName, sourcesList) { +function extractState (contractName, sourcesList) { var contracts = extractContractDefinitions(sourcesList) var node = contracts.contractsByName[contractName] if (node) { + var stateItems = [] var stateVar = [] var baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById) baseContracts.reverse() for (var k in baseContracts) { var ctr = baseContracts[k] for (var i in ctr.children) { - stateVar.push(ctr.children[i]) + var item = ctr.children[i] + stateItems.push(item) + if (item.name === 'VariableDeclaration') { + stateVar.push(item) + } } } - return stateVar + return { + stateItems: stateItems, + stateVariables: stateVar + } } return null } module.exports = { - extractStateVariables: extractStateVariables, + extractState: extractState, extractContractDefinitions: extractContractDefinitions, getLinearizedBaseContracts: getLinearizedBaseContracts } diff --git a/src/solidity/decodeInfo.js b/src/solidity/decodeInfo.js index fe26c1b0af..1887ba55c4 100644 --- a/src/solidity/decodeInfo.js +++ b/src/solidity/decodeInfo.js @@ -164,43 +164,17 @@ function getEnum (type, stateDefinitions) { * @return {Array} containing all members of the current struct type */ function getStructMembers (typeName, stateDefinitions) { - var members = [] for (var k in stateDefinitions) { var dec = stateDefinitions[k] if (dec.name === 'StructDefinition' && typeName === dec.attributes.name) { - var location = { - offset: 0, - slot: 0 + var offsets = computeOffsets(dec.children, stateDefinitions) + return { + members: offsets.typesOffsets, + storageBytes: offsets.endLocation.slot } - for (var i in dec.children) { - var member = dec.children[i] - var type = parseType(member.attributes.type, stateDefinitions) - if (location.offset + type.storageBytes > 32) { - location.slot++ - location.offset = 0 - } - if (!type) { - console.log('unable to retrieve decode info of ' + member.attributes.type) - return null - } - members.push(type) - if (type.storageSlots === 1 && location.offset + type.storageBytes <= 32) { - location.offset += type.storageBytes - } else { - location.slot += type.storageSlots - location.offset = 0 - } - } - if (location.offset > 0) { - location.slot++ - } - break } } - return { - members: members, - storageBytes: location.slot - } + return null } /** @@ -248,8 +222,57 @@ function parseType (type, stateDefinitions) { return decodeInfos[currentType](type, stateDefinitions) } +/** + * compute offset (slot offset and byte offset of the @arg 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) + * @return {Array} - return an array of types item: {name, type, location}. location defines the byte offset and slot offset + */ +function computeOffsets (types, stateItems, cb) { + var ret = [] + var location = { + offset: 0, + slot: 0 + } + for (var i in types) { + var variable = types[i] + var type = parseType(variable.attributes.type, stateItems) + if (location.offset + type.storageBytes > 32) { + location.slot++ + location.offset = 0 + } + if (!type) { + console.log('unable to retrieve decode info of ' + variable.attributes.type) + return null + } + 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 + } + } + if (location.offset > 0) { + location.slot++ + } + return { + typesOffsets: ret, + endLocation: location + } +} + module.exports = { parseType: parseType, + computeOffsets: computeOffsets, Uint: Uint, Address: Address, Bool: Bool, diff --git a/src/solidity/stateDecoder.js b/src/solidity/stateDecoder.js index 21473026ff..7737cff7d2 100644 --- a/src/solidity/stateDecoder.js +++ b/src/solidity/stateDecoder.js @@ -25,40 +25,13 @@ function decodeState (stateVars, storageContent) { * @return {Object} - return the location of all contract variables in the storage */ function extractStateVariables (contractName, sourcesList) { - var stateDefinitions = astHelper.extractStateVariables(contractName, sourcesList) + var state = astHelper.extractState(contractName, sourcesList) var ret = [] - if (!stateDefinitions) { + if (!state) { 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 + var offsets = decodeInfo.computeOffsets(state.stateVariables, state.stateItems) + return offsets.typesOffsets } /** @@ -79,4 +52,3 @@ module.exports = { extractStateVariables: extractStateVariables, decodeState: decodeState } - diff --git a/test/solidity/decodeInfo.js b/test/solidity/decodeInfo.js index 36b28ee64f..f740d41411 100644 --- a/test/solidity/decodeInfo.js +++ b/test/solidity/decodeInfo.js @@ -8,7 +8,7 @@ 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 stateDec = index.solidity.astHelper.extractState('contractUint', output.sources).stateItems 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) @@ -18,7 +18,7 @@ tape('solidity', function (t) { decodeInfo = index.solidity.decodeInfo.parseType(stateDec[4].attributes.type, stateDec) checkDecodeInfo(st, decodeInfo, 1, 16, 'bytesX') - stateDec = index.solidity.astHelper.extractStateVariables('contractStructAndArray', output.sources) + stateDec = index.solidity.astHelper.extractState('contractStructAndArray', output.sources).stateItems 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) @@ -26,7 +26,7 @@ tape('solidity', function (t) { decodeInfo = index.solidity.decodeInfo.parseType(stateDec[3].attributes.type, stateDec) checkDecodeInfo(st, decodeInfo, 2, 32, 'array') - stateDec = index.solidity.astHelper.extractStateVariables('contractArray', output.sources) + stateDec = index.solidity.astHelper.extractState('contractArray', output.sources).stateItems 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) @@ -34,11 +34,11 @@ tape('solidity', function (t) { decodeInfo = index.solidity.decodeInfo.parseType(stateDec[2].attributes.type, stateDec) checkDecodeInfo(st, decodeInfo, 4, 32, 'array') - stateDec = index.solidity.astHelper.extractStateVariables('contractEnum', output.sources) + stateDec = index.solidity.astHelper.extractState('contractEnum', output.sources).stateItems decodeInfo = index.solidity.decodeInfo.parseType(stateDec[1].attributes.type, stateDec) checkDecodeInfo(st, decodeInfo, 1, 2, 'enum') - stateDec = index.solidity.astHelper.extractStateVariables('contractSmallVariable', output.sources) + stateDec = index.solidity.astHelper.extractState('contractSmallVariable', output.sources).stateItems 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) From ef848d4436ec52cdac00d2691790d1b2a63b1b31 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 16 Nov 2016 12:35:07 +0100 Subject: [PATCH 3/3] renaming --- src/solidity/decodeInfo.js | 10 +++++----- src/solidity/types/Struct.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/solidity/decodeInfo.js b/src/solidity/decodeInfo.js index 1887ba55c4..be0665031a 100644 --- a/src/solidity/decodeInfo.js +++ b/src/solidity/decodeInfo.js @@ -170,7 +170,7 @@ function getStructMembers (typeName, stateDefinitions) { var offsets = computeOffsets(dec.children, stateDefinitions) return { members: offsets.typesOffsets, - storageBytes: offsets.endLocation.slot + storageSlots: offsets.endLocation.slot } } } @@ -238,14 +238,14 @@ function computeOffsets (types, stateItems, cb) { for (var i in types) { var variable = types[i] var type = parseType(variable.attributes.type, stateItems) - if (location.offset + type.storageBytes > 32) { - location.slot++ - location.offset = 0 - } if (!type) { console.log('unable to retrieve decode info of ' + variable.attributes.type) return null } + if (location.offset + type.storageBytes > 32) { + location.slot++ + location.offset = 0 + } ret.push({ name: variable.attributes.name, type: type, diff --git a/src/solidity/types/Struct.js b/src/solidity/types/Struct.js index 138694104f..06b2df20a1 100644 --- a/src/solidity/types/Struct.js +++ b/src/solidity/types/Struct.js @@ -1,7 +1,7 @@ 'use strict' function Struct (memberDetails) { - this.storageSlots = memberDetails.storageBytes + this.storageSlots = memberDetails.storageSlots this.storageBytes = 32 this.members = memberDetails.members this.typeName = 'struct'