Cast Storage

PUBLISHED ON
Apr 19, 2024
WRITTEN BY
BlockApex
DURATION
5 min
CATEGORY
Insights, Trending Projects

Introduction

Lets understand the smart contract storage model in Ethereum and EVM-based chains and how you can access the public and private variables of any smart contract deployed on the blockchain. We can do this by using cast storage.

Contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract Storage {
address public contractAddress = address(this);
bytes private BlockApex = hex"426c6f636b41706578";
uint256 public Slot = 0;
struct Passwords {
 string name;
uint256 secretKey;
string password;
}
Passwords[] private passwords;
mapping (uint256 => Passwords) private destiny;
}

Contract Address (Rinkeby) : 0xfE43d853eBa639c40d071ebd046c9F61fF215ebF

Contract Link : https://rinkeby.etherscan.io/address/0xfe43d853eba639c40d071ebd046c9f61ff215ebf

Let’s start: 

| - - - - - - - - - - - -Slot 0 - - - - - - - - - - - -|
address public contractAddress = address(this); 
| - - - - - - - - - - - -Slot 1 - - - - - - - - - - - -|
bytes private BlockApex = hex"426c6f636b41706578";
| - - - - - - - - - - - -Slot 2 - - - - - - - - - - - -|
uint256 public Slot = 0;
| - - - - - - - -No Slot Consumed- - - - - - - -|
struct Passwords {
string name;
uint256 secretKey;
string password;
}
| - - - - - - - - - - - -Slot 3 - - - - - - - - - - - -| // size will be here
Passwords[] private passwords;
| - - - - - - - - - - - -Slot 4 - - - - - - - - - - - -|
mapping (uint256 => Passwords) private destiny;

Static Sized Variables can be simply accessed with command of cast storage

Cast storage $ContractAddress slotNumber
cast storage 0xfE43d853eBa639c40d071ebd046c9F61fF215ebF 0

Similarly for the storage slot 1 

cast storage 0xfE43d853eBa639c40d071ebd046c9F61fF215ebF 1

This command will lead you to the data stored in memory slots. . 

The data you receive might be in hex, to make it meaningful try using (cast —to-ascii (hex))

Eg:

cast storage 0xfE43d853eBa639c40d071ebd046c9F61fF215ebF 1

Result: 0x426c6f636b417065780000000000000000000000000000000000000000000012

cast –to-ascii 0x426c6f636b417065780000000000000000000000000000000000000000000012

Result: BlockApex

Accessing mapping data in solidity is a little bit complex. First you  identify the slot where your mapping currently stands. In our case, the mapping is on the 4th slot. Another important thing to note is since mappings  are hashTables they are only accessed by keys so you need to pass [key + StorageSlot] to the keccak hashing function in order to retrieve the data. 

Eg: 

cast keccak (key + storageSlot) 
cast keccak “0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004

This command will give you the respective hash which is actually the slot of the first element  stored in mapping. To access the 2nd element increment in the key like:

Eg: 

cast keccak (key++  +  storageSlot) 
cast keccak “0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004

It will give you the hash slot of the 2nd item of the mapping, if you iterate through you can access all the items.

Now send this hash (result of keccak) to the cast command as follows 

Eg: 

cast storage $contractAddress hash
cast storage 0xfE43d853eBa639c40d071ebd046c9F61fF215ebF 0xabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe05

This command leads you to the 1st property of the struct that is saved in the mapping and further on as you increment in the key. 

Now the problem is if your mapping contains a struct, you only get the 1st element of the struct which is the string property [name] in our case.

Eg: 

struct Passwords {
string name;
uint256 secretKey;
string password;
}

To iterate further in the same struct, you need to increment one in your keccak hash, for instance if you get a hash like 

0xabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe05+1 (add 1) 

the next element is held in

0xabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe06

Now we send this updated hash to the cast command like 

Eg: 

cast storage $contractAddress hash
cast storage 0xfE43d853eBa639c40d071ebd046c9F61fF215ebF 0xabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe06

This leads you to the second element of the struct which is the secretKey.

Further add 1 again in the hash.

0xabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe06+1 

the next element is held in 0xabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe07

Again hit the contract with the updated hash and you will get the password which is the last element of the struct stored in mapping!

Congrats you have unveiled the mystery of Solidity internals!
PS: cast can come handy only if you want.

Also read :

Liquidity Challenges In Illiquid Marketplaces.

Cryptocurrency: Cutting-edge or Criminal?

The Collapse Of Blockchain Security

related reports

Subscribe to our Newsletter!