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.
Try it Live
Run Authorization examples in the interactive playground
Utilities
Helper functions for authorization formatting and comparison.
Format authorization to human-readable string.
Authorization.format.call(
auth: Authorization.Item | Authorization.Unsigned
): string
Parameters:
auth: Authorization (signed or unsigned) to format
Returns: Human-readable string representation
Usage
Signed Authorization:
import { Authorization } from 'tevm';
const auth: Authorization.Item = {
chainId: 1n,
address: contractAddress,
nonce: 42n,
yParity: 0,
r: 0x123456789abcdef0n,
s: 0xfedcba9876543210n
};
console.log(Authorization.format.call(auth));
// "Authorization(chain=1, to=0x742d...bEb2, nonce=42, r=0x123456789abcdef0, s=0xfedcba9876543210, v=0)"
Unsigned Authorization:
import { Authorization } from 'tevm';
const unsigned: Authorization.Unsigned = {
chainId: 1n,
address: contractAddress,
nonce: 0n
};
console.log(Authorization.format.call(unsigned));
// "Authorization(chain=1, to=0x742d...bEb2, nonce=0)"
Signed format:
Authorization(chain={chainId}, to={address}, nonce={nonce}, r={r}, s={s}, v={yParity})
Unsigned format:
Authorization(chain={chainId}, to={address}, nonce={nonce})
Address formatting: Shortened to 0x{first4}...{last4}
Examples
import { Authorization, Address } from 'tevm';
const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2');
// Unsigned
const unsigned = { chainId: 1n, address: addr, nonce: 0n };
Authorization.format.call(unsigned);
// "Authorization(chain=1, to=0x742d...bEb2, nonce=0)"
// Signed
const auth = {
chainId: 1n,
address: addr,
nonce: 42n,
yParity: 0,
r: 0x123n,
s: 0x456n
};
Authorization.format.call(auth);
// "Authorization(chain=1, to=0x742d...bEb2, nonce=42, r=0x123, s=0x456, v=0)"
Use Cases
Logging:
console.log(`Processing: ${Authorization.format.call(auth)}`);
Debugging:
const formatted = Authorization.format.call(auth);
console.error(`Invalid authorization: ${formatted}`);
Display:
function displayAuth(auth: Authorization.Item): void {
const formatted = Authorization.format.call(auth);
document.getElementById('auth-display').textContent = formatted;
}
equals
Check if two authorizations are equal.
Authorization.equals.call(
auth1: Authorization.Item,
auth2: Authorization.Item
): boolean
Parameters:
auth1: First authorization
auth2: Second authorization
Returns: true if all fields are equal, false otherwise
Comparison: Compares all fields:
- chainId
- address (byte-by-byte)
- nonce
- yParity
- r
- s
Usage
import { Authorization } from 'tevm';
const auth1: Authorization.Item = {
chainId: 1n,
address: contractAddress,
nonce: 0n,
yParity: 0,
r: 0x123n,
s: 0x456n
};
const auth2: Authorization.Item = {
chainId: 1n,
address: contractAddress,
nonce: 0n,
yParity: 0,
r: 0x123n,
s: 0x456n
};
const auth3: Authorization.Item = {
...auth1,
nonce: 1n // Different nonce
};
console.log(Authorization.equals.call(auth1, auth2)); // true
console.log(Authorization.equals.call(auth1, auth3)); // false
Implementation Details
Address Comparison:
Byte-by-byte comparison:
function addressEquals(a: Address, b: Address): boolean {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
Field Comparison:
function equals(auth1: Authorization.Item, auth2: Authorization.Item): boolean {
return (
auth1.chainId === auth2.chainId &&
addressEquals(auth1.address, auth2.address) &&
auth1.nonce === auth2.nonce &&
auth1.yParity === auth2.yParity &&
auth1.r === auth2.r &&
auth1.s === auth2.s
);
}
Examples
Exact match:
const auth1 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };
const auth2 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };
Authorization.equals.call(auth1, auth2); // true
Different chainId:
const auth1 = { chainId: 1n, ... };
const auth2 = { chainId: 137n, ... };
Authorization.equals.call(auth1, auth2); // false
Different address:
const auth1 = { address: addr1, ... };
const auth2 = { address: addr2, ... };
Authorization.equals.call(auth1, auth2); // false
Different signature:
const auth1 = { ..., r: 0x123n, s: 0x456n };
const auth2 = { ..., r: 0x789n, s: 0xabcn };
Authorization.equals.call(auth1, auth2); // false
Common Patterns
Deduplication
Remove duplicate authorizations:
import { Authorization } from 'tevm';
function deduplicateAuths(
authList: Authorization.Item[]
): Authorization.Item[] {
const unique: Authorization.Item[] = [];
for (const auth of authList) {
// Check if already in unique list
const isDuplicate = unique.some(u =>
Authorization.equals.call(u, auth)
);
if (!isDuplicate) {
unique.push(auth);
}
}
return unique;
}
const deduplicated = deduplicateAuths([auth1, auth2, auth1, auth3]);
// Returns [auth1, auth2, auth3]
Authorization Set
Track unique authorizations:
import { Authorization } from 'tevm';
class AuthorizationSet {
private auths: Authorization.Item[] = [];
add(auth: Authorization.Item): boolean {
if (this.has(auth)) {
return false;
}
this.auths.push(auth);
return true;
}
has(auth: Authorization.Item): boolean {
return this.auths.some(a =>
Authorization.equals.call(a, auth)
);
}
remove(auth: Authorization.Item): boolean {
const index = this.auths.findIndex(a =>
Authorization.equals.call(a, auth)
);
if (index === -1) return false;
this.auths.splice(index, 1);
return true;
}
toArray(): Authorization.Item[] {
return [...this.auths];
}
get size(): number {
return this.auths.length;
}
}
const set = new AuthorizationSet();
set.add(auth1); // true
set.add(auth1); // false (duplicate)
set.has(auth1); // true
Logging Helper
Create logging helper:
import { Authorization } from 'tevm';
class AuthLogger {
log(auth: Authorization.Item | Authorization.Unsigned): void {
const formatted = Authorization.format.call(auth);
console.log(`[AUTH] ${formatted}`);
}
error(auth: Authorization.Item | Authorization.Unsigned, error: Error): void {
const formatted = Authorization.format.call(auth);
console.error(`[AUTH ERROR] ${formatted}: ${error.message}`);
}
debug(auth: Authorization.Item | Authorization.Unsigned, message: string): void {
const formatted = Authorization.format.call(auth);
console.debug(`[AUTH DEBUG] ${formatted} - ${message}`);
}
}
const logger = new AuthLogger();
logger.log(auth);
logger.debug(auth, 'Processing authorization');
Comparison Helper
Compare and report differences:
import { Authorization } from 'tevm';
interface AuthDifference {
field: string;
value1: any;
value2: any;
}
function compareAuths(
auth1: Authorization.Item,
auth2: Authorization.Item
): AuthDifference[] {
const differences: AuthDifference[] = [];
if (auth1.chainId !== auth2.chainId) {
differences.push({
field: 'chainId',
value1: auth1.chainId,
value2: auth2.chainId
});
}
if (!addressEquals(auth1.address, auth2.address)) {
differences.push({
field: 'address',
value1: auth1.address,
value2: auth2.address
});
}
if (auth1.nonce !== auth2.nonce) {
differences.push({
field: 'nonce',
value1: auth1.nonce,
value2: auth2.nonce
});
}
if (auth1.yParity !== auth2.yParity) {
differences.push({
field: 'yParity',
value1: auth1.yParity,
value2: auth2.yParity
});
}
if (auth1.r !== auth2.r) {
differences.push({
field: 'r',
value1: auth1.r,
value2: auth2.r
});
}
if (auth1.s !== auth2.s) {
differences.push({
field: 's',
value1: auth1.s,
value2: auth2.s
});
}
return differences;
}
const diffs = compareAuths(auth1, auth2);
if (diffs.length > 0) {
console.log('Differences found:');
diffs.forEach(d => {
console.log(` ${d.field}: ${d.value1} vs ${d.value2}`);
});
}
Create display-friendly format:
import { Authorization, Address } from 'tevm';
interface DisplayAuth {
chain: string;
delegateTo: string;
nonce: string;
signature?: string;
}
function formatForDisplay(auth: Authorization.Item): DisplayAuth {
return {
chain: getChainName(auth.chainId),
delegateTo: Address.toChecksummed(auth.address),
nonce: auth.nonce.toString(),
signature: `r:${auth.r.toString(16)}, s:${auth.s.toString(16)}, v:${auth.yParity}`
};
}
function getChainName(chainId: bigint): string {
switch (chainId) {
case 1n: return 'Ethereum Mainnet';
case 137n: return 'Polygon';
case 42161n: return 'Arbitrum';
default: return `Chain ${chainId}`;
}
}
const display = formatForDisplay(auth);
console.log(`Chain: ${display.chain}`);
console.log(`Delegate to: ${display.delegateTo}`);
console.log(`Nonce: ${display.nonce}`);
console.log(`Signature: ${display.signature}`);
Format multiple authorizations:
import { Authorization } from 'tevm';
function formatAuthBatch(
authList: Authorization.Item[]
): string {
const formatted = authList.map((auth, i) =>
`${i + 1}. ${Authorization.format.call(auth)}`
);
return formatted.join('\n');
}
console.log('Authorization List:');
console.log(formatAuthBatch([auth1, auth2, auth3]));
// 1. Authorization(chain=1, to=0x742d...bEb2, nonce=0, ...)
// 2. Authorization(chain=1, to=0x1234...5678, nonce=1, ...)
// 3. Authorization(chain=1, to=0x9abc...def0, nonce=2, ...)
Find Duplicates
Find all duplicates in list:
import { Authorization } from 'tevm';
function findDuplicates(
authList: Authorization.Item[]
): Array<{ auth: Authorization.Item; indices: number[] }> {
const duplicates = new Map<string, number[]>();
authList.forEach((auth, index) => {
const key = Authorization.format.call(auth);
const indices = duplicates.get(key) || [];
indices.push(index);
duplicates.set(key, indices);
});
const result: Array<{ auth: Authorization.Item; indices: number[] }> = [];
duplicates.forEach((indices, key) => {
if (indices.length > 1) {
result.push({
auth: authList[indices[0]],
indices
});
}
});
return result;
}
const dupes = findDuplicates(authList);
dupes.forEach(d => {
console.log(`Duplicate at indices ${d.indices.join(', ')}:`);
console.log(` ${Authorization.format.call(d.auth)}`);
});
O(1) - Constant time string construction
Cost:
- Address shortening: O(40) = O(1)
- String concatenation: O(1)
- Number to hex conversion: O(log n) for bigint
equals
O(1) - Constant time comparison
Cost:
- 5 bigint comparisons: O(1) each
- 1 number comparison: O(1)
- Address comparison: O(20) = O(1)
Total: O(1)
Optimization Tips
- Cache formatted strings if formatting same auth repeatedly
- Use equals for deduplication instead of string comparison
- Batch format operations when possible
Testing
import { Authorization } from 'tevm';
const auth: Authorization.Item = {
chainId: 1n,
address: contractAddress,
nonce: 0n,
yParity: 0,
r: 0x123n,
s: 0x456n
};
const formatted = Authorization.format.call(auth);
expect(formatted).toContain('chain=1');
expect(formatted).toContain('nonce=0');
expect(formatted).toContain('r=0x123');
expect(formatted).toContain('s=0x456');
expect(formatted).toContain('v=0');
Test equals
import { Authorization } from 'tevm';
// Same authorizations
const auth1 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };
const auth2 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };
expect(Authorization.equals.call(auth1, auth2)).toBe(true);
// Different authorizations
const auth3 = { ...auth1, nonce: 1n };
expect(Authorization.equals.call(auth1, auth3)).toBe(false);
See Also