Commit 097c1409 authored by yann300's avatar yann300

fic Struct as value in Mapping

parent 32fda787
......@@ -12,10 +12,12 @@ class Mapping extends RefType {
}
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
var mappingsInitialPreimages
try {
mappingsInitialPreimages = await storageResolver.initialMappingsLocation()
mappingsInitialPreimages = await storageResolver.initialMappingsLocation(corrections)
this.initialDecodedState = await this.decodeMappingsLocation(mappingsInitialPreimages, location, storageResolver)
} catch (e) {
return {
......@@ -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
ret = Object.assign({}, this.initialDecodedState, ret) // merge changes
return {
......
......@@ -88,6 +88,10 @@ function add (value1, value2) {
return toBN(value1).add(toBN(value2))
}
function sub (value1, value2) {
return toBN(value1).sub(toBN(value2))
}
function removeLocation (type) {
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 = {
decodeMappingsKeys: decodeMappingsKeys
......@@ -8,15 +11,22 @@ module.exports = {
* like { "<mapping_slot>" : { "<mapping-key1>": preimageOf1 }, { "<mapping-key2>": preimageOf2 }, ... }
*
* @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
* @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 = {}
if (!corrections.length) corrections.push(0)
for (var hashedLoc in storage) {
var preimage
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) {
}
if (preimage) {
......
......@@ -33,11 +33,13 @@ class StorageResolver {
* compute the mappgings type locations for the current address (cached for a debugging session)
* note: that only retrieve the first 100 items.
*
* @param {String} address - contract address
* @param {Object} tx
* @param {Int} stepIndex
* @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
*/
initialPreimagesMappings (tx, stepIndex, address, callback) {
initialPreimagesMappings (tx, stepIndex, address, corrections, callback) {
const self = this
if (this.preimagesMappingByAddress[address]) {
return callback(null, this.preimagesMappingByAddress[address])
......@@ -46,7 +48,7 @@ class StorageResolver {
if (error) {
return callback(error)
}
mappingPreimages.decodeMappingsKeys(self.web3, storage, (error, mappings) => {
mappingPreimages.decodeMappingsKeys(self.web3, storage, corrections, (error, mappings) => {
if (error) {
callback(error)
} else {
......
......@@ -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
*
* @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) {
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) {
reject(error)
} else {
......@@ -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
*
* @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) {
this.currentMappingsLocationPromise = new Promise((resolve, reject) => {
this.extractMappingsLocationChanges(this.storageChanges, (error, mappingsLocationChanges) => {
this.extractMappingsLocationChanges(this.storageChanges, corrections, (error, mappingsLocationChanges) => {
if (error) {
reject(error)
} else {
......@@ -111,14 +111,15 @@ class StorageViewer {
/**
* 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) {
return callback(null, this.mappingsLocationChanges)
}
mappingPreimages.decodeMappingsKeys(this.web3, storageChanges, (error, mappings) => {
mappingPreimages.decodeMappingsKeys(this.web3, storageChanges, corrections, (error, mappings) => {
if (!error) {
this.mappingsLocationChanges = mappings
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