Skip to main content
The CTFExchange supports multiple signature types to accommodate different wallet architectures and user setups. Each signature type has specific validation rules to ensure security and compatibility.

SignatureType Enum

The exchange defines four signature types:
OrderStructs.sol
enum SignatureType {
    // 0: ECDSA EIP712 signatures signed by EOAs
    EOA,
    // 1: EIP712 signatures signed by EOAs that own Polymarket Proxy wallets
    POLY_PROXY,
    // 2: EIP712 signatures signed by EOAs that own Polymarket Gnosis safes
    POLY_GNOSIS_SAFE,
    // 3: EIP1271 signatures signed by smart contracts. To be used by smart contract wallets or vaults
    POLY_1271
}

Signature Type Details

EOA (Externally Owned Account)

Value: 0Description: Standard ECDSA EIP-712 signatures signed by regular Ethereum accounts.

Validation Rules

1

Signature Recovery

The signature is validated using standard ECDSA signature recovery:
Signatures.sol
function verifyECDSASignature(
    address signer,
    bytes32 structHash,
    bytes memory signature
) internal pure returns (bool) {
    return ECDSA.recover(structHash, signature) == signer;
}
2

Address Verification

The signer and maker addresses must be identical:
Signatures.sol
function verifyEOASignature(
    address signer,
    address maker,
    bytes32 structHash,
    bytes memory signature
) internal pure returns (bool) {
    return (signer == maker) && verifyECDSASignature(signer, structHash, signature);
}

Use Cases

MetaMask

Direct signing with MetaMask or other browser wallets

Hardware Wallets

Ledger, Trezor, and other hardware wallet users

Private Keys

Direct private key signing in backend services

Mobile Wallets

Rainbow, Trust Wallet, and other mobile wallet apps
This is the most common signature type and the simplest to implement for individual users.

Signature Validation Flow

The exchange validates signatures through a unified interface:
Signatures.sol
function isValidSignature(
    address signer,
    address associated,
    bytes32 structHash,
    bytes memory signature,
    SignatureType signatureType
) internal view returns (bool) {
    if (signatureType == SignatureType.EOA) {
        // EOA
        return verifyEOASignature(signer, associated, structHash, signature);
    } else if (signatureType == SignatureType.POLY_GNOSIS_SAFE) {
        // POLY_GNOSIS_SAFE
        return verifyPolySafeSignature(signer, associated, structHash, signature);
    } else if (signatureType == SignatureType.POLY_1271) {
        // POLY_1271
        return verifyPoly1271Signature(signer, associated, structHash, signature);
    } else {
        // POLY_PROXY
        return verifyPolyProxySignature(signer, associated, structHash, signature);
    }
}

Signature Type Comparison

FeatureEOAPOLY_PROXYPOLY_GNOSIS_SAFEPOLY_1271
Signer = Maker✅ Required❌ Different❌ Different✅ Required
Must be Contract❌ No❌ No❌ No✅ Yes
Ownership Check❌ No✅ Proxy✅ Safe❌ No
Signature TypeECDSAECDSAECDSAEIP-1271
ComplexityLowMediumMediumHigh
Gas CostLowestMediumMediumVariable

Security Considerations

  • Private key must be kept secure
  • No recovery mechanism if key is lost
  • Single point of failure
  • Simplest but least flexible
  • Ownership relationship is validated on-chain
  • Proxy contract code must be trusted
  • Additional attack surface through proxy contract
  • More flexible than raw EOA
  • Multi-signature provides redundancy
  • Owner set can be updated
  • More complex validation logic
  • Higher gas costs but better security
  • Security depends entirely on contract implementation
  • Must carefully audit validation logic
  • Potential for complex vulnerabilities
  • Maximum flexibility but requires expertise

Choosing the Right Signature Type

1

Individual Users

Use EOA for simplicity and lowest gas costs. Suitable for most retail traders.
2

Advanced Users

Use POLY_PROXY if you need gas optimization or additional wallet features.
3

Teams & Organizations

Use POLY_GNOSIS_SAFE for multi-signature security and shared account management.
4

Protocols & Smart Contracts

Use POLY_1271 for vaults, DAOs, or any custom signature validation logic.

Order Structure

Learn about the complete Order struct

EIP-712

Read the EIP-712 specification

EIP-1271

Read the EIP-1271 specification

Build docs developers (and LLMs) love