package polymarket

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file order_signing.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(** EIP-712 order signing for CTF Exchange.

    This module provides the cryptographic primitives for signing orders
    compatible with Polymarket's CTF Exchange contract. Used by both CLOB and
    RFQ APIs. *)

(** {1 Salt Generation} *)

let generate_salt () =
  let n = ref Int64.zero in
  for _ = 1 to 8 do
    n := Int64.(logor (shift_left !n 8) (of_int (Random.int 256)))
  done;
  Int64.(to_string (logand !n max_int))

(** {1 EIP-712 Type Hash} *)

let order_type_hash =
  let type_string =
    "Order(uint256 salt,address maker,address signer,address taker,uint256 \
     tokenId,uint256 makerAmount,uint256 takerAmount,uint256 \
     expiration,uint256 nonce,uint256 feeRateBps,uint8 side,uint8 \
     signatureType)"
  in
  Digestif.KECCAK_256.(to_hex (digest_string type_string))

(** {1 EIP-712 Domain Separator} *)

let ctf_domain_separator =
  let domain_type_hash =
    let type_string =
      "EIP712Domain(string name,string version,uint256 chainId,address \
       verifyingContract)"
    in
    Digestif.KECCAK_256.(to_hex (digest_string type_string))
  in
  let name_hash =
    Digestif.KECCAK_256.(
      to_hex (digest_string Constants.ctf_exchange_domain_name))
  in
  let version_hash =
    Digestif.KECCAK_256.(
      to_hex (digest_string Constants.ctf_exchange_domain_version))
  in
  let chain_id_hex = Crypto.Private.encode_uint256 Constants.polygon_chain_id in
  let contract_hex = String.sub Constants.ctf_exchange_address 2 40 in
  let contract_padded = Crypto.Private.pad_hex_32 contract_hex in
  let data =
    domain_type_hash ^ name_hash ^ version_hash ^ chain_id_hex ^ contract_padded
  in
  let bytes = Hex.to_string (`Hex data) in
  Digestif.KECCAK_256.(to_hex (digest_string bytes))

(** {1 Order Signing} *)

let sign_order ~private_key ~salt ~maker ~signer ~taker ~token_id ~maker_amount
    ~taker_amount ~expiration ~nonce ~fee_rate_bps ~side ~signature_type =
  let encode_address addr =
    let hex =
      if String.length addr > 2 && String.sub addr 0 2 = "0x" then
        String.sub addr 2 (String.length addr - 2)
      else addr
    in
    Crypto.Private.pad_hex_32 hex
  in
  let encode_uint256_str s = Crypto.Private.encode_uint256 (int_of_string s) in
  let struct_data =
    order_type_hash ^ encode_uint256_str salt ^ encode_address maker
    ^ encode_address signer ^ encode_address taker
    ^ encode_uint256_str token_id
    ^ encode_uint256_str maker_amount
    ^ encode_uint256_str taker_amount
    ^ encode_uint256_str expiration
    ^ encode_uint256_str nonce
    ^ encode_uint256_str fee_rate_bps
    ^ Crypto.Private.encode_uint256 side
    ^ Crypto.Private.encode_uint256 signature_type
  in
  let struct_bytes = Hex.to_string (`Hex struct_data) in
  let struct_hash = Digestif.KECCAK_256.(to_hex (digest_string struct_bytes)) in
  let prefix = "\x19\x01" in
  let domain_bytes = Hex.to_string (`Hex ctf_domain_separator) in
  let struct_bytes = Hex.to_string (`Hex struct_hash) in
  let final_data = prefix ^ domain_bytes ^ struct_bytes in
  let final_hash = Digestif.KECCAK_256.(to_hex (digest_string final_data)) in
  let private_key_str = Crypto.private_key_to_string private_key in
  Crypto.Private.sign_hash ~private_key:private_key_str final_hash