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.
ErrorSignature
An ErrorSignature is a 4-byte identifier used for Solidity custom errors in revert data. It’s computed as the first 4 bytes of the Keccak-256 hash of the error signature, similar to function selectors.
Type Definition
type ErrorSignatureType = Uint8Array & {
readonly [brand]: "ErrorSignature";
readonly length: 4;
};
Creating Error Signatures
From Signature String
import * as ErrorSignature from '@tevm/primitives';
const insufficientBalance = ErrorSignature.fromSignature(
'InsufficientBalance(uint256,uint256)'
);
console.log(ErrorSignature.toHex(insufficientBalance));
// '0xcf479181'
From Hex String
const sig = ErrorSignature.fromHex('0xcf479181');
From Bytes
const bytes = new Uint8Array([0xcf, 0x47, 0x91, 0x81]);
const sig = ErrorSignature.from(bytes);
Operations
Convert to Hex
const hex = ErrorSignature.toHex(signature);
// '0xcf479181'
Compare Signatures
const sig1 = ErrorSignature.fromSignature('Unauthorized()');
const sig2 = ErrorSignature.fromSignature('Error(string)');
const equal = ErrorSignature.equals(sig1, sig2); // false
Standard Error Signatures
Built-in Errors
Solidity has two built-in error signatures:
// Error(string) - Used by require()
const errorString = ErrorSignature.fromSignature('Error(string)');
// 0x08c379a0
// Panic(uint256) - Used by assert()
const panic = ErrorSignature.fromSignature('Panic(uint256)');
// 0x4e487b71
Panic Codes
When using assert() or encountering specific errors, Solidity reverts with Panic(uint256) and a code:
0x00 - Generic panic
0x01 - Assert failed
0x11 - Arithmetic overflow/underflow
0x12 - Division by zero
0x21 - Invalid enum value
0x22 - Invalid storage byte array access
0x31 - Pop on empty array
0x32 - Array out of bounds
0x41 - Out of memory
0x51 - Invalid internal function call
Custom Errors
Custom errors are more gas-efficient than require() with strings:
// Define custom error
error InsufficientBalance(uint256 available, uint256 required);
// Use in contract
if (balance < amount) {
revert InsufficientBalance(balance, amount);
}
const sig = ErrorSignature.fromSignature('InsufficientBalance(uint256,uint256)');
// 0xcf479181
Common Custom Errors
Access Control
const unauthorized = ErrorSignature.fromSignature('Unauthorized()');
const onlyOwner = ErrorSignature.fromSignature('OnlyOwner()');
const invalidRole = ErrorSignature.fromSignature('InvalidRole(bytes32)');
Token Operations
const insufficientBalance = ErrorSignature.fromSignature(
'InsufficientBalance(uint256,uint256)'
);
const insufficientAllowance = ErrorSignature.fromSignature(
'InsufficientAllowance(uint256,uint256)'
);
const invalidRecipient = ErrorSignature.fromSignature('InvalidRecipient(address)');
DeFi
const slippageTooHigh = ErrorSignature.fromSignature(
'SlippageTooHigh(uint256,uint256)'
);
const deadlineExpired = ErrorSignature.fromSignature('DeadlineExpired(uint256)');
const insufficientLiquidity = ErrorSignature.fromSignature('InsufficientLiquidity()');
Revert Data Structure
When a custom error is thrown, the revert data contains:
[selector (4 bytes)][encoded parameters]
Example for InsufficientBalance(1000, 2000):
0xcf479181 // selector
0000000000000000000000000000000000000000000000000000000000003e8 // 1000
0000000000000000000000000000000000000000000000000000000000007d0 // 2000
Decoding Errors
Use error signatures to decode revert data:
const revertData = '0xcf479181...'; // from transaction
const selector = revertData.slice(0, 10); // '0xcf479181'
const errorSig = ErrorSignature.fromHex(selector);
// Identify: InsufficientBalance(uint256,uint256)
// Decode parameters from revertData.slice(10)
Error signatures must use canonical type names:
✅ Correct:
InsufficientBalance(uint256,uint256)
Unauthorized()
InvalidSwap(address,uint256,bytes)
❌ Incorrect:
InsufficientBalance(uint, uint) (should be uint256)
InsufficientBalance(uint256, uint256) (has spaces)
insufficientBalance(uint256,uint256) (wrong capitalization)
Note: Error names conventionally start with uppercase.
How Error Signatures Work
- Error Signature: Start with the canonical error signature
- Hash: Compute
keccak256(signature)
- Truncate: Take the first 4 bytes
InsufficientBalance(uint256,uint256)
↓ keccak256
0xcf4791819f1b70c0f30aefb0f54ba2bc...
↓ slice(0, 4)
0xcf479181
Gas Efficiency
Custom errors are significantly more gas-efficient than require() with strings:
// ❌ Expensive (~24k gas)
require(balance >= amount, "Insufficient balance");
// ✅ Efficient (~1k gas)
if (balance < amount) revert InsufficientBalance(balance, amount);
Handling Errors
try {
await contract.transfer(recipient, amount);
} catch (error) {
if (error.data) {
const selector = error.data.slice(0, 10);
const insufficientBalanceSig = ErrorSignature.fromSignature(
'InsufficientBalance(uint256,uint256)'
);
if (selector === ErrorSignature.toHex(insufficientBalanceSig)) {
// Handle insufficient balance error
console.log('Not enough balance');
}
}
}
API Reference
Constructors
from(value: ErrorSignatureLike): ErrorSignatureType - Create from various inputs
fromHex(hex: string): ErrorSignatureType - Create from hex string
fromSignature(signature: string): ErrorSignatureType - Compute from error signature
Operations
toHex(sig: ErrorSignatureType): string - Convert to hex string
equals(a: ErrorSignatureType, b: ErrorSignatureType): boolean - Compare signatures
See Also