> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sesameterminal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# go-ethereum in the Polymarket signing code (P2-10 notes)

# go-ethereum in the Polymarket signing code (P2-10 notes)

Written 2026-09-30 for Phase 3, as input to ADR 0010 (the tech lead writes the ADR). Security
finding P2-10 asked for either a small EIP-712 encoder or a recorded acceptance of go-ethereum.
Phase 3 keeps go-ethereum (`v1.17.6`, `backend/go.mod`); these notes say what is imported, what
it pulls in, and what it is trusted for.

## What the code imports

Only `backend/internal/venue/polymarket/signing` imports go-ethereum for signing. The adapter
package (`venue/polymarket`) uses `common` (the `Address` type) and `common/hexutil` (hex encoding
of the order signature).

| Package | Used for | Where |
| - | - | - |
| `common` | `Address`, `Hash`, `HexToAddress`, `LeftPadBytes` | signing, adapter |
| `common/hexutil` | hex encoding of signatures and hashes; `Bytes` typed-data values | signing, adapter |
| `common/math` | `HexOrDecimal256`, the typed-data `chainId` type | signing |
| `crypto` | `ToECDSA` (key parsing), `PubkeyToAddress`, `Sign` (secp256k1 over a 32-byte digest) | signing |
| `signer/core/apitypes` | EIP-712 `encodeType`, `hashStruct` and the `0x1901` digest for ClobAuth, `Order` and the ERC-7739 `TypedDataSign` | signing |
| `accounts/abi` | **tests only**: an independent `abi.encode(bytes32, bytes32, bytes)` to check the session-key wrapper | `signing/order_test.go` |

Code written here, not taken from go-ethereum: the typed-data allowlist (`signing/typeddata.go`),
the ERC-7739 signature layout and the session-key wrapper (`signing/order.go`), and the amount
maths (`signing/amounts.go`).

## What it pulls in

`go list -deps` of the signing package with `CGO_ENABLED=0` lists 66 non-standard-library
packages. Most come from `apitypes`, which imports `core/types` (transactions, blocks), `params`,
`rlp`, `event`, `log`, `crypto/kzg4844`, and through them `gnark-crypto` (BLS12-381),
`go-eth-kzg`, `holiman/uint256` and `bits-and-blooms/bitset`. None of that is called by the signing
code; it is compiled in because `apitypes` declares transaction types beside the typed-data code.

`crypto` alone needs far less: `common`, `common/hexutil`, `common/math`, `crypto/keccak`, `rlp`,
`holiman/uint256`, `golang.org/x/sys/cpu` and the secp256k1 implementation.

**secp256k1 backend.** With `CGO_ENABLED=0`, `crypto` signs with the pure-Go
`github.com/decred/dcrd/dcrec/secp256k1/v4`. With cgo on (for example a default Linux build), it
compiles go-ethereum's `crypto/secp256k1`, a C copy of libsecp256k1. Both give the same RFC 6979
deterministic signatures, which is why the golden vectors match on Windows (cgo off) and must
match on Linux. PLAN Phase 6 builds with `CGO_ENABLED=0` everywhere (P2-10 disposition), which
keeps one backend.

## Why keeping it is acceptable

* **Checked output.** Every hash and signature the package produces is compared byte for byte
  with vectors from the official TS SDK: 2 ClobAuth, 9 orders (both exchanges, signature types 0
  and 3, BUY and SELL, GTD with non-zero metadata and builder), 26 amount cases, 10 HMAC cases.
  The SDK's own `TypedDataSign` payloads, hashed by `apitypes`, give the vectors' digests too.
* **Narrow use.** The package calls three things: `apitypes` hashing, `crypto.Sign`, and address
  helpers. It never uses go-ethereum's keystore, RPC, transaction building or account managers.
* **One signing path.** Every signature goes through `signTypedData`, which first requires the
  primary type, the full type set and the domain to be one of ClobAuth or a CLOB V2 order on the
  two pinned exchanges on chain 137 (`TestSignTypedDataRefusesOthers`, gate item 13). A bug or
  misuse elsewhere in go-ethereum cannot widen what the key signs.
* **Scanned.** `govulncheck ./internal/venue/...` reports no vulnerabilities (2026-09-30).

## Costs and what would change the decision

* Binary size and build time grow with the unused `core/types`, KZG and BLS code.
* A go-ethereum upgrade can move `apitypes` behaviour (it did change encoding rules across
  versions). The golden vectors catch a change in any hash we produce; upgrades should be
  deliberate and run `go test ./internal/venue/...`.
* Replacing `apitypes` with a small fixed encoder for the three structs (about 100 lines over
  `crypto/keccak`) would drop most of the transitive tree. `crypto` would stay for secp256k1.
  The vectors already pin every value such an encoder must produce.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.