eth_getStorageAt
Retrieves the value from a storage position at a given address on the Zora network. This method allows direct access to contract storage slots, enabling you to read contract state variables, proxy implementation addresses, and other stored data.
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
address | string | Yes | The 20-byte address of the contract whose storage you want to read |
position | string | Yes | The hex-encoded storage position/slot number (32 bytes) |
blockNumber | string | Yes | Block number in hex, or block tag ("latest", "earliest", "pending") |
Storage Position Calculation
- Simple variables: Use slot number directly (e.g.,
0x0
,0x1
,0x2
) - Mappings:
keccak256(key + slot)
where key is padded to 32 bytes - Arrays: Length at slot, elements at
keccak256(slot) + index
- Structs: Each field occupies consecutive slots
Returns
Returns a 32-byte hex string representing the storage value. Values are left-padded with zeros if smaller than 32 bytes.
Code Examples
- cURL
- JavaScript
- Python
# Read storage slot 0 from USDC contract on Zora
curl -X POST https://api-zora-mainnet.n.dwellir.com/2307f636-d01d-4f85-ba5e-514ff37069f5 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"0x0",
"latest"
],
"id": 1
}'
// Read storage from Base USDC contract
const getStorage = async () => {
const response = await fetch('https://api-zora-mainnet.n.dwellir.com/2307f636-d01d-4f85-ba5e-514ff37069f5', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_getStorageAt',
params: [
'0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // Base USDC
'0x0', // Storage slot 0
'latest'
],
id: 1
})
});
const data = await response.json();
return data.result;
};
// Calculate mapping storage position
const getMappingSlot = (key, slot) => {
const keyPadded = key.padStart(64, '0');
const slotPadded = slot.toString(16).padStart(64, '0');
return web3.utils.keccak256('0x' + keyPadded + slotPadded);
};
import requests
from web3 import Web3
# Read storage from contract
def get_storage_at(address, position, block='latest'):
payload = {
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [address, position, block],
"id": 1
}
response = requests.post(
'https://api-zora-mainnet.n.dwellir.com/2307f636-d01d-4f85-ba5e-514ff37069f5',
json=payload,
headers={'Content-Type': 'application/json'}
)
return response.json()['result']
# Example: Read from Base USDC contract
usdc_address = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
storage_value = get_storage_at(usdc_address, '0x0')
# Calculate mapping storage position
def get_mapping_slot(key, slot):
key_padded = key.zfill(64)
slot_padded = hex(slot)[2:].zfill(64)
return Web3.keccak(bytes.fromhex(key_padded + slot_padded)).hex()
# Example: Get balance mapping for an address
balance_slot = get_mapping_slot('000000000000000000000000YourAddress', 9)
balance = get_storage_at(usdc_address, balance_slot)
Response Example
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
Use Cases
- Contract State Inspection: Read private or internal variables
- Proxy Implementation: Get implementation address from proxy contracts
- Token Balances: Access balance mappings directly
- Access Control: Check role assignments and permissions
- Debugging: Investigate contract state during development
Important Notes
- Storage values are always 32 bytes (64 hex characters plus 0x prefix)
- Unused storage slots return
0x0000000000000000000000000000000000000000000000000000000000000000
- Storage layout depends on Solidity version and compiler optimizations
- For dynamic arrays, slot contains length; actual data starts at
keccak256(slot)
- Packed structs may share storage slots for gas optimization
Need help? Contact our support team or check the Zora documentation.