Commit 097c1409 authored by yann300's avatar yann300

fic Struct as value in Mapping

parent 32fda787
...@@ -12,10 +12,12 @@ class Mapping extends RefType { ...@@ -12,10 +12,12 @@ class Mapping extends RefType {
} }
async decodeFromStorage (location, storageResolver) { async decodeFromStorage (location, storageResolver) {
var corrections = this.valueType.members ? this.valueType.members.map((value) => { return value.storagelocation }) : []
if (!this.initialDecodedState) { // cache the decoded initial storage if (!this.initialDecodedState) { // cache the decoded initial storage
var mappingsInitialPreimages var mappingsInitialPreimages
try { try {
mappingsInitialPreimages = await storageResolver.initialMappingsLocation() mappingsInitialPreimages = await storageResolver.initialMappingsLocation(corrections)
this.initialDecodedState = await this.decodeMappingsLocation(mappingsInitialPreimages, location, storageResolver) this.initialDecodedState = await this.decodeMappingsLocation(mappingsInitialPreimages, location, storageResolver)
} catch (e) { } catch (e) {
return { return {
...@@ -24,7 +26,7 @@ class Mapping extends RefType { ...@@ -24,7 +26,7 @@ class Mapping extends RefType {
} }
} }
} }
var mappingPreimages = await storageResolver.mappingsLocation() var mappingPreimages = await storageResolver.mappingsLocation(corrections)
var ret = await this.decodeMappingsLocation(mappingPreimages, location, storageResolver) // fetch mapping storage changes var ret = await this.decodeMappingsLocation(mappingPreimages, location, storageResolver) // fetch mapping storage changes
ret = Object.assign({}, this.initialDecodedState, ret) // merge changes ret = Object.assign({}, this.initialDecodedState, ret) // merge changes
return { return {
......
...@@ -88,6 +88,10 @@ function add (value1, value2) { ...@@ -88,6 +88,10 @@ function add (value1, value2) {
return toBN(value1).add(toBN(value2)) return toBN(value1).add(toBN(value2))
} }
function sub (value1, value2) {
return toBN(value1).sub(toBN(value2))
}
function removeLocation (type) { function removeLocation (type) {
return type.replace(/( storage ref| storage pointer| memory| calldata)/g, '') return type.replace(/( storage ref| storage pointer| memory| calldata)/g, '')
} }
......
var BN = require('ethereumjs-util').BN
var ethutil = require('ethereumjs-util')
var util = require('../solidity-decoder/types/util')
module.exports = { module.exports = {
decodeMappingsKeys: decodeMappingsKeys decodeMappingsKeys: decodeMappingsKeys
...@@ -8,15 +11,22 @@ module.exports = { ...@@ -8,15 +11,22 @@ module.exports = {
* like { "<mapping_slot>" : { "<mapping-key1>": preimageOf1 }, { "<mapping-key2>": preimageOf2 }, ... } * like { "<mapping_slot>" : { "<mapping-key1>": preimageOf1 }, { "<mapping-key2>": preimageOf2 }, ... }
* *
* @param {Object} storage - storage given by storage Viewer (basically a mapping hashedkey : {key, value}) * @param {Object} storage - storage given by storage Viewer (basically a mapping hashedkey : {key, value})
* @param {Array} corrections - used in case the calculated sha3 has been modifyed before SSTORE (notably used for struct in mapping).
* @param {Function} callback - calback * @param {Function} callback - calback
* @return {Map} - solidity mapping location (e.g { "<mapping_slot>" : { "<mapping-key1>": preimageOf1 }, { "<mapping-key2>": preimageOf2 }, ... }) * @return {Map} - solidity mapping location (e.g { "<mapping_slot>" : { "<mapping-key1>": preimageOf1 }, { "<mapping-key2>": preimageOf2 }, ... })
*/ */
async function decodeMappingsKeys (web3, storage, callback) { async function decodeMappingsKeys (web3, storage, corrections, callback) {
var ret = {} var ret = {}
if (!corrections.length) corrections.push(0)
for (var hashedLoc in storage) { for (var hashedLoc in storage) {
var preimage var preimage
try { try {
preimage = await getPreimage(web3, storage[hashedLoc].key) var key = storage[hashedLoc].key
for (var k in corrections) {
var corrected = util.sub(key, corrections[k].slot).toString(16)
preimage = await getPreimage(web3, '0x' + corrected)
if (preimage) break
}
} catch (e) { } catch (e) {
} }
if (preimage) { if (preimage) {
......
...@@ -33,11 +33,13 @@ class StorageResolver { ...@@ -33,11 +33,13 @@ class StorageResolver {
* compute the mappgings type locations for the current address (cached for a debugging session) * compute the mappgings type locations for the current address (cached for a debugging session)
* note: that only retrieve the first 100 items. * note: that only retrieve the first 100 items.
* *
* @param {String} address - contract address * @param {Object} tx
* @param {Int} stepIndex
* @param {Object} address - storage * @param {Object} address - storage
* @param {Array} corrections - used in case the calculated sha3 has been modifyed before SSTORE (notably used for struct in mapping).
* @return {Function} - callback * @return {Function} - callback
*/ */
initialPreimagesMappings (tx, stepIndex, address, callback) { initialPreimagesMappings (tx, stepIndex, address, corrections, callback) {
const self = this const self = this
if (this.preimagesMappingByAddress[address]) { if (this.preimagesMappingByAddress[address]) {
return callback(null, this.preimagesMappingByAddress[address]) return callback(null, this.preimagesMappingByAddress[address])
...@@ -46,7 +48,7 @@ class StorageResolver { ...@@ -46,7 +48,7 @@ class StorageResolver {
if (error) { if (error) {
return callback(error) return callback(error)
} }
mappingPreimages.decodeMappingsKeys(self.web3, storage, (error, mappings) => { mappingPreimages.decodeMappingsKeys(self.web3, storage, corrections, (error, mappings) => {
if (error) { if (error) {
callback(error) callback(error)
} else { } else {
......
...@@ -72,12 +72,12 @@ class StorageViewer { ...@@ -72,12 +72,12 @@ class StorageViewer {
/** /**
* return all the possible mappings locations for the current context (cached) do not return state changes during the current transaction * return all the possible mappings locations for the current context (cached) do not return state changes during the current transaction
* *
* @param {Function} callback * @param {Array} corrections - used in case the calculated sha3 has been modifyed before SSTORE (notably used for struct in mapping).
*/ */
async initialMappingsLocation () { async initialMappingsLocation (corrections) {
if (!this.initialMappingsLocationPromise) { if (!this.initialMappingsLocationPromise) {
this.initialMappingsLocationPromise = new Promise((resolve, reject) => { this.initialMappingsLocationPromise = new Promise((resolve, reject) => {
this.storageResolver.initialPreimagesMappings(this.context.tx, this.context.stepIndex, this.context.address, (error, initialMappingsLocation) => { this.storageResolver.initialPreimagesMappings(this.context.tx, this.context.stepIndex, this.context.address, corrections, (error, initialMappingsLocation) => {
if (error) { if (error) {
reject(error) reject(error)
} else { } else {
...@@ -92,12 +92,12 @@ class StorageViewer { ...@@ -92,12 +92,12 @@ class StorageViewer {
/** /**
* return all the possible mappings locations for the current context (cached) and current mapping slot. returns state changes during the current transaction * return all the possible mappings locations for the current context (cached) and current mapping slot. returns state changes during the current transaction
* *
* @param {Function} callback * @param {Array} corrections - used in case the calculated sha3 has been modifyed before SSTORE (notably used for struct in mapping).
*/ */
async mappingsLocation () { async mappingsLocation (corrections) {
if (!this.currentMappingsLocationPromise) { if (!this.currentMappingsLocationPromise) {
this.currentMappingsLocationPromise = new Promise((resolve, reject) => { this.currentMappingsLocationPromise = new Promise((resolve, reject) => {
this.extractMappingsLocationChanges(this.storageChanges, (error, mappingsLocationChanges) => { this.extractMappingsLocationChanges(this.storageChanges, corrections, (error, mappingsLocationChanges) => {
if (error) { if (error) {
reject(error) reject(error)
} else { } else {
...@@ -111,14 +111,15 @@ class StorageViewer { ...@@ -111,14 +111,15 @@ class StorageViewer {
/** /**
* retrieve mapping location changes from the storage changes. * retrieve mapping location changes from the storage changes.
*
* @param {Function} callback * @param {Map} storageChanges
* @param {Array} corrections - used in case the calculated sha3 has been modifyed before SSTORE (notably used for struct in mapping).
*/ */
extractMappingsLocationChanges (storageChanges, callback) { extractMappingsLocationChanges (storageChanges, corrections, callback) {
if (this.mappingsLocationChanges) { if (this.mappingsLocationChanges) {
return callback(null, this.mappingsLocationChanges) return callback(null, this.mappingsLocationChanges)
} }
mappingPreimages.decodeMappingsKeys(this.web3, storageChanges, (error, mappings) => { mappingPreimages.decodeMappingsKeys(this.web3, storageChanges, corrections, (error, mappings) => {
if (!error) { if (!error) {
this.mappingsLocationChanges = mappings this.mappingsLocationChanges = mappings
return callback(null, this.mappingsLocationChanges) return callback(null, this.mappingsLocationChanges)
......
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