eth_getStorageAt
Examines storage contents from smart contracts deployed on the Bittensor network. This method provides direct access to contract state variables, enabling inspection of AI subnet configurations, validator registrations, and network parameters.
Parameters​
Parameter | Type | Required | Description |
---|---|---|---|
address | string | Yes | Smart contract address (20 bytes) to inspect |
position | string | Yes | Storage slot position as hex string (32 bytes, 0x-prefixed) |
blockNumber | string | Yes | Block number in hex or block tag ("latest", "earliest", "pending") |
Bittensor Storage Patterns​
- Registry contracts: Subnet IDs, validator keys, and network parameters
- Token contracts: TAO balances, staking amounts, and delegation mappings
- AI model state: Training progress, consensus data, and performance metrics
- Governance: Proposal states, voting records, and parameter updates
Returns​
A 32-byte hex string containing the storage value. Data smaller than 32 bytes is left-padded with zeros for consistent formatting.
Implementation Examples​
- cURL
- JavaScript
- Python
# Read storage from Bittensor registry contract
curl -X POST https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x0000000000000000000000000000000000000800",
"0x0",
"latest"
],
"id": 1
}'
// Bittensor network storage inspector
class BittensorStorageInspector {
constructor(apiKey) {
this.endpoint = `https://api-bittensor-mainnet.n.dwellir.com/${apiKey}`;
}
async getStorageAt(address, position, block = 'latest') {
const response = await fetch(this.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_getStorageAt',
params: [address, position, block],
id: 1
})
});
const data = await response.json();
if (data.error) {
throw new Error(`RPC Error: ${data.error.message}`);
}
return data.result;
}
// Calculate storage position for mapping
getMappingSlot(key, baseSlot) {
const keyPadded = key.replace('0x', '').padStart(64, '0');
const slotPadded = baseSlot.toString(16).padStart(64, '0');
return ethers.utils.keccak256('0x' + keyPadded + slotPadded);
}
// Parse Bittensor-specific data types
parseValue(hex, type) {
const value = BigInt(hex);
switch(type) {
case 'tao_amount':
return (Number(value) / 1e9).toFixed(9); // TAO has 9 decimals
case 'subnet_id':
return Number(value);
case 'validator_key':
return '0x' + hex.slice(-40); // Extract address
case 'stake_amount':
return (Number(value) / 1e9).toFixed(9);
case 'bool':
return value > 0n;
default:
return hex;
}
}
// Get subnet information
async getSubnetInfo(subnetContract, subnetId) {
const subnetSlot = this.getMappingSlot(
'0x' + subnetId.toString(16).padStart(64, '0'),
0 // Assuming subnets mapping at slot 0
);
const info = await this.getStorageAt(subnetContract, subnetSlot);
return {
id: subnetId,
isActive: this.parseValue(info, 'bool'),
rawData: info
};
}
// Get validator stake
async getValidatorStake(stakingContract, validatorKey) {
const stakeSlot = this.getMappingSlot(validatorKey, 1); // Stakes at slot 1
const stake = await this.getStorageAt(stakingContract, stakeSlot);
return this.parseValue(stake, 'stake_amount');
}
}
// Example usage
const inspector = new BittensorStorageInspector('YOUR_API_KEY');
// Read from Bittensor contracts
const registryAddress = '0x0000000000000000000000000000000000000800';
// Get total number of subnets
inspector.getStorageAt(registryAddress, '0x0')
.then(result => {
const subnetCount = parseInt(result, 16);
console.log('Total Subnets:', subnetCount);
});
// Check specific subnet
inspector.getSubnetInfo(registryAddress, 1)
.then(subnet => {
console.log('Subnet 1 Info:', subnet);
});
import requests
from web3 import Web3
from decimal import Decimal
class BittensorStorageAnalyzer:
def __init__(self, api_key):
self.api_url = f'https://api-bittensor-mainnet.n.dwellir.com/{api_key}'
self.w3 = Web3()
def get_storage_at(self, address, position, block='latest'):
"""Read storage from Bittensor contract"""
payload = {
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [address, position, block],
"id": 1
}
response = requests.post(
self.api_url,
json=payload,
headers={'Content-Type': 'application/json'}
)
result = response.json()
if 'error' in result:
raise Exception(f"RPC Error: {result['error']['message']}")
return result['result']
def calculate_mapping_slot(self, key, base_slot):
"""Calculate storage position for mapping"""
if isinstance(key, str) and key.startswith('0x'):
key_bytes = bytes.fromhex(key[2:].zfill(64))
elif isinstance(key, int):
key_bytes = key.to_bytes(32, 'big')
else:
key_bytes = bytes.fromhex(str(key).zfill(64))
slot_bytes = base_slot.to_bytes(32, 'big')
position = self.w3.keccak(key_bytes + slot_bytes).hex()
return position
def parse_tao_amount(self, hex_value):
"""Convert hex to TAO amount (9 decimals)"""
raw_amount = int(hex_value, 16)
return Decimal(raw_amount) / Decimal(10**9)
def parse_bittensor_value(self, hex_value, data_type):
"""Parse Bittensor-specific values"""
if data_type == 'tao':
return float(self.parse_tao_amount(hex_value))
elif data_type == 'subnet_id':
return int(hex_value, 16)
elif data_type == 'validator':
return '0x' + hex_value[-40:] # Extract address
elif data_type == 'bool':
return int(hex_value, 16) > 0
elif data_type == 'uint256':
return int(hex_value, 16)
else:
return hex_value
def get_subnet_validator_count(self, registry_addr, subnet_id):
"""Get number of validators in a subnet"""
# Assuming validator count stored in mapping
count_slot = self.calculate_mapping_slot(subnet_id, 2)
count_hex = self.get_storage_at(registry_addr, count_slot)
return self.parse_bittensor_value(count_hex, 'uint256')
def get_validator_registration(self, registry_addr, validator_key):
"""Check if validator is registered"""
reg_slot = self.calculate_mapping_slot(validator_key, 3)
reg_hex = self.get_storage_at(registry_addr, reg_slot)
return self.parse_bittensor_value(reg_hex, 'bool')
def get_staking_info(self, staking_addr, address):
"""Get staking information for an address"""
stake_slot = self.calculate_mapping_slot(address, 0)
stake_hex = self.get_storage_at(staking_addr, stake_slot)
# Get delegation info if applicable
delegation_slot = self.calculate_mapping_slot(address, 1)
delegation_hex = self.get_storage_at(staking_addr, delegation_slot)
return {
'stake_amount': self.parse_bittensor_value(stake_hex, 'tao'),
'delegated_to': self.parse_bittensor_value(delegation_hex, 'validator'),
'raw_stake': stake_hex,
'raw_delegation': delegation_hex
}
# Example usage for Bittensor network analysis
analyzer = BittensorStorageAnalyzer('YOUR_API_KEY')
# Common Bittensor contract addresses (examples)
REGISTRY_CONTRACT = '0x0000000000000000000000000000000000000800'
STAKING_CONTRACT = '0x0000000000000000000000000000000000000801'
try:
# Get total number of active subnets
total_subnets_hex = analyzer.get_storage_at(REGISTRY_CONTRACT, '0x0')
total_subnets = analyzer.parse_bittensor_value(total_subnets_hex, 'uint256')
print(f"Total Active Subnets: {total_subnets}")
# Check subnet 1 validator count
subnet_1_validators = analyzer.get_subnet_validator_count(REGISTRY_CONTRACT, 1)
print(f"Subnet 1 Validators: {subnet_1_validators}")
# Check validator registration
validator_key = '0x1234567890123456789012345678901234567890'
is_registered = analyzer.get_validator_registration(REGISTRY_CONTRACT, validator_key)
print(f"Validator {validator_key} registered: {is_registered}")
# Get staking information
staker_address = '0x0987654321098765432109876543210987654321'
staking_info = analyzer.get_staking_info(STAKING_CONTRACT, staker_address)
print(f"Staking Info: {staking_info}")
except Exception as e:
print(f"Error analyzing Bittensor storage: {e}")
Response Example​
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x0000000000000000000000000000000000000000000000000000000000000010"
}
Bittensor-Specific Use Cases​
- Subnet Analysis: Monitor subnet registration, validator counts, and network topology
- Validator Monitoring: Track validator stakes, performance metrics, and consensus participation
- TAO Token Tracking: Analyze token distribution, staking patterns, and delegation flows
- AI Model State: Inspect model training progress and consensus mechanisms
- Network Governance: Monitor proposal voting and parameter changes
Storage Layout for AI Networks​
Validator Registry​
// Common validator storage pattern
const validatorSlots = {
totalValidators: '0x0', // Total count at slot 0
validatorKeys: 1, // Mapping: validatorId => key
validatorStakes: 2, // Mapping: validator => stake
subnetAssignments: 3, // Mapping: validator => subnet
lastActive: 4 // Mapping: validator => timestamp
};
Subnet Configuration​
// Subnet state storage
const subnetSlots = {
subnetCount: '0x5', // Total active subnets
subnetConfigs: 6, // Mapping: subnetId => config
validatorCounts: 7, // Mapping: subnetId => count
consensusParams: 8, // Mapping: subnetId => params
rewards: 9 // Mapping: subnetId => rewards
};
TAO Token and Staking​
// Token and staking storage
const stakingSlots = {
totalStaked: '0xa', // Total TAO staked
userStakes: 11, // Mapping: user => amount
delegations: 12, // Mapping: delegator => validator
stakingRewards: 13, // Mapping: staker => rewards
lockPeriods: 14 // Mapping: stake => unlock_time
};
AI Network Considerations​
- TAO amounts use 9 decimal places (1 TAO = 1e9 units)
- Validator keys are often stored as addresses in the rightmost 20 bytes
- Subnet IDs are typically small integers stored in 32-byte slots
- Consensus data may be packed efficiently to minimize storage costs
- Historical validator performance may be stored in array structures
Need help? Contact our support team or check the Bittensor documentation.