Raxol.Payments.Protocols.Permit2 (Raxol Payments v0.2.0)

Copy Markdown View Source

Permit2 PermitWitnessTransferFrom signing for Riddler's /order endpoint.

Like Xochi, Permit2 is direct-API (not HTTP 402). Riddler returns a quote with gasless.orderId; the client signs a PermitWitnessTransferFrom whose OriginPullWitness binds that orderId into the digest. The Permit2 contract verifies the signature on-chain when the solver calls permitWitnessTransferFrom.

Mirrors riddler-client/src/signing.js#signPermit2. The EIP-712 domain has no version field (Permit2 deployed without versioning); the verifyingContract is the same universal Permit2 address on every EVM chain.

Signed-object encoding

signed_object is the ABI-encoded tuple tuple(tuple(address,uint256),address,uint256,uint256) that Riddler's /order endpoint consumes. Because every field is static, the encoding is just the concatenation of left-padded 32-byte values for token, amount, spender, nonce, and deadline.

The Node CLI calls abiCoder.encode(['tuple(...)'], [[...]]) which wraps the result in a 32-byte offset (always 0x20) and then strips it via a heuristic. We produce the stripped form directly: the output bytes are identical to the CLI's stripped output.

Summary

Functions

Sign a Permit2 PermitWitnessTransferFrom from a Riddler /quote response.

Return the EIP-712 types map this module signs against.

Return the universal Permit2 contract address.

Functions

sign_quote(quote, chain_id, wallet)

@spec sign_quote(map(), pos_integer(), module()) ::
  {:ok,
   %{
     signature: String.t(),
     signed_object: String.t(),
     digest: String.t(),
     domain: map(),
     message: map()
   }}
  | {:error, term()}

Sign a Permit2 PermitWitnessTransferFrom from a Riddler /quote response.

quote shape mirrors signing.js#signPermit2:

%{
  "request" => %{"inputAmount" => "1000000", "inputToken" => "0x..."},
  "quoteExpires" => 1_900_000_000,
  "gasless" => %{
    "to" => "0x<solver>",
    "nonce" => "0x...",
    "orderId" => "0x<32 bytes>"
  }
}

Atoms keys are also accepted. Returns {:ok, %{signature: hex, signed_object: hex, digest: hex, domain: map, message: map}}.

types()

@spec types() :: map()

Return the EIP-712 types map this module signs against.

verifying_contract()

@spec verifying_contract() :: String.t()

Return the universal Permit2 contract address.