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.
ContractSignature
EIP-1271 contract signature verification primitive. Enables verification of signatures from smart contract wallets using the isValidSignature standard interface.
Overview
EIP-1271 allows smart contracts to validate signatures, enabling:
- Smart contract wallets (Gnosis Safe, Argent, etc.)
- Multi-signature schemes
- Custom signature validation logic
- Account abstraction
Installation
npm install @tevm/primitives
Basic Usage
Verify Contract Signature
import * as ContractSignature from '@tevm/primitives/ContractSignature';
// Check if a contract signature is valid
const isValid = await ContractSignature.isValidSignature(
provider,
contractAddress,
messageHash,
signature
);
Unified EOA + Contract Verification
import * as ContractSignature from '@tevm/primitives/ContractSignature';
import { hash as keccak256 } from '@tevm/crypto/keccak256';
import { recoverPublicKey } from '@tevm/crypto/Secp256k1';
import { fromPublicKey } from '@tevm/primitives/Address';
// Create unified verifier
const verifySignature = ContractSignature.VerifySignature({
keccak256,
recoverPublicKey,
addressFromPublicKey: fromPublicKey
});
// Automatically detects EOA vs contract and uses correct method
const isValid = await verifySignature(
provider,
signerAddress, // Can be EOA or contract
messageHash,
signature
);
API Reference
Functions
isValidSignature(provider, contractAddress, hash, signature)
Verify signature using EIP-1271 contract method.
Parameters:
provider: JSON-RPC provider with request method
contractAddress: Contract address (string or Uint8Array)
hash: Message hash (32 bytes)
signature: Signature bytes
Returns: Promise<boolean> - True if signature is valid
Example:
const isValid = await ContractSignature.isValidSignature(
provider,
'0x742d35cc6634c0532925a3b844bc9e7595f251e3',
messageHash,
signatureBytes
);
VerifySignature({ keccak256, recoverPublicKey, addressFromPublicKey })
Factory function that creates a unified signature verifier for both EOA and contract accounts.
Parameters:
keccak256: Keccak256 hash function
recoverPublicKey: secp256k1 public key recovery function
addressFromPublicKey: Address derivation function
Returns: Async function that verifies signatures
Example:
const verifySignature = ContractSignature.VerifySignature({
keccak256,
recoverPublicKey,
addressFromPublicKey: fromPublicKey
});
// Works for both EOA and contracts
const isValidEOA = await verifySignature(
provider,
eoaAddress,
messageHash,
signature
);
const isValidContract = await verifySignature(
provider,
contractAddress,
messageHash,
signature
);
Constants
EIP1271_MAGIC_VALUE = "0x1626ba7e";
IS_VALID_SIGNATURE_SELECTOR = "0x1626ba7e";
The magic value 0x1626ba7e is bytes4(keccak256("isValidSignature(bytes32,bytes)")).
How It Works
Detection Logic
VerifySignature automatically detects the account type:
- Calls
eth_getCode to check if address has contract code
- If no code (
0x): Uses EOA verification (ecrecover)
- If has code: Uses EIP-1271 contract verification
Contract Interface
EIP-1271 contracts must implement:
interface IERC1271 {
function isValidSignature(
bytes32 _hash,
bytes memory _signature
) external view returns (bytes4 magicValue);
}
Valid signatures return 0x1626ba7e, invalid signatures return anything else.
Usage Examples
With Gnosis Safe
import * as ContractSignature from '@tevm/primitives/ContractSignature';
const safeAddress = '0x...'; // Gnosis Safe contract
const messageHash = new Uint8Array(32); // Message hash
const signature = new Uint8Array(65); // Signature from Safe
const isValid = await ContractSignature.isValidSignature(
provider,
safeAddress,
messageHash,
signature
);
With Personal Message
import * as SignedData from '@tevm/primitives/SignedData';
import * as ContractSignature from '@tevm/primitives/ContractSignature';
// Hash personal message (EIP-191)
const hash = SignedData.Hash({ keccak256 });
const messageHash = hash("Hello, Ethereum!");
// Verify with automatic EOA/contract detection
const verifySignature = ContractSignature.VerifySignature({
keccak256,
recoverPublicKey,
addressFromPublicKey: fromPublicKey
});
const isValid = await verifySignature(
provider,
signerAddress,
messageHash,
signature
);
Custom Provider
const customProvider = {
request: async (method, params) => {
// Custom JSON-RPC implementation
const response = await fetch('https://eth-mainnet.g.alchemy.com/v2/...', {
method: 'POST',
body: JSON.stringify({ method, params })
});
return response.json();
}
};
const isValid = await ContractSignature.isValidSignature(
customProvider,
contractAddress,
messageHash,
signature
);
Error Handling
import {
ContractSignatureError,
ContractCallError
} from '@tevm/primitives/ContractSignature';
try {
const isValid = await ContractSignature.isValidSignature(
provider,
contractAddress,
messageHash,
signature
);
} catch (error) {
if (error instanceof ContractCallError) {
console.error("Failed to call contract:", error.message);
}
}
Smart Contract Example
Example EIP-1271 implementation:
contract MyWallet {
address public owner;
function isValidSignature(
bytes32 _hash,
bytes memory _signature
) external view returns (bytes4) {
// Recover signer from signature
address signer = ECDSA.recover(_hash, _signature);
// Check if signer is owner
if (signer == owner) {
return 0x1626ba7e; // Magic value for valid signature
}
return 0xffffffff; // Invalid signature
}
}
See Also
- Address - Ethereum address handling
- Abi - ABI encoding for contract calls