How to read Ethereum contract storage

Darius
Darius
Sep 14, 2017 · 3 min read

Everybody is talking that data in contracts are public, but not everybody knows how to read it.

All contracts deployed to ethereum VM has dedicated storage where stores state. Here is an example how to read this storage with the web3.js library using eth.getStorageAt() method.

Contract example which we examine:

Image for post
Image for post

This contract is deployed in ropsten test net: at 0xf1f5896ace3a78c347eb7eab503450bc93bd0c3b

All parameters in the storage are indexed from the beginning. One index takes 256 bytes ant it fits 64 symbols. In this example, we have 10 parameters and we can iterate them:

let contractAddress = '0xf1f5896ace3a78c347eb7eab503450bc93bd0c3b'
for (index = 0; index < 10; index++){
console.log(`[${index}]` +
web3.eth.getStorageAt(contractAddress, index))
}
result:
[0] 0x000000000000000000000000000000000000000000000000000000000000000f
[1] 0x00000000000000000000000059b92d9a0000000000000000000000000000429f
[2] 0x0000000000000000000000000000000074657374310000000000000000000000
[3] 0x7465737431323336000000000000000000000000000000000000000000000000
[4] 0x6c65747320737472696e6720736f6d657468696e67000000000000000000002a
[5] 0x0000000000000000000000000000000000000000000000000000000000000000
[6] 0x0000000000000000000000000000000000000000000000000000000000000000
[7] 0x0000000000000000000000000000000000000000000000000000000000000002
[8] 0x0000000000000000000000000000000000000000000000000000000000000002
[9] 0x0000000000000000000000000000000000000000000000000000000000000000

Let`s have a deeper look into each parameter

Index 0 — storeduint1

let contractAddress = '0xf1f5896ace3a78c347eb7eab503450bc93bd0c3b'
let index = 0
console.log(web3.eth.getStorageAt(contractAddress, index))
console.log('DEC:' + web3.toDecimal(web3.eth.getStorageAt(contractAddress, index)))
result:
0x000000000000000000000000000000000000000000000000000000000000000f
DEC:15

constuint

Index 1 — investmentsLimit, investmentsDeadlineTimeStamp

let index = 1
console.log(web3.eth.getStorageAt(contractAddress, index))
result:
0x00000000000000000000000059b92d9a0000000000000000000000000000429f
DEC: 1505308058 and 17055

In index 1 is merged 2 properties to optimize storage usage.

index 2 — string1

index = 2
console.log(web3.eth.getStorageAt(contractAddress, index))
console.log('ASCII: ' +
web3.toAscii(web3.eth.getStorageAt(contractAddress, index)))
result:
0x0000000000000000000000000000000074657374310000000000000000000000
ASCII: test1

index 3 — string2

index = 3
console.log(web3.eth.getStorageAt(contractAddress, index))
console.log('ASCII: ' +
web3.toAscii(web3.eth.getStorageAt(contractAddress, index)))
result:
0x7465737431323336000000000000000000000000000000000000000000000000
ASCII: test1236

index 4— string3

index = 4
console.log(web3.eth.getStorageAt(contractAddress, index))
console.log('ASCII: ' +
web3.toAscii(web3.eth.getStorageAt(contractAddress, index)))
result:
0x6c65747320737472696e6720736f6d657468696e67000000000000000000002a
ASCII: lets string something * (42)

End symbol 2a (dec 42) is length of the stored string. (more details http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage)

index 5 — uints1

index = 5
console.log(web3.eth.getStorageAt(contractAddress, index))
result:
0x0000000000000000000000000000000000000000000000000000000000000000
PROBLEM!!!!

Mappings have a different indexation and should be read in other way. To read mapping value you should know the key value. Otherwise, read mapping value is impossible.

index = '0000000000000000000000000000000000000000000000000000000000000005'
key = '00000000000000000000000xbccc714d56bc0da0fd33d96d2a87b680dd6d0df6'
let newKey = web3.sha3(key + index, {"encoding":"hex"})console.log(web3.eth.getStorageAt(contractAddress, newKey))
console.log('DEC: ' + web3.toDecimal(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x0000000000000000000000000000000000000000000000000000000000000058
DEC: 88

index6 — structs1

index = "0000000000000000000000000000000000000000000000000000000000000006"
key = "00000000000000000000000xbccc714d56bc0da0fd33d96d2a87b680dd6d0df6"
let newKey = web3.sha3(key + index, {"encoding":"hex"})
console.log(web3.eth.getStorageAt(contractAddress, newKey))
console.log('ASCII: ' +
web3.toAscii(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x6465766963654272616e64000000000000000000000000000000000000000016
ASCII: deviceBrand

To read second struct value you need to increase newKey value by 1

function increaseHexByOne(hex) {
let x = new BigNumber(hex)
let sum = x.add(1)
let result = '0x' + sum.toString(16)
return result
}
index = "0000000000000000000000000000000000000000000000000000000000000006"
key = "00000000000000000000000xbccc714d56bc0da0fd33d96d2a87b680dd6d0df6"
let newKey = increaseHexByOne(
web3.sha3(key + index, {"encoding":"hex"}))
console.log(web3.eth.getStorageAt(contractAddress,newKey))
console.log('ASCII: ' +
web3.toAscii(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x6465766963655965617200000000000000000000000000000000000000000014
ASCII: deviceYear

If you want third struct value increase newKey once more.

index 7— uintarray

index = "7"
console.log(web3.eth.getStorageAt(contractAddress, index))
result:
0x0000000000000000000000000000000000000000000000000000000000000002

This array has 2 items

index = "0000000000000000000000000000000000000000000000000000000000000007"
let newKey = web3.sha3(index, {"encoding":"hex"})
console.log(web3.eth.getStorageAt(contractAddress, newKey))
console.log('DEC: ' +
web3.toDecimal(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x0000000000000000000000000000000000000000000000000000000000001f40
DEC: 8000
newKey = increaseHexByOne(web3.sha3(index, {"encoding":"hex"}))console.log(web3.eth.getStorageAt(contractAddress, newKey))
console.log('DEC: ' +
web3.toDecimal(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x0000000000000000000000000000000000000000000000000000000000002328
DEC: 9000

index 8— deviceDataArray

index = "0000000000000000000000000000000000000000000000000000000000000008"let newKey = web3.sha3(index, {"encoding":"hex"})console.log(web3.eth.getStorageAt(contractAddress, newKey))
console.log('ASCII: ' +
web3.toAscii(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x6465766963654272616e64000000000000000000000000000000000000000016
ASCII: deviceBrand
index = "0000000000000000000000000000000000000000000000000000000000000008"let newKey = increaseHexByOne(web3.sha3(index, {"encoding":"hex"}))console.log(web3.eth.getStorageAt(contractAddress, newKey))
console.log('ASCII: ' +
web3.toAscii(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x6465766963655965617200000000000000000000000000000000000000000014
ASCII: deviceYear

Increase by 2 result:

0x776561724c6576656c0000000000000000000000000000000000000000000012

ASCII: wearLevel

Increase by 3 you enter to second item into array result:

0x6465766963654272616e64320000000000000000000000000000000000000018

ASCII: deviceBrand2

Sources:
https://github.com/ethereum/solidity/issues/1550
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat
https://ethereum.stackexchange.com/questions/13910/how-to-read-a-private-variable-from-a-contract
https://github.com/ethereum/web3.js/issues/445

Check out our testing ground — Aigang!

More about Aigang — http://bit.ly/AigangWebsite
Aigang Whitepaper — http://bit.ly/2hwAtkt
Aigang on Telegram — http://bit.ly/AigangTelegram
Get Aigang Latest Updates — http://bit.ly/AigangUpdates

Aigang

Autonomous insurance network — fully automated insurance…

Thanks to Jonas Matk

Darius

Written by

Darius

Aigang

Aigang

Autonomous insurance network — fully automated insurance for IoT devices and a platform for insurance innovation built around data

Darius

Written by

Darius

Aigang

Aigang

Autonomous insurance network — fully automated insurance for IoT devices and a platform for insurance innovation built around data

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store