Skip to content

Instantly share code, notes, and snippets.

@sorXCode
Created July 6, 2022 11:14
Show Gist options
  • Save sorXCode/58ff7db4cf4a36b049852a437af215a2 to your computer and use it in GitHub Desktop.
Save sorXCode/58ff7db4cf4a36b049852a437af215a2 to your computer and use it in GitHub Desktop.
Reading storage layout in the EVM via web3.js
const Web3 = require("web3");
var web3 = new Web3("https://ropsten.infura.io/v3/YOUR-API-KEY"); // use a websocket connection
var contractAddress = "Contract Address"; //
getStorageValues();
async function getStorageValues(){
// #1 single variable uint
web3.eth.getStorageAt(contractAddress, 0).then(function(res){
console.log("firstVar:");
console.log(res);
console.log(parseInt(res, 16));
console.log("----------------------")
console.log("----------------------")
});
// # 2 single variable string
web3.eth.getStorageAt(contractAddress, 1).then(function(res){
console.log("secondVar:");
console.log(res);
console.log(web3.utils.toAscii(res));
console.log("----------------------")
console.log("----------------------")
});
// #3 a constant
// Constants are stored in the contract code
// #4 two variables in one slot
web3.eth.getStorageAt(contractAddress, 2).then(function(res){
console.log("thirdVar and fourth var:");
console.log(res);
console.log("----------------------")
console.log("----------------------")
});
// #5 staitc array
web3.eth.getStorageAt(contractAddress, 3).then(function(res){
console.log("Index 3: numberArray:");
console.log(res);
console.log("----------------------")
console.log("----------------------")
});
web3.eth.getStorageAt(contractAddress, 4).then(function(res){
console.log("Index 4: numberArray");
console.log(res);
console.log("----------------------")
console.log("----------------------")
});
web3.eth.getStorageAt(contractAddress, 5).then(function(res){
console.log("Index 5 numberArray:");
console.log(res);
console.log("----------------------")
console.log("----------------------")
});
// #6 dynamic array
resDynamicArray = await web3.eth.getStorageAt(contractAddress, 6);
console.log("Index: 6 dynamic Array");
console.log(resDynamicArray);
newIndex = web3.utils.soliditySha3(6); // Use soliditySha3 instead of SHA3 because they are different
console.log("new index: " + newIndex);
// Showing the first value of the dynamic array
storage01 = await web3.eth.getStorageAt(contractAddress, newIndex);
console.log("Storage01: " + storage01);
// Showing the second value of the dynamic array
console.log(newIndex);
newIndexPlus1 = BigInt(newIndex) + 1n; // Increasing the index by one
var hexIndexPlusOne = BigInt(newIndexPlus1).toString(16); // converting BigInt back to hex
if (hexIndexPlusOne.length % 2) { // get the padding right
hexIndexPlusOne = '0' + hexIndexPlusOne;
}
hexIndexPlusOne = '0x' + hexIndexPlusOne; // add the hex prefix
console.log(hexIndexPlusOne)
storage02 = await web3.eth.getStorageAt(contractAddress, hexIndexPlusOne); // look up the storage slot
console.log("Storage02: " + storage02);
// #7 Struct: Each member of a struct has its own continous index
web3.eth.getStorageAt(contractAddress, 7).then(function(res){
console.log("Index 7 Struct" + res);
console.log(web3.utils.toAscii(res));
console.log("----------------------")
console.log("----------------------")
});
web3.eth.getStorageAt(contractAddress, 8).then(function(res){
console.log(res);
console.log("Index 8 Struct" + parseInt(res, 16));
console.log("----------------------")
console.log("----------------------")
});
#8 Mapping
In order to read a mapping, you need the index and the key of the element
newKey = web3.utils.soliditySha3(10, 9); // Use soliditySha3 instead of SHA3 because they are different / key . index
console.log("Mapping: Key 10");
web3.eth.getStorageAt(contractAddress, newKey).then(function(res){
console.log(res);
console.log(parseInt(res, 16));
console.log("----------------------")
console.log("----------------------")
});
newKey =web3.utils.soliditySha3(11, 9); // Use soliditySha3 instead of SHA3 because they are different / key . index
console.log("Mapping: Key 11");
web3.eth.getStorageAt(contractAddress, newKey).then(function(res){
console.log(res);
console.log(parseInt(res, 16));
console.log("----------------------")
console.log("----------------------")
});
}
pragma solidity 0.8.13;
contract StorageContract{
// # 1 single variable uint
uint256 firstVar = 100;
// # 2 single variable string
string secondVar = "Hello World";
// #3 a constant
string constant myConst = "I am a constant";
// #4 two variables in one slot
uint128 thirdVar = 5555;
uint32 fourthVar = 1000000;
// #5 array
uint32[20] numberArray = [10,15,20,30,40,50,60,70,100,200,300,400,500,600,700,800,900,1000,2000,3000];
// #6 dynamic size array
uint256[] dynamicArray;
// #7 Struct
PersonStruct myPerson;
struct PersonStruct{
string name;
uint256 age;
}
// #8 mapping
mapping(uint256 => uint256) myMapping;
constructor(){
myMapping[10] = 12345;
myMapping[11] = 1234567890;
myPerson.name = "Alice";
myPerson.age = 25;
dynamicArray.push(1234);
dynamicArray.push(5678);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment