Created
July 6, 2022 11:14
-
-
Save sorXCode/58ff7db4cf4a36b049852a437af215a2 to your computer and use it in GitHub Desktop.
Reading storage layout in the EVM via web3.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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("----------------------") | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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