Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
calculateErc7201(keccak256: Function, id: string): Uint8Array
Calculates a collision-resistant storage slot using the ERC-7201 formula: keccak256(keccak256(id) - 1) & ~0xff.
The last byte is cleared to provide an additional 256 slots for related storage variables.
Parameters:
keccak256: (data: Uint8Array) => Uint8Array - Keccak256 hash function
id: string - Namespace identifier (recommend reverse domain notation)
Returns: Uint8Array - 32-byte storage slot with last byte cleared
Example:
import { calculateErc7201 } from '@tevm/voltaire/Storage';
import { keccak256 } from '@tevm/voltaire/crypto';
// Calculate storage slot for namespace
const slot = calculateErc7201(keccak256, 'example.main.storage');
console.log(Buffer.from(slot).toString('hex'));
// "c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181c0"
// Note: Last byte is 0x00
Defined in: src/primitives/Storage/calculateErc7201.js
1. innerHash = keccak256(id)
2. decremented = innerHash - 1
3. outerHash = keccak256(decremented)
4. result = outerHash & ~0xff // Clear last byte
The formula provides:
- Collision resistance: Double hash prevents preimage attacks
- 256 slots: Last byte cleared provides slots 0x00-0xFF for related variables
- Deterministic: Same ID always produces same slot
Usage Patterns
Solidity Storage Pattern
import { calculateErc7201 } from '@tevm/voltaire/Storage';
import { keccak256 } from '@tevm/voltaire/crypto';
// Calculate slot for Solidity contract
const namespace = 'com.example.mycontract.storage';
const slot = calculateErc7201(keccak256, namespace);
// Convert to Solidity hex literal
const hexSlot = '0x' + Buffer.from(slot).toString('hex');
console.log(`
bytes32 private constant STORAGE_LOCATION = ${hexSlot};
struct MyStorage {
uint256 value;
mapping(address => uint256) balances;
}
function _getStorage() private pure returns (MyStorage storage $) {
assembly {
$.slot := STORAGE_LOCATION
}
}
`);
import { calculateErc7201 } from '@tevm/voltaire/Storage';
import { keccak256 } from '@tevm/voltaire/crypto';
// Main storage slot
const baseSlot = calculateErc7201(keccak256, 'my.contract.storage');
// Related slots (last byte can be 0x00 - 0xFF)
const adminSlot = new Uint8Array(baseSlot);
adminSlot[31] = 0x01;
const configSlot = new Uint8Array(baseSlot);
configSlot[31] = 0x02;
const dataSlot = new Uint8Array(baseSlot);
dataSlot[31] = 0x03;
// All slots guaranteed collision-free
Namespace Conventions
import { calculateErc7201 } from '@tevm/voltaire/Storage';
import { keccak256 } from '@tevm/voltaire/crypto';
// ✅ Good: Reverse domain notation
calculateErc7201(keccak256, 'org.uniswap.v3.storage');
calculateErc7201(keccak256, 'com.openzeppelin.access.ownable');
// ✅ Good: Contract-specific namespaces
calculateErc7201(keccak256, 'MyToken.balances');
calculateErc7201(keccak256, 'MyToken.allowances');
// ❌ Bad: Too generic (collision risk across projects)
calculateErc7201(keccak256, 'storage');
calculateErc7201(keccak256, 'data');
Comparison with ERC-8042
| Feature | ERC-7201 | ERC-8042 |
|---|
| Formula | keccak256(keccak256(id) - 1) & ~0xff | keccak256(id) |
| Related slots | 256 (last byte) | None |
| Collision resistance | Higher (double hash) | Standard (single hash) |
| Use case | General upgradeable contracts | Diamond Standard |
See Also