Merge pull request #905 from ethereum/fixStructinMapping

Fix Decoding struct in mapping
pull/5370/head
yann300 6 years ago committed by GitHub
commit 77ede5f588
  1. 5
      remix-debug/src/solidity-decoder/types/Mapping.js
  2. 5
      remix-debug/src/solidity-decoder/types/util.js
  3. 12
      remix-debug/src/storage/mappingPreimages.js
  4. 8
      remix-debug/src/storage/storageResolver.js
  5. 20
      remix-debug/src/storage/storageViewer.js

@ -12,10 +12,11 @@ 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 +25,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 {

@ -9,6 +9,7 @@ module.exports = {
extractHexByteSlice: extractHexByteSlice,
toBN: toBN,
add: add,
sub: sub,
extractLocation: extractLocation,
removeLocation: removeLocation,
normalizeHex: normalizeHex,
@ -88,6 +89,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, '')
}

@ -1,3 +1,4 @@
var util = require('../solidity-decoder/types/util')
module.exports = {
decodeMappingsKeys: decodeMappingsKeys
@ -8,15 +9,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({offset: 0, slot: 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,14 @@ 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)

Loading…
Cancel
Save