remove needsFreeStorageSlot

pull/7/head
yann300 8 years ago
parent 222a4f8363
commit 5b06c33d3c
  1. 59
      src/solidity/decodeInfo.js
  2. 61
      src/solidity/locationDecoder.js
  3. 18
      src/solidity/stateDecoder.js
  4. 2
      src/solidity/types/baseType.js
  5. 38
      test/solidity/decodeInfo.js

@ -3,12 +3,12 @@
* Uint decode the given @arg type
*
* @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) {
type === 'uint' ? 'uint256' : type
return {
needsFreeStorageSlot: false,
storageSlots: 1,
storageBytes: parseInt(type.replace('uint', '')) / 8,
typeName: 'uint'
}
@ -18,12 +18,12 @@ function Uint (type) {
* Int decode the given @arg type
*
* @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) {
type === 'int' ? 'int256' : type
return {
needsFreeStorageSlot: false,
storageSlots: 1,
storageBytes: parseInt(type.replace('int', '')) / 8,
typeName: 'int'
}
@ -33,11 +33,11 @@ function Int (type) {
* Address decode the given @arg type
*
* @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) {
return {
needsFreeStorageSlot: false,
storageSlots: 1,
storageBytes: 20,
typeName: 'address'
}
@ -47,11 +47,11 @@ function Address (type) {
* Bool decode the given @arg type
*
* @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) {
return {
needsFreeStorageSlot: false,
storageSlots: 1,
storageBytes: 1,
typeName: 'bool'
}
@ -61,11 +61,11 @@ function Bool (type) {
* DynamicByteArray decode the given @arg type
*
* @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) {
return {
needsFreeStorageSlot: true,
storageSlots: 1,
storageBytes: 32,
typeName: 'bytes'
}
@ -75,11 +75,11 @@ function DynamicByteArray (type) {
* FixedByteArray decode the given @arg type
*
* @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) {
return {
needsFreeStorageSlot: false,
storageSlots: 1,
storageBytes: parseInt(type.replace('bytes', '')),
typeName: 'bytesX'
}
@ -89,11 +89,11 @@ function FixedByteArray (type) {
* StringType decode the given @arg type
*
* @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) {
return {
needsFreeStorageSlot: true,
storageSlots: 1,
storageBytes: 32,
typeName: 'string'
}
@ -103,11 +103,10 @@ function StringType (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)
* @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) {
var arraySize
var storageBytes
var match = type.match(/(.*)\[(.*?)\]( storage ref| storage pointer| memory| calldata)?$/)
if (!match || match.length < 3) {
@ -123,20 +122,21 @@ function ArrayType (type, stateDefinitions) {
return null
}
var storageSlots
if (arraySize === 'dynamic') {
storageBytes = 32
storageSlots = 1
} else {
storageBytes = underlyingType.storageBytes
if (storageBytes > 32) {
storageBytes = 32 * arraySize * Math.ceil(storageBytes / 32)
if (underlyingType.storageBytes < 32) {
var itemPerSlot = Math.floor(32 / underlyingType.storageBytes)
storageSlots = Math.ceil(arraySize / itemPerSlot)
} else {
storageBytes = 32 * (arraySize / Math.floor(32 / storageBytes))
storageSlots = arraySize * underlyingType.storageSlots
}
}
return {
needsFreeStorageSlot: true,
storageBytes: storageBytes,
storageSlots: storageSlots,
storageBytes: 32,
typeName: 'array',
arraySize: arraySize,
underlyingType: underlyingType
@ -147,7 +147,7 @@ function ArrayType (type, stateDefinitions) {
* Enum decode the given @arg type
*
* @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) {
var enumDef = getEnum(type, stateDefinitions)
@ -162,7 +162,7 @@ function Enum (type, stateDefinitions) {
storageBytes++
}
return {
needsFreeStorageSlot: false,
storageSlots: 1,
storageBytes: storageBytes,
typeName: 'enum',
enum: enumDef
@ -173,7 +173,7 @@ function Enum (type, stateDefinitions) {
* Struct decode the given @arg type
*
* @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) {
var match = type.match(/struct (.*?)( storage ref| storage pointer| memory| calldata)?$/)
@ -183,8 +183,8 @@ function Struct (type, stateDefinitions) {
var memberDetails = getStructMembers(match[1], stateDefinitions) // type is used to extract the ast struct definition
if (!memberDetails) return null
return {
needsFreeStorageSlot: true,
storageBytes: memberDetails.storageBytes,
storageSlots: Math.ceil(memberDetails.storageBytes / 32),
storageBytes: 32,
typeName: 'struct',
members: memberDetails.members
}
@ -228,9 +228,6 @@ function getStructMembers (typeName, stateDefinitions) {
return null
}
members.push(decoded)
if (decoded.needsFreeStorageSlot) {
storageBytes = Math.ceil(storageBytes / 32) * 32
}
storageBytes += decoded.storageBytes
}
break

@ -1,61 +0,0 @@
/**
* 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
}

@ -1,6 +1,5 @@
var astHelper = require('./astHelper')
var decodeInfo = require('./decodeInfo')
var locationDecoder = require('./locationDecoder')
/**
* decode the contract state storage
@ -44,13 +43,24 @@ function extractStateVariables (contractName, sourcesList) {
if (variable.name === 'VariableDeclaration') {
var decoded = decodeInfo.decode(variable.attributes.type, stateDefinitions)
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({
name: variable.attributes.name,
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

@ -1,7 +1,7 @@
'use strict'
module.exports = function (type, decoder) {
type.needsFreeStorageSlot = decoder.needsFreeStorageSlot
type.storageSlots = decoder.storageSlots
type.storageBytes = decoder.storageBytes
type.typeName = decoder.typeName
type.decoder = decoder.decoder

@ -10,54 +10,54 @@ tape('solidity', function (t) {
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, 'uint')
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
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)
checkDecodeInfo(st, decodeInfo, false, 32, 'uint')
checkDecodeInfo(st, decodeInfo, 1, 32, 'uint')
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)
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)
checkDecodeInfo(st, decodeInfo, true, 192, 'array')
checkDecodeInfo(st, decodeInfo, 6, 32, 'array')
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)
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)
checkDecodeInfo(st, decodeInfo, true, 32, 'array')
checkDecodeInfo(st, decodeInfo, 1, 32, 'array')
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)
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)
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)
checkDecodeInfo(st, decodeInfo, false, 1, 'uint')
checkDecodeInfo(st, decodeInfo, 1, 1, 'uint')
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)
checkDecodeInfo(st, decodeInfo, false, 4, 'int')
checkDecodeInfo(st, decodeInfo, 1, 4, 'int')
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)
checkDecodeInfo(st, decodeInfo, false, 2, 'int')
checkDecodeInfo(st, decodeInfo, 1, 2, 'int')
st.end()
})
})
function checkDecodeInfo (st, decodeInfo, freeSlot, storageBytes, typeName, name) {
st.equal(decodeInfo.needsFreeStorageSlot, freeSlot)
function checkDecodeInfo (st, decodeInfo, storageSlots, storageBytes, typeName) {
st.equal(decodeInfo.storageSlots, storageSlots)
st.equal(decodeInfo.storageBytes, storageBytes)
st.equal(decodeInfo.typeName, typeName)
}

Loading…
Cancel
Save