Documentation Index Fetch the complete documentation index at: https://mintlify.com/Polymarket/ctf-exchange/llms.txt
Use this file to discover all available pages before exploring further.
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:
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
POLY_PROXY
POLY_GNOSIS_SAFE
POLY_1271
EOA (Externally Owned Account) Value: 0Description: Standard ECDSA EIP-712 signatures signed by regular Ethereum accounts.Validation Rules
Signature Recovery
The signature is validated using standard ECDSA signature recovery: function verifyECDSASignature (
address signer ,
bytes32 structHash ,
bytes memory signature
) internal pure returns ( bool ) {
return ECDSA. recover (structHash, signature) == signer;
}
Address Verification
The signer and maker addresses must be identical : 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.
POLY_PROXY (Polymarket Proxy Wallet) Value: 1Description: EIP-712 signatures signed by EOAs that own Polymarket Proxy wallets.How It Works Polymarket Proxy wallets allow users to interact with the exchange through a proxy contract owned by their EOA.
EOA Signs Order
The EOA (externally owned account) signs the order using their private key.
Proxy Ownership Verification
The exchange verifies that the EOA owns the proxy wallet: function verifyPolyProxySignature (
address signer ,
address proxyWallet ,
bytes32 structHash ,
bytes memory signature
) internal view returns ( bool ) {
return verifyECDSASignature (signer, structHash, signature)
&& getPolyProxyWalletAddress (signer) == proxyWallet;
}
Assets Transfer from Proxy
When the order is matched, assets are transferred from the proxy wallet address, not the EOA.
Order Field Setup Order memory order = Order ({
// ... other fields
maker : 0xABCD ..., // Proxy wallet address
signer : 0x1234 ..., // EOA that owns the proxy
signatureType : SignatureType.POLY_PROXY,
// ... other fields
});
The signer must be the EOA that owns the proxy wallet specified in maker. The exchange validates this relationship on-chain.
Benefits
Gas Optimization : Proxy contracts can implement gas-efficient patterns
Flexibility : Additional logic can be implemented in the proxy
Security : Separation between signing key and asset holder
POLY_GNOSIS_SAFE (Polymarket Gnosis Safe) Value: 2Description: EIP-712 signatures signed by EOAs that own Polymarket Gnosis Safe wallets.How It Works Similar to POLY_PROXY, but specifically for Gnosis Safe multi-signature wallets.
Safe Owner Signs
One of the safe owners (EOA) signs the order with their private key.
Safe Ownership Verification
The exchange verifies that the EOA is an owner of the Gnosis Safe: function verifyPolySafeSignature (
address signer ,
address safeAddress ,
bytes32 hash ,
bytes memory signature
) internal view returns ( bool ) {
return verifyECDSASignature (signer, hash, signature)
&& getSafeAddress (signer) == safeAddress;
}
Assets Transfer from Safe
When matched, assets are transferred from the Gnosis Safe contract.
Order Field Setup Order memory order = Order ({
// ... other fields
maker : 0 xSAFE..., // Gnosis Safe address
signer : 0x1234 ..., // EOA that owns the safe
signatureType : SignatureType.POLY_GNOSIS_SAFE,
// ... other fields
});
Use Cases
Multi-Sig Institutional accounts with multiple signers
Treasury DAO or protocol treasuries
Security Enhanced security through multi-party approval
Shared Accounts Team or organizational trading accounts
While Gnosis Safe supports multiple owners, only one owner’s signature is required for order signing in this implementation.
POLY_1271 (EIP-1271 Smart Contract Signature) Value: 3Description: EIP-1271 signatures for smart contract wallets and vaults.How It Works EIP-1271 allows smart contracts to validate signatures according to their own custom logic.
Contract Signature
The smart contract implements the EIP-1271 isValidSignature function: interface IERC1271 {
function isValidSignature (
bytes32 hash ,
bytes memory signature
) external view returns ( bytes4 magicValue );
}
Exchange Validation
The exchange calls the contract’s validation function: function verifyPoly1271Signature (
address signer ,
address maker ,
bytes32 hash ,
bytes memory signature
) internal view returns ( bool ) {
return (signer == maker)
&& maker.code.length > 0
&& SignatureCheckerLib. isValidSignatureNow (maker, hash, signature);
}
Custom Logic
The smart contract can implement any validation logic (multi-sig, time-locks, custom rules, etc.).
Order Field Setup Order memory order = Order ({
// ... other fields
maker : 0 xCONTRACT..., // Smart contract address
signer : 0 xCONTRACT..., // Same as maker
signatureType : SignatureType.POLY_1271,
// ... other fields
});
For POLY_1271, signer and maker must be the same address and must be a deployed smart contract.
Use Cases
Smart Wallets Account abstraction wallets (e.g., Argent, Safe)
Vaults DeFi protocol vaults and automated strategies
DAOs Decentralized autonomous organizations
Custom Logic Any contract with custom signature validation rules
Implementation Example Example Smart Contract Wallet
contract SmartWallet is IERC1271 {
address public owner;
function isValidSignature (
bytes32 hash ,
bytes memory signature
) external view override returns ( bytes4 ) {
// Custom validation logic
if (ECDSA. recover (hash, signature) == owner) {
return 0x1626ba7e ; // EIP-1271 magic value
}
return 0xffffffff ; // Invalid
}
}
Signature Validation Flow
The exchange validates signatures through a unified interface:
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
Feature EOA POLY_PROXY POLY_GNOSIS_SAFE POLY_1271 Signer = Maker ✅ Required ❌ Different ❌ Different ✅ Required Must be Contract ❌ No ❌ No ❌ No ✅ Yes Ownership Check ❌ No ✅ Proxy ✅ Safe ❌ No Signature Type ECDSA ECDSA ECDSA EIP-1271 Complexity Low Medium Medium High Gas Cost Lowest Medium Medium Variable
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
Individual Users
Use EOA for simplicity and lowest gas costs. Suitable for most retail traders.
Advanced Users
Use POLY_PROXY if you need gas optimization or additional wallet features.
Teams & Organizations
Use POLY_GNOSIS_SAFE for multi-signature security and shared account management.
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