Built-in X402.Scheme for exact payments on EVM (eip155:*) networks.
The exact-EVM scheme specification defines several asset transfer
methods, selected by the requirements' extra.assetTransferMethod:
extra.assetTransferMethod | Transfer method | Scheme payload |
|---|---|---|
absent or "eip3009" | EIP-3009 | %{"signature", "authorization"} |
"permit2" | Permit2 | %{"signature", "permit2Authorization"} |
Any other value is unsupported (transfer_method/1). Both methods are
implemented for both roles:
- Client —
sign/3signs an EIP-3009TransferWithAuthorizationthroughX402.EIP3009for the default method, or a Permit2PermitWitnessTransferFromthroughX402.Permit2.sign_exact/2when the requirements select"permit2"(spender: thex402ExactPermit2Proxy, witness:payTo, permitted amount: the exactamount). An entry is signable when the selected method's EIP-712 domain can be derived from the requirements —extra.name/extra.versionfor EIP-3009, aneip155:*network for Permit2. - Server —
precheck/3runs the local pre-checks before the facilitator round-trip on whichever authorization object the payload carries: for EIP-3009,tomust equalpayTo,valuemust equal the advertisedamount, and thevalidAfter/validBeforewindow must cover now plus a settlement buffer (X402.Scheme.EVM.authorization_precheck/3); for Permit2,witness.tomust equalpayTo,permitted.amountmust equalamount,permitted.tokenmust equalasset,spendermust be thex402ExactPermit2Proxy, and thewitness.validAfter/deadlinewindow must cover now plus the buffer (X402.Scheme.EVM.permit2_precheck/3). Payloads carrying neither map are skipped.
Envelope validation of the PAYMENT-SIGNATURE payload is handled by
X402.PaymentSignature; this scheme adds no extra structural checks
(X402.Scheme.validate_payload/3 returns :ok).
Summary
Types
An asset transfer method of the exact-EVM scheme.
Functions
Returns ["eip155:*"] — every EVM network.
Runs the local pre-checks with exact-amount equality enforced.
Returns "exact".
Signs the scheme payload for the selected transfer method.
Whether the selected transfer method's EIP-712 domain can be derived from the requirements.
Resolves the asset transfer method selected by the requirements.
Always :ok — envelope validation covers the exact payload shape.
Types
Functions
@spec networks() :: [String.t()]
Returns ["eip155:*"] — every EVM network.
Examples
iex> X402.Scheme.ExactEVM.networks()
["eip155:*"]
@spec precheck(map(), map(), keyword()) :: :ok | {:error, {:precheck_failed, X402.Scheme.EVM.precheck_failure()}}
Runs the local pre-checks with exact-amount equality enforced.
Dispatches on the payload shape: payload.authorization runs
X402.Scheme.EVM.authorization_precheck/3, payload.permit2Authorization
runs X402.Scheme.EVM.permit2_precheck/3 against the
x402ExactPermit2Proxy spender. Both run when both maps are present;
neither present passes.
@spec scheme() :: String.t()
Returns "exact".
Examples
iex> X402.Scheme.ExactEVM.scheme()
"exact"
@spec sign(map(), X402.Signer.t(), keyword()) :: {:ok, map()} | {:error, term()}
Signs the scheme payload for the selected transfer method.
EIP-3009 requirements sign via X402.EIP3009.sign/3, honoring the
client's :valid_after_buffer option; Permit2 requirements sign via
X402.Permit2.sign_exact/2 (valid immediately, expiring after
maxTimeoutSeconds). Other options are ignored.
Whether the selected transfer method's EIP-712 domain can be derived from the requirements.
Examples
iex> X402.Scheme.ExactEVM.signable?(%{
...> "network" => "eip155:84532",
...> "asset" => "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
...> "extra" => %{"name" => "USDC", "version" => "2"}
...> })
true
iex> X402.Scheme.ExactEVM.signable?(%{
...> "network" => "eip155:84532",
...> "asset" => "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
...> "extra" => %{"assetTransferMethod" => "permit2"}
...> })
true
iex> X402.Scheme.ExactEVM.signable?(%{"extra" => %{}})
false
iex> X402.Scheme.ExactEVM.signable?(%{
...> "network" => "eip155:84532",
...> "extra" => %{"assetTransferMethod" => "erc7710"}
...> })
false
@spec transfer_method(map()) :: {:ok, transfer_method()} | {:error, {:unsupported_transfer_method, term()}}
Resolves the asset transfer method selected by the requirements.
Reads extra.assetTransferMethod: absent or "eip3009" selects
:eip3009, "permit2" selects :permit2, anything else is
{:error, {:unsupported_transfer_method, value}}.
Examples
iex> X402.Scheme.ExactEVM.transfer_method(%{"extra" => %{"name" => "USDC"}})
{:ok, :eip3009}
iex> X402.Scheme.ExactEVM.transfer_method(%{"extra" => %{"assetTransferMethod" => "permit2"}})
{:ok, :permit2}
iex> X402.Scheme.ExactEVM.transfer_method(%{"extra" => %{"assetTransferMethod" => "erc7710"}})
{:error, {:unsupported_transfer_method, "erc7710"}}
iex> X402.Scheme.ExactEVM.transfer_method(%{})
{:ok, :eip3009}
Always :ok — envelope validation covers the exact payload shape.
Examples
iex> X402.Scheme.ExactEVM.validate_payload(%{}, %{}, [])
:ok