Commit 5b06c33d authored by yann300's avatar yann300

remove needsFreeStorageSlot

parent 222a4f83
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
* 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 { return {
needsFreeStorageSlot: false, storageSlots: 1,
storageBytes: parseInt(type.replace('uint', '')) / 8, storageBytes: parseInt(type.replace('uint', '')) / 8,
typeName: 'uint' typeName: 'uint'
} }
...@@ -18,12 +18,12 @@ function Uint (type) { ...@@ -18,12 +18,12 @@ function Uint (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 { return {
needsFreeStorageSlot: false, storageSlots: 1,
storageBytes: parseInt(type.replace('int', '')) / 8, storageBytes: parseInt(type.replace('int', '')) / 8,
typeName: 'int' typeName: 'int'
} }
...@@ -33,11 +33,11 @@ function Int (type) { ...@@ -33,11 +33,11 @@ function Int (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 {
needsFreeStorageSlot: false, storageSlots: 1,
storageBytes: 20, storageBytes: 20,
typeName: 'address' typeName: 'address'
} }
...@@ -47,11 +47,11 @@ function Address (type) { ...@@ -47,11 +47,11 @@ function Address (type) {
* 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 {
needsFreeStorageSlot: false, storageSlots: 1,
storageBytes: 1, storageBytes: 1,
typeName: 'bool' typeName: 'bool'
} }
...@@ -61,11 +61,11 @@ function Bool (type) { ...@@ -61,11 +61,11 @@ function Bool (type) {
* 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 {
needsFreeStorageSlot: true, storageSlots: 1,
storageBytes: 32, storageBytes: 32,
typeName: 'bytes' typeName: 'bytes'
} }
...@@ -75,11 +75,11 @@ function DynamicByteArray (type) { ...@@ -75,11 +75,11 @@ function DynamicByteArray (type) {
* 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 { return {
needsFreeStorageSlot: false, storageSlots: 1,
storageBytes: parseInt(type.replace('bytes', '')), storageBytes: parseInt(type.replace('bytes', '')),
typeName: 'bytesX' typeName: 'bytesX'
} }
...@@ -89,11 +89,11 @@ function FixedByteArray (type) { ...@@ -89,11 +89,11 @@ function FixedByteArray (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 StringType (type) {
return { return {
needsFreeStorageSlot: true, storageSlots: 1,
storageBytes: 32, storageBytes: 32,
typeName: 'string' typeName: 'string'
} }
...@@ -103,11 +103,10 @@ function StringType (type) { ...@@ -103,11 +103,10 @@ function StringType (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)
* @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 ArrayType (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) {
...@@ -123,20 +122,21 @@ function ArrayType (type, stateDefinitions) { ...@@ -123,20 +122,21 @@ function ArrayType (type, stateDefinitions) {
return null return null
} }
var storageSlots
if (arraySize === 'dynamic') { if (arraySize === 'dynamic') {
storageBytes = 32 storageSlots = 1
} else { } else {
storageBytes = underlyingType.storageBytes if (underlyingType.storageBytes < 32) {
if (storageBytes > 32) { var itemPerSlot = Math.floor(32 / underlyingType.storageBytes)
storageBytes = 32 * arraySize * Math.ceil(storageBytes / 32) storageSlots = Math.ceil(arraySize / itemPerSlot)
} else { } else {
storageBytes = 32 * (arraySize / Math.floor(32 / storageBytes)) storageSlots = arraySize * underlyingType.storageSlots
} }
} }
return { return {
needsFreeStorageSlot: true, storageSlots: storageSlots,
storageBytes: storageBytes, storageBytes: 32,
typeName: 'array', typeName: 'array',
arraySize: arraySize, arraySize: arraySize,
underlyingType: underlyingType underlyingType: underlyingType
...@@ -147,7 +147,7 @@ function ArrayType (type, stateDefinitions) { ...@@ -147,7 +147,7 @@ function ArrayType (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)
* @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)
...@@ -162,7 +162,7 @@ function Enum (type, stateDefinitions) { ...@@ -162,7 +162,7 @@ function Enum (type, stateDefinitions) {
storageBytes++ storageBytes++
} }
return { return {
needsFreeStorageSlot: false, storageSlots: 1,
storageBytes: storageBytes, storageBytes: storageBytes,
typeName: 'enum', typeName: 'enum',
enum: enumDef enum: enumDef
...@@ -173,7 +173,7 @@ function Enum (type, stateDefinitions) { ...@@ -173,7 +173,7 @@ 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)
* @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)?$/)
...@@ -183,8 +183,8 @@ function Struct (type, stateDefinitions) { ...@@ -183,8 +183,8 @@ 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 {
needsFreeStorageSlot: true, storageSlots: Math.ceil(memberDetails.storageBytes / 32),
storageBytes: memberDetails.storageBytes, storageBytes: 32,
typeName: 'struct', typeName: 'struct',
members: memberDetails.members members: memberDetails.members
} }
...@@ -228,9 +228,6 @@ function getStructMembers (typeName, stateDefinitions) { ...@@ -228,9 +228,6 @@ function getStructMembers (typeName, stateDefinitions) {
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
......
/**
* determine what will be the start and end location of the current @arg type.
*
* @param {Object} type - current type ( see ./types/list.js )
* @param {Object} positon - current position in storage
* @return {Object} returns the start and end location of the current @arg type.
*/
function walkStorage (type, position) {
var usedLocation = locationToFitType(type, position)
return {
currentLocation: usedLocation,
endLocation: locationToEnd(type, usedLocation)
}
}
/**
* determine the start location of #arg type
*
* @param {Object} type - current type ( see ./types/list.js )
* @param {Object} positon - current position in storage
* @return {Object} returns the start position of the current @arg type.
*/
function locationToFitType (type, position) {
if ((position.offset !== 0 && type.needsFreeStorageSlot) || (position.offset + type.storageBytes > 32 && !type.needsFreeStorageSlot)) {
return {
slot: position.slot + 1,
offset: 0
}
} else {
return {
slot: position.slot,
offset: position.offset
}
}
}
/**
* determine the end location of #arg type
*
* @param {Object} type - current type ( see ./types/list.js )
* @param {Object} positon - current position in storage
* @return {Object} returns the end position of the current @arg type.
*/
function locationToEnd (type, positon) {
if (positon.offset + type.storageBytes > 32) {
var slots = Math.floor(type.storageBytes / 32) - 1
return {
slot: positon.slot + slots,
offset: 32
}
} else {
return {
slot: positon.slot,
offset: positon.offset + type.storageBytes
}
}
}
module.exports = {
walkStorage: walkStorage
}
var astHelper = require('./astHelper') var astHelper = require('./astHelper')
var decodeInfo = require('./decodeInfo') var decodeInfo = require('./decodeInfo')
var locationDecoder = require('./locationDecoder')
/** /**
* decode the contract state storage * decode the contract state storage
...@@ -44,13 +43,24 @@ function extractStateVariables (contractName, sourcesList) { ...@@ -44,13 +43,24 @@ function extractStateVariables (contractName, sourcesList) {
if (variable.name === 'VariableDeclaration') { if (variable.name === 'VariableDeclaration') {
var decoded = decodeInfo.decode(variable.attributes.type, stateDefinitions) var decoded = decodeInfo.decode(variable.attributes.type, stateDefinitions)
var type = new types[decoded.typeName](decoded) var type = new types[decoded.typeName](decoded)
var loc = locationDecoder.walkStorage(type, location) if (location.offset + type.storageBytes > 32) {
location.slot++
location.offset = 0
}
ret.push({ ret.push({
name: variable.attributes.name, name: variable.attributes.name,
type: type, type: type,
location: loc.currentLocation location: {
offset: location.offset,
slot: location.slot
}
}) })
location = loc.endLocation if (type.storageSlots === 1 && location.offset + type.storageBytes <= 32) {
location.offset += type.storageBytes
} else {
location.slot += type.storageSlots
location.offset = 0
}
} }
} }
return ret return ret
......
'use strict' 'use strict'
module.exports = function (type, decoder) { module.exports = function (type, decoder) {
type.needsFreeStorageSlot = decoder.needsFreeStorageSlot type.storageSlots = decoder.storageSlots
type.storageBytes = decoder.storageBytes type.storageBytes = decoder.storageBytes
type.typeName = decoder.typeName type.typeName = decoder.typeName
type.decoder = decoder.decoder type.decoder = decoder.decoder
......
...@@ -10,54 +10,54 @@ tape('solidity', function (t) { ...@@ -10,54 +10,54 @@ tape('solidity', function (t) {
var stateDec = index.solidity.astHelper.extractStateVariables('contractUint', output.sources) var stateDec = index.solidity.astHelper.extractStateVariables('contractUint', output.sources)
var decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec) var decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 1, 'uint') checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[4].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[4].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 16, 'bytesX') checkDecodeInfo(st, decodeInfo, 1, 16, 'bytesX')
stateDec = index.solidity.astHelper.extractStateVariables('contractStructAndArray', output.sources) stateDec = index.solidity.astHelper.extractStateVariables('contractStructAndArray', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 64, 'struct') checkDecodeInfo(st, decodeInfo, 2, 32, 'struct')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 192, 'array') checkDecodeInfo(st, decodeInfo, 6, 32, 'array')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 64, 'array') checkDecodeInfo(st, decodeInfo, 2, 32, 'array')
stateDec = index.solidity.astHelper.extractStateVariables('contractArray', output.sources) stateDec = index.solidity.astHelper.extractStateVariables('contractArray', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 4 * 5, 'array') checkDecodeInfo(st, decodeInfo, 1, 32, 'array')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 32, 'array') checkDecodeInfo(st, decodeInfo, 1, 32, 'array')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, true, 4 * 32, 'array') checkDecodeInfo(st, decodeInfo, 4, 32, 'array')
stateDec = index.solidity.astHelper.extractStateVariables('contractEnum', output.sources) stateDec = index.solidity.astHelper.extractStateVariables('contractEnum', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 2, 'enum') checkDecodeInfo(st, decodeInfo, 1, 2, 'enum')
stateDec = index.solidity.astHelper.extractStateVariables('contractSmallVariable', output.sources) stateDec = index.solidity.astHelper.extractStateVariables('contractSmallVariable', output.sources)
decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[0].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 1, 'int') checkDecodeInfo(st, decodeInfo, 1, 1, 'int')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[1].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 1, 'uint') checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[2].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 2, 'uint') checkDecodeInfo(st, decodeInfo, 1, 2, 'uint')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[3].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 4, 'int') checkDecodeInfo(st, decodeInfo, 1, 4, 'int')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[4].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[4].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 32, 'uint') checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
decodeInfo = index.solidity.decodeInfo.decode(stateDec[5].attributes.type, stateDec) decodeInfo = index.solidity.decodeInfo.decode(stateDec[5].attributes.type, stateDec)
checkDecodeInfo(st, decodeInfo, false, 2, 'int') checkDecodeInfo(st, decodeInfo, 1, 2, 'int')
st.end() st.end()
}) })
}) })
function checkDecodeInfo (st, decodeInfo, freeSlot, storageBytes, typeName, name) { function checkDecodeInfo (st, decodeInfo, storageSlots, storageBytes, typeName) {
st.equal(decodeInfo.needsFreeStorageSlot, freeSlot) st.equal(decodeInfo.storageSlots, storageSlots)
st.equal(decodeInfo.storageBytes, storageBytes) st.equal(decodeInfo.storageBytes, storageBytes)
st.equal(decodeInfo.typeName, typeName) st.equal(decodeInfo.typeName, typeName)
} }
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