> ## 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 for smart contract wallets

# 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

```bash theme={null}
npm install @tevm/primitives
```

## Basic Usage

### Verify Contract Signature

```typescript theme={null}
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

```typescript theme={null}
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:**

```typescript theme={null}
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:**

```typescript theme={null}
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

```typescript theme={null}
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:

1. Calls `eth_getCode` to check if address has contract code
2. If no code (`0x`): Uses EOA verification (ecrecover)
3. If has code: Uses EIP-1271 contract verification

### Contract Interface

EIP-1271 contracts must implement:

```solidity theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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:

```solidity theme={null}
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
  }
}
```

## Related

* [EIP-1271 Specification](https://eips.ethereum.org/EIPS/eip-1271)
* [SignedData](../signed-data) - EIP-191 personal message signing
* [Signature](../signature) - ECDSA signature handling
* [TypedData](../typed-data) - EIP-712 structured data

## See Also

* [Address](../address) - Ethereum address handling
* [Abi](../abi) - ABI encoding for contract calls
