# EIP-799: Ethereum Auction Identifier Algorithm
[TOC]
## Abstract
This EIP defines an algorithm for generating 64-bit auction identifiers by combining a 16-bit chain ID with a 48-bit slot number, creating globally unique, time-ordered identifiers for auction systems across Ethereum networks.
## Motivation
Auction systems need identifiers that are:
- Globally unique across all Ethereum chains
- Time-ordered for efficient querying
- Compact for on-chain storage (8 bytes vs 32 for hashes)
- Deterministically generated without external dependencies
## Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Identifier Structure
An Auction ID SHALL be represented as a 64-bit unsigned integer with the following bit layout:
### Algorithm
An Auction ID is a 64-bit unsigned integer constructed as:
```
AuctionID = (ChainID << 48) | SlotNumber
```
Where:
- `ChainID`: 16-bit EIP-155 chain identifier (0-65535)
- `SlotNumber`: 48-bit beacon chain slot number (0-281474976710655)
### Bit Layout
```
┌─────────────────┬───────────────────────────────────────────────┐
│ Bits 63-48 │ Bits 47-0 │
├─────────────────┼───────────────────────────────────────────────┤
│ Chain ID (16) │ Slot Number (48) │
└─────────────────┴───────────────────────────────────────────────┘
```
### Field Specifications
#### Chain ID (16 bits)
- **Purpose**: Identifies the blockchain network per EIP-155
- **Range**: 0 to 65,535 (0x0000 to 0xFFFF)
- **Encoding**: Big-endian unsigned 16-bit integer
- **Reserved Values**:
- `0x0000`: RESERVED for testing environments
- `0x0001`: Ethereum Mainnet
- Other values: As defined in the [Chainlist Registry](https://chainlist.org)
#### Slot Number (48 bits)
- **Purpose**: Represents the Beacon Chain slot number
- **Range**: 0 to 281,474,976,710,655 (0x000000000000 to 0xFFFFFFFFFFFF)
- **Encoding**: Big-endian unsigned 48-bit integer
- **Pre-Merge Conversion**: For blocks before The Merge, implementers SHOULD use: `slot = blockNumber * 12`
### Serialization Requirements
Implementations **MUST** support the following serialization formats:
1. **Canonical Hex Format**:
- 16 hexadecimal characters with `0x` prefix
- Zero-padded to 16 characters
- Example: `0x0001000000abcdef`
2. **Decimal String Format**:
- Decimal representation as string
- MUST support BigInt suffix `n` in JavaScript environments
- Example: `281474976710656n`
3. **Binary Format**:
- 8-byte array in big-endian byte order
- Example: `[0x00, 0x01, 0x00, 0x00, 0x00, 0xab, 0xcd, 0xef]`
## Examples
```
Original Chain ID: 1
Original Slot: 8,234,567
Generated ID: 281474984945223
Decoded: (Chain: 1, Slot: 8,234,567)
```
```
ID for Slot 9,000,000:
-> Generated ID (Decimal): 281474985710656
-> Hex: 0x1000000895440
-> Decoded (Chain: 1, Slot: 9,000,000)
ID for Slot 9,000,001:
-> Generated ID (Decimal): 281474985710657
-> Hex: 0x1000000895441
-> Decoded (Chain: 1, Slot: 9,000,001)
ID for Slot 9,000,002:
-> Generated ID (Decimal): 281474985710658
-> Hex: 0x1000000895442
-> Decoded (Chain: 1, Slot: 9,000,002)
ID for Slot 9,000,003:
-> Generated ID (Decimal): 281474985710659
-> Hex: 0x1000000895443
-> Decoded (Chain: 1, Slot: 9,000,003)
ID for Slot 9,000,004:
-> Generated ID (Decimal): 281474985710660
-> Hex: 0x1000000895444
-> Decoded (Chain: 1, Slot: 9,000,004)
```
### Core Functions
#### Generation
```solidity
function generateAuctionId(uint16 chainId, uint48 slot) pure returns (uint64) {
return (uint64(chainId) << 48) | uint64(slot);
}
```
#### Decoding
```solidity
function decodeAuctionId(uint64 auctionId) pure returns (uint16 chainId, uint48 slot) {
chainId = uint16(auctionId >> 48);
slot = uint48(auctionId);
}
```
### Slot Number Determination
- **Post-Merge**: Use beacon chain slot directly
- **Pre-Merge**: Calculate as `slot = blockNumber * 12`
## Rationale
### Why 64 bits?
- Single EVM stack value
- Efficient storage (fits 4 IDs per storage slot)
- Sufficient range for all practical use cases
### Why this bit allocation?
- **16-bit Chain ID**: Supports 65,536 chains (current: ~200)
- **48-bit Slot**: Supports 281 trillion slots (~107,000 years at 12s/slot)
### Benefits over alternatives
- **vs Hashes**: 75% smaller, preserves temporal ordering
- **vs Sequential IDs**: Cross-chain unique, no coordinator needed
- **vs UUIDs**: Deterministic, time-ordered, more compact
## Reference Implementation
### JavaScript/TypeScript
```javascript
class AuctionId {
static generate(chainId, slot) {
if (chainId > 0xFFFF) throw new Error("Chain ID out of range");
if (slot > 0xFFFFFFFFFFFF) throw new Error("Slot out of range");
return (BigInt(chainId) << 48n) | BigInt(slot);
}
static decode(auctionId) {
return {
chainId: Number((BigInt(auctionId) >> 48n) & 0xFFFFn),
slot: BigInt(auctionId) & 0xFFFFFFFFFFFFn
};
}
}
```
### Solidity
```solidity
library AuctionIdLib {
function generate(uint16 chainId, uint48 slot) internal pure returns (uint64) {
return (uint64(chainId) << 48) | uint64(slot);
}
function decode(uint64 auctionId) internal pure returns (uint16, uint48) {
return (uint16(auctionId >> 48), uint48(auctionId));
}
}
```
## Test Vectors
| Chain ID | Slot | Auction ID (hex) | Auction ID (decimal) |
|----------|------|------------------|----------------------|
| 1 | 0 | `0x0001000000000000` | 281474976710656 |
| 1 | 1000000 | `0x00010000000f4240` | 281474977710656 |
| 11155111 | 123456789 | `0xaa3600000075bcd15` | 48038396047317269 |
## Security Considerations
1. **Not suitable for cryptographic randomness** - IDs are predictable
2. **Validate chain ID matches current chain** to prevent cross-chain replay
3. **Check slot is within reasonable bounds** (e.g., not too far in future)
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).