From 93ae75446d354f3d277e85f51d9eb858920627de Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 7 Sep 2022 15:45:23 +0200 Subject: [PATCH 1/4] fix storage at --- libs/remix-simulator/src/VmProxy.ts | 16 ++++++++++++++-- libs/remix-simulator/src/methods/blocks.ts | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libs/remix-simulator/src/VmProxy.ts b/libs/remix-simulator/src/VmProxy.ts index f7090d8b1d..f4e72c2efe 100644 --- a/libs/remix-simulator/src/VmProxy.ts +++ b/libs/remix-simulator/src/VmProxy.ts @@ -132,6 +132,7 @@ export class VmProxy { this.txs[this.processingHash] = tx this.txsReceipt[this.processingHash] = tx this.storageCache[this.processingHash] = {} + this.storageCache['after_' + this.processingHash] = {} if (data.to) { try { const storage = await this.vm.stateManager.dumpStorage(data.to) @@ -175,6 +176,17 @@ export class VmProxy { const status = data.execResult.exceptionError ? 0 : 1 this.txsReceipt[this.processingHash].status = `0x${status}` + const to = this.txs[this.processingHash].to + if (to) { + try { + const account = Address.fromString(to) + const storage = await this.vm.stateManager.dumpStorage(account) + this.storageCache['after_' + this.processingHash][to] = storage + } catch (e) { + console.log(e) + } + } + if (data.createdAddress) { const address = data.createdAddress.toString() this.vmTraces[this.processingHash].return = toChecksumAddress(address) @@ -308,8 +320,8 @@ export class VmProxy { - if (this.storageCache[txHash] && this.storageCache[txHash][address]) { - const storage = this.storageCache[txHash][address] + if (this.storageCache['after_' + txHash] && this.storageCache['after_' + txHash][address]) { + const storage = this.storageCache['after_' + txHash][address] return cb(null, { storage: JSON.parse(JSON.stringify(storage)), nextKey: null diff --git a/libs/remix-simulator/src/methods/blocks.ts b/libs/remix-simulator/src/methods/blocks.ts index e2594b05ac..1651499cd2 100644 --- a/libs/remix-simulator/src/methods/blocks.ts +++ b/libs/remix-simulator/src/methods/blocks.ts @@ -173,7 +173,7 @@ export class Blocks { } eth_getStorageAt (payload, cb) { - const [address, position, blockNumber] = payload.params + const [ address, position, blockNumber ] = payload.params this.vmContext.web3().debug.storageRangeAt(blockNumber, 'latest', address.toLowerCase(), position, 1, (err, result) => { if (err || (result.storage && Object.values(result.storage).length === 0)) { From 48977a8cc5ed10d3fd3daff2c0cd1359e71cf98c Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 8 Sep 2022 11:11:14 +0200 Subject: [PATCH 2/4] fix unit tests --- libs/remix-simulator/test/blocks.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/remix-simulator/test/blocks.ts b/libs/remix-simulator/test/blocks.ts index 47e7f8ba9e..5ffb448070 100644 --- a/libs/remix-simulator/test/blocks.ts +++ b/libs/remix-simulator/test/blocks.ts @@ -212,13 +212,13 @@ describe('blocks', () => { let storage = await web3.eth.getStorageAt(contractInstance.options.address, 0) assert.deepEqual(storage, '0x64') - await contractInstance.methods.set(200).send({ from: accounts[0], gas: 400000 }) + await contractInstance.methods.set(200).send({ from: accounts[0].toLowerCase(), gas: 400000 }) storage = await web3.eth.getStorageAt(contractInstance.options.address, 0) - assert.deepEqual(storage, '0x64') + assert.deepEqual(storage, '0xc8') - await contractInstance.methods.set(200).send({ from: accounts[0], gas: 400000 }) + await contractInstance.methods.set(1).send({ from: accounts[0].toLowerCase(), gas: 400000 }) storage = await web3.eth.getStorageAt(contractInstance.options.address, 0) - assert.deepEqual(storage, '0xc8') + assert.deepEqual(storage, '0x01') }) }) describe('eth_call', () => { From 51c79c823634b5de47008d061ab82596f2636710 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 8 Sep 2022 12:09:48 +0200 Subject: [PATCH 3/4] fix eth_getStorageAt --- libs/remix-simulator/src/VmProxy.ts | 11 ++--------- libs/remix-simulator/src/methods/blocks.ts | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/libs/remix-simulator/src/VmProxy.ts b/libs/remix-simulator/src/VmProxy.ts index f4e72c2efe..a49043f295 100644 --- a/libs/remix-simulator/src/VmProxy.ts +++ b/libs/remix-simulator/src/VmProxy.ts @@ -310,15 +310,8 @@ export class VmProxy { // we don't use the range params here address = toChecksumAddress(address) - let txHash - if (txIndex === 'latest') { - txHash = this.lastProcessedStorageTxHash[address] - } else { - const block = this.vmContext.blocks[blockNumber] - txHash = '0x' + block.transactions[txIndex].hash().toString('hex') - } - - + const block = this.vmContext.blocks[blockNumber] + const txHash = '0x' + block.transactions[txIndex].hash().toString('hex') if (this.storageCache['after_' + txHash] && this.storageCache['after_' + txHash][address]) { const storage = this.storageCache['after_' + txHash][address] diff --git a/libs/remix-simulator/src/methods/blocks.ts b/libs/remix-simulator/src/methods/blocks.ts index 1651499cd2..cd0d220fc5 100644 --- a/libs/remix-simulator/src/methods/blocks.ts +++ b/libs/remix-simulator/src/methods/blocks.ts @@ -175,7 +175,7 @@ export class Blocks { eth_getStorageAt (payload, cb) { const [ address, position, blockNumber ] = payload.params - this.vmContext.web3().debug.storageRangeAt(blockNumber, 'latest', address.toLowerCase(), position, 1, (err, result) => { + this.vmContext.web3().debug.storageRangeAt(blockNumber + 1, 0, address.toLowerCase(), position, 1, (err, result) => { if (err || (result.storage && Object.values(result.storage).length === 0)) { return cb(err, '') } From b580a09837b7be3be337ebb9b002225b6fc522f1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 8 Sep 2022 15:55:29 +0200 Subject: [PATCH 4/4] fix test --- libs/remix-simulator/src/VmProxy.ts | 28 ++++++++++++++++++---- libs/remix-simulator/src/methods/blocks.ts | 23 +++++++----------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/libs/remix-simulator/src/VmProxy.ts b/libs/remix-simulator/src/VmProxy.ts index a49043f295..dcc834b617 100644 --- a/libs/remix-simulator/src/VmProxy.ts +++ b/libs/remix-simulator/src/VmProxy.ts @@ -3,7 +3,7 @@ const { hexListFromBNs, formatMemory } = util import { helpers } from '@remix-project/remix-lib' const { normalizeHexAddress } = helpers.ui import { ConsoleLogs } from '@remix-project/remix-lib' -import { toChecksumAddress, BN, bufferToHex, Address } from 'ethereumjs-util' +import { toChecksumAddress, BN, keccak, bufferToHex, Address, toBuffer } from 'ethereumjs-util' import Web3 from 'web3' import { ethers } from 'ethers' import { VMContext } from './vm-context' @@ -40,7 +40,6 @@ export class VmProxy { utils txsMapBlock blocks - latestBlockNumber constructor (vmContext: VMContext) { this.vmContext = vmContext @@ -62,6 +61,7 @@ export class VmProxy { this.eth.getTransactionReceipt = (txHash, cb) => this.getTransactionReceipt(txHash, cb) this.eth.getTransactionFromBlock = (blockNumber, txIndex, cb) => this.getTransactionFromBlock(blockNumber, txIndex, cb) this.eth.getBlockNumber = (cb) => this.getBlockNumber(cb) + this.eth.getStorageAt = (address: string, position: string, blockNumber: string, cb) => this.getStorageAt(address, position, blockNumber, cb) this.debug.traceTransaction = (txHash, options, cb) => this.traceTransaction(txHash, options, cb) this.debug.storageRangeAt = (blockNumber, txIndex, address, start, maxLength, cb) => this.storageRangeAt(blockNumber, txIndex, address, start, maxLength, cb) this.debug.preimage = (hashedKey, cb) => this.preimage(hashedKey, cb) @@ -83,7 +83,6 @@ export class VmProxy { this.utils = Web3.utils || [] this.txsMapBlock = {} this.blocks = {} - this.latestBlockNumber = 0 } setVM (vm) { @@ -306,15 +305,34 @@ export class VmProxy { } } - storageRangeAt (blockNumber, txIndex, address, start, maxLength, cb) { + getStorageAt (address: string, position: string, blockNumber: string, cb) { // we don't use the range params here address = toChecksumAddress(address) + + blockNumber = blockNumber === 'latest' ? this.vmContext.latestBlockNumber : blockNumber const block = this.vmContext.blocks[blockNumber] - const txHash = '0x' + block.transactions[txIndex].hash().toString('hex') + const txHash = '0x' + block.transactions[block.transactions.length - 1].hash().toString('hex') if (this.storageCache['after_' + txHash] && this.storageCache['after_' + txHash][address]) { + const slot = '0x' + keccak(toBuffer(ethers.utils.hexZeroPad(position, 32))).toString('hex') const storage = this.storageCache['after_' + txHash][address] + return cb(null, storage[slot].value) + } + // Before https://github.com/ethereum/remix-project/pull/1703, it used to throw error as + // 'unable to retrieve storage ' + txIndex + ' ' + address + cb(null, { storage: {} }) + } + + storageRangeAt (blockNumber, txIndex, address, start, maxLength, cb) { + // we don't use the range params here + address = toChecksumAddress(address) + + const block = this.vmContext.blocks[blockNumber] + const txHash = '0x' + block.transactions[txIndex].hash().toString('hex') + + if (this.storageCache[txHash] && this.storageCache[txHash][address]) { + const storage = this.storageCache[txHash][address] return cb(null, { storage: JSON.parse(JSON.stringify(storage)), nextKey: null diff --git a/libs/remix-simulator/src/methods/blocks.ts b/libs/remix-simulator/src/methods/blocks.ts index cd0d220fc5..cc6f96f042 100644 --- a/libs/remix-simulator/src/methods/blocks.ts +++ b/libs/remix-simulator/src/methods/blocks.ts @@ -1,7 +1,7 @@ import Web3 from 'web3' - +import { VMContext } from '../vm-context' export class Blocks { - vmContext + vmContext: VMContext coinbase: string TX_INDEX = '0x0' // currently there's always only 1 tx per block, so the transaction index will always be 0x0 constructor (vmContext, _options) { @@ -73,7 +73,7 @@ export class Blocks { stateRoot: this.toHex(block.header.stateRoot), miner: this.coinbase, difficulty: this.toHex(block.header.difficulty), - totalDifficulty: this.toHex(block.header.totalDifficulty), + totalDifficulty: this.toHex((block.header as any).totalDifficulty), extraData: this.toHex(block.header.extraData), size: '0x027f07', // 163591 gasLimit: this.toHex(block.header.gasLimit), @@ -127,7 +127,7 @@ export class Blocks { stateRoot: this.toHex(block.header.stateRoot), miner: this.coinbase, difficulty: this.toHex(block.header.difficulty), - totalDifficulty: this.toHex(block.header.totalDifficulty), + totalDifficulty: this.toHex((block.header as any).totalDifficulty), extraData: this.toHex(block.header.extraData), size: '0x027f07', // 163591 gasLimit: this.toHex(block.header.gasLimit), @@ -173,15 +173,10 @@ export class Blocks { } eth_getStorageAt (payload, cb) { - const [ address, position, blockNumber ] = payload.params - - this.vmContext.web3().debug.storageRangeAt(blockNumber + 1, 0, address.toLowerCase(), position, 1, (err, result) => { - if (err || (result.storage && Object.values(result.storage).length === 0)) { - return cb(err, '') - } - - const value = Object.values(result.storage)[0]['value'] - cb(err, value) - }) + return this.vmContext.web3().eth.getStorageAt( + payload.params[0], + payload.params[1], + payload.params[2], + cb) } }