Merge pull request #2893 from ethereum/fix-getstorageat-rpc

fix storageAt rpc call
pull/2831/head
bunsenstraat 2 years ago committed by GitHub
commit 2cbfb34873
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 47
      libs/remix-simulator/src/VmProxy.ts
  2. 23
      libs/remix-simulator/src/methods/blocks.ts
  3. 8
      libs/remix-simulator/test/blocks.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) {
@ -132,6 +131,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 +175,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)
@ -294,19 +305,31 @@ 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
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[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]

@ -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, 'latest', 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)
}
}

@ -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', () => {

Loading…
Cancel
Save