Mechanisms

mechanisms/evm/exact/facilitator

github.com/x402-foundation/x402/go/v2/mechanisms/evm/exact/facilitator

import "github.com/x402-foundation/x402/go/v2/mechanisms/evm/exact/facilitator"

Constants

Facilitator error constants for the exact EVM scheme

Source: mechanisms/evm/exact/facilitator/errors.go:8

const (
	// EIP-3009 Verify errors
	ErrInvalidScheme               = "invalid_exact_evm_scheme"
	ErrNetworkMismatch             = "invalid_exact_evm_network_mismatch"
	ErrInvalidPayload              = "invalid_exact_evm_payload"
	ErrMissingSignature            = "invalid_exact_evm_payload_missing_signature"
	ErrFailedToGetNetworkConfig    = "invalid_exact_evm_failed_to_get_network_config"
	ErrMissingEip712Domain         = "invalid_exact_evm_missing_eip712_domain"
	ErrRecipientMismatch           = "invalid_exact_evm_recipient_mismatch"
	ErrInvalidAuthorizationValue   = "invalid_exact_evm_authorization_value"
	ErrInvalidRequiredAmount       = "invalid_exact_evm_required_amount"
	ErrAuthorizationValueMismatch  = "invalid_exact_evm_payload_authorization_value_mismatch"
	ErrFailedToCheckNonce          = "invalid_exact_evm_failed_to_check_nonce"
	ErrNonceAlreadyUsed            = "invalid_exact_evm_nonce_already_used"
	ErrFailedToGetBalance          = "invalid_exact_evm_failed_to_get_balance"
	ErrInsufficientBalance         = "invalid_exact_evm_insufficient_balance"
	ErrInvalidSignatureFormat      = "invalid_exact_evm_signature_format"
	ErrFailedToVerifySignature     = "invalid_exact_evm_failed_to_verify_signature"
	ErrInvalidSignature            = "invalid_exact_evm_signature"
	ErrValidBeforeExpired          = "invalid_exact_evm_payload_authorization_valid_before"
	ErrValidAfterInFuture          = "invalid_exact_evm_payload_authorization_valid_after"
	ErrEip3009TokenNameMismatch    = "invalid_exact_evm_token_name_mismatch"
	ErrEip3009TokenVersionMismatch = "invalid_exact_evm_token_version_mismatch"
	ErrEip3009NotSupported         = "invalid_exact_evm_eip3009_not_supported"
	ErrEip3009SimulationFailed     = "invalid_exact_evm_transaction_simulation_failed"

	// EIP-3009 Settle errors
	ErrVerificationFailed      = "invalid_exact_evm_verification_failed"
	ErrFailedToParseSignature  = "invalid_exact_evm_failed_to_parse_signature"
	ErrFailedToCheckDeployment = "invalid_exact_evm_failed_to_check_deployment"
	ErrFailedToExecuteTransfer = "invalid_exact_evm_failed_to_execute_transfer"
	ErrFailedToGetReceipt      = "invalid_exact_evm_failed_to_get_receipt"
	ErrTransactionFailed       = "invalid_exact_evm_transaction_failed"
	ErrTransferEventMismatch   = "invalid_exact_evm_transfer_event_mismatch"

	// Smart wallet errors (shared by EIP-3009 and Permit2)
	ErrUndeployedSmartWallet       = "invalid_exact_evm_payload_undeployed_smart_wallet"
	ErrSmartWalletDeploymentFailed = "smart_wallet_deployment_failed"
	ErrFactoryNotAllowed           = "eip6492_factory_not_allowed"
	ErrUnsupportedPayloadType      = "unsupported_payload_type"

	// Permit2 verify errors - canonical values live in evm.ErrPermit2*
	ErrPermit2InvalidSpender    = evm.ErrPermit2InvalidSpender
	ErrPermit2RecipientMismatch = evm.ErrPermit2RecipientMismatch
	ErrPermit2DeadlineExpired   = evm.ErrPermit2DeadlineExpired
	ErrPermit2NotYetValid       = evm.ErrPermit2NotYetValid
	ErrPermit2AmountMismatch    = evm.ErrPermit2AmountMismatch
	ErrPermit2TokenMismatch     = evm.ErrPermit2TokenMismatch
	ErrPermit2InvalidSignature  = evm.ErrPermit2InvalidSignature
	ErrPermit2AllowanceRequired = evm.ErrPermit2AllowanceRequired

	// Permit2 settle errors (from contract reverts)
	ErrPermit2InvalidAmount      = evm.ErrPermit2InvalidAmount
	ErrPermit2InvalidDestination = evm.ErrPermit2InvalidDestination
	ErrPermit2InvalidOwner       = evm.ErrPermit2InvalidOwner
	ErrPermit2PaymentTooEarly    = evm.ErrPermit2PaymentTooEarly
	ErrPermit2InvalidNonce       = evm.ErrPermit2InvalidNonce
	ErrPermit2612AmountMismatch  = evm.ErrPermit2612AmountMismatch

	// Permit2 simulation errors
	ErrPermit2SimulationFailed    = evm.ErrPermit2SimulationFailed
	ErrPermit2InsufficientBalance = evm.ErrPermit2InsufficientBalance
	ErrPermit2ProxyNotDeployed    = evm.ErrPermit2ProxyNotDeployed
	ErrErc20ApprovalTxFailed      = "erc20_approval_tx_failed"

	// ERC-20 approval gas sponsoring errors
	ErrErc20ApprovalInsufficientEth = evm.ErrErc20ApprovalInsufficientEth
	ErrErc20ApprovalInvalidFormat   = "invalid_erc20_approval_extension_format"
	ErrErc20ApprovalFromMismatch    = "erc20_approval_from_mismatch"
	ErrErc20ApprovalAssetMismatch   = "erc20_approval_asset_mismatch"
	ErrErc20ApprovalWrongSpender    = "erc20_approval_spender_not_permit2"
	ErrErc20ApprovalTxParseFailed   = "erc20_approval_tx_parse_failed"
	ErrErc20ApprovalWrongTarget     = "erc20_approval_tx_wrong_target"
	ErrErc20ApprovalWrongSelector   = "erc20_approval_tx_wrong_selector"
	ErrErc20ApprovalWrongCalldata   = "erc20_approval_tx_wrong_spender"
	ErrErc20ApprovalSignerMismatch  = "erc20_approval_tx_signer_mismatch"
	ErrErc20ApprovalInvalidSig      = "erc20_approval_tx_invalid_signature"
	ErrErc20ApprovalBroadcastFailed = evm.ErrErc20ApprovalBroadcastFailed
)

Functions

func BuildPermit2SettleArgs(permit2Payload *evm.ExactPermit2Payload) (*Permit2SettleArgs, error)

Source: mechanisms/evm/exact/facilitator/permit2_helpers.go:33

BuildPermit2SettleArgs converts a raw ExactPermit2Payload into typed contract-call arguments, deduplicating the struct construction shared by verify simulation and settle.

func CheckPermit2Prerequisites( ctx context.Context, signer evm.FacilitatorEvmSigner, tokenAddress string, payer string, amountRequired string, ) *x402.VerifyResponse

Source: mechanisms/evm/exact/facilitator/permit2_helpers.go:223

CheckPermit2Prerequisites checks proxy deployment and payer token balance.

func ClassifyEIP3009Signature( ctx context.Context, signer evm.FacilitatorEvmSigner, authorization evm.ExactEIP3009Authorization, signature []byte, chainID *big.Int, tokenAddress string, tokenName string, tokenVersion string, ) (*EIP3009SignatureClassification, error)

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:124

ClassifyEIP3009Signature checks the signature directly when possible, while preserving smart-wallet signatures for simulation-first verification.

func DiagnoseEIP3009SimulationFailure( ctx context.Context, signer evm.FacilitatorEvmSigner, tokenAddress string, authorization evm.ExactEIP3009Authorization, requiredAmount *big.Int, tokenName string, tokenVersion string, ) string

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:281

DiagnoseEIP3009SimulationFailure resolves a failed simulation into the most specific error.

func DiagnosePermit2SimulationFailure( ctx context.Context, signer evm.FacilitatorEvmSigner, tokenAddress string, permit2Payload *evm.ExactPermit2Payload, amountRequired string, ) *x402.VerifyResponse

Source: mechanisms/evm/exact/facilitator/permit2_helpers.go:166

DiagnosePermit2SimulationFailure runs a multicall diagnostic to return the most specific error reason after a simulation failure.

func ExecuteTransferWithAuthorization( ctx context.Context, signer evm.FacilitatorEvmSigner, tokenAddress string, parsed *ParsedEIP3009Authorization, sigData *evm.ERC6492SignatureData, dataSuffix []byte, ) (string, error)

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:352

ExecuteTransferWithAuthorization executes the actual transfer onchain.

func HasEIP6492Deployment(sigData *evm.ERC6492SignatureData) bool

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:476

func NewExactEvmScheme(signer evm.FacilitatorEvmSigner, config *ExactEvmSchemeConfig) *ExactEvmScheme

Source: mechanisms/evm/exact/facilitator/scheme.go:40

NewExactEvmScheme creates a new ExactEvmScheme Args:

signer: The EVM signer for facilitator operations
config: Optional configuration (nil uses defaults)

Returns:

Configured ExactEvmScheme instance

func ParseEIP3009Authorization( authorization evm.ExactEIP3009Authorization, ) (*ParsedEIP3009Authorization, error)

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:83

ParseEIP3009Authorization parses authorization fields into contract-call arguments.

func SendDeployTransaction( ctx context.Context, signer evm.FacilitatorEvmSigner, sigData *evm.ERC6492SignatureData, ) error

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:402

SendDeployTransaction submits the ERC-6492 factory deployment transaction and waits for the receipt, returning an error if the deployment transaction reverted.

func SettlePermit2( ctx context.Context, signer evm.FacilitatorEvmSigner, payload types.PaymentPayload, requirements types.PaymentRequirements, permit2Payload *evm.ExactPermit2Payload, facilCtx *x402.FacilitatorContext, config *Permit2FacilitatorConfig, ) (*x402.SettleResponse, error)

Source: mechanisms/evm/exact/facilitator/permit2.go:212

SettlePermit2 settles a Permit2 payment by calling x402ExactPermit2Proxy.settle().

func SimulateEIP3009Transfer( ctx context.Context, signer evm.FacilitatorEvmSigner, tokenAddress string, parsed *ParsedEIP3009Authorization, sigData *evm.ERC6492SignatureData, ) (bool, error)

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:199

SimulateEIP3009Transfer runs the transfer via eth_call.

func SimulatePermit2Settle( ctx context.Context, signer evm.FacilitatorEvmSigner, permit2Payload *evm.ExactPermit2Payload, ) (bool, error)

Source: mechanisms/evm/exact/facilitator/permit2_helpers.go:73

SimulatePermit2Settle runs settle() via eth_call (ReadContract). Returns true if the simulation succeeded.

func SimulatePermit2SettleWithPermit( ctx context.Context, signer evm.FacilitatorEvmSigner, permit2Payload *evm.ExactPermit2Payload, eip2612Signature, eip2612Amount, eip2612DeadlineStr string, ) (bool, error)

Source: mechanisms/evm/exact/facilitator/permit2_helpers.go:105

SimulatePermit2SettleWithPermit runs settleWithPermit() via eth_call. The contract atomically calls token.permit() then PERMIT2.permitTransferFrom(), so simulation covers allowance + balance + nonces.

func ValidateErc20ApprovalForPayment(info *erc20approvalgassponsor.Info, payer, tokenAddress string) (reason, message string)

Source: mechanisms/evm/exact/facilitator/erc20_approval.go:22

ValidateErc20ApprovalForPayment validates the ERC-20 approval extension data. Returns ("", "") if valid, or (reason, message) on failure where reason is the error constant and message is a human-readable contextual description.

func VerifyPermit2( ctx context.Context, signer evm.FacilitatorEvmSigner, payload types.PaymentPayload, requirements types.PaymentRequirements, permit2Payload *evm.ExactPermit2Payload, facilCtx *x402.FacilitatorContext, opts *VerifyPermit2Options, ) (*x402.VerifyResponse, error)

Source: mechanisms/evm/exact/facilitator/permit2.go:32

VerifyPermit2 verifies a Permit2 payment payload.

Types

type EIP3009SignatureClassification

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:27

EIP3009SignatureClassification captures how the signature should be treated.

type EIP3009SignatureClassification struct {
	Valid         bool
	IsSmartWallet bool
	IsUndeployed  bool
	SigData       *evm.ERC6492SignatureData
}
Fields
  • Valid bool
  • IsSmartWallet bool
  • IsUndeployed bool
  • SigData *evm.ERC6492SignatureData

type ExactEvmScheme

Source: mechanisms/evm/exact/facilitator/scheme.go:26

ExactEvmScheme implements the SchemeNetworkFacilitator interface for EVM exact payments (V2)

type ExactEvmScheme struct {
	// contains filtered or unexported fields
}

func CaipFamily() string

Source: mechanisms/evm/exact/facilitator/scheme.go:57

CaipFamily returns the CAIP family pattern this facilitator supports

func GetExtra(_ x402.Network) map[string]interface{}

Source: mechanisms/evm/exact/facilitator/scheme.go:63

GetExtra returns mechanism-specific extra data for the supported kinds endpoint. For EVM, no extra data is needed.

func GetSigners(_ x402.Network) []string

Source: mechanisms/evm/exact/facilitator/scheme.go:69

GetSigners returns signer addresses used by this facilitator. Returns all addresses this facilitator can use for signing/settling transactions.

func Scheme) Scheme() string

Source: mechanisms/evm/exact/facilitator/scheme.go:52

Scheme returns the scheme identifier

func Settle( ctx context.Context, payload types.PaymentPayload, requirements types.PaymentRequirements, fctx *x402.FacilitatorContext, ) (*x402.SettleResponse, error)

Source: mechanisms/evm/exact/facilitator/scheme.go:96

Settle settles a V2 payment on-chain. Routes to EIP-3009 or Permit2 settlement based on payload type.

func Verify( ctx context.Context, payload types.PaymentPayload, requirements types.PaymentRequirements, fctx *x402.FacilitatorContext, ) (*x402.VerifyResponse, error)

Source: mechanisms/evm/exact/facilitator/scheme.go:75

Verify verifies a V2 payment payload against requirements. Routes to EIP-3009 or Permit2 verification based on payload type.

type ExactEvmSchemeConfig

Source: mechanisms/evm/exact/facilitator/scheme.go:13

ExactEvmSchemeConfig holds configuration for the ExactEvmScheme facilitator

type ExactEvmSchemeConfig struct {
	// EIP6492AllowedFactories is the allowlist of factory contract addresses (hex strings,
	// case-insensitive) that the facilitator will call when deploying an undeployed smart wallet
	// via ERC-6492. A non-empty list enables ERC-4337 smart wallet deployment. An empty list
	// (the default) denies all factory deployment calls. Facilitators must explicitly list every
	// factory they trust to prevent arbitrary transaction injection via attacker-controlled
	// ERC-6492 signature wrappers.
	EIP6492AllowedFactories []string
	// SimulateInSettle reruns transfer simulation during settle. Verify always simulates.
	SimulateInSettle bool
}
Fields
  • EIP6492AllowedFactories []string

    EIP6492AllowedFactories is the allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator will call when deploying an undeployed smart wallet via ERC-6492. A non-empty list enables ERC-4337 smart wallet deployment. An empty list (the default) denies all factory deployment calls. Facilitators must explicitly list every factory they trust to prevent arbitrary transaction injection via attacker-controlled ERC-6492 signature wrappers.

  • SimulateInSettle bool

    SimulateInSettle reruns transfer simulation during settle. Verify always simulates.

type ParsedEIP3009Authorization

Source: mechanisms/evm/exact/facilitator/eip3009_helpers.go:17

ParsedEIP3009Authorization contains the parsed transfer arguments used by verify and settle.

type ParsedEIP3009Authorization struct {
	From        common.Address
	To          common.Address
	Value       *big.Int
	ValidAfter  *big.Int
	ValidBefore *big.Int
	Nonce       [32]byte
}
Fields
  • From common.Address
  • To common.Address
  • Value *big.Int
  • ValidAfter *big.Int
  • ValidBefore *big.Int
  • Nonce [32]byte

type Permit2FacilitatorConfig

Source: mechanisms/evm/exact/facilitator/permit2.go:205

Permit2FacilitatorConfig holds optional settlement-time configuration.

type Permit2FacilitatorConfig struct {
	// SimulateInSettle re-runs simulation during settle
	// When false (default), the settle path skips simulation since verify already ran it
	SimulateInSettle bool
}
Fields
  • SimulateInSettle bool

    SimulateInSettle re-runs simulation during settle When false (default), the settle path skips simulation since verify already ran it

type Permit2SettleArgs

Source: mechanisms/evm/exact/facilitator/permit2_helpers.go:14

Permit2SettleArgs holds the parsed and typed arguments for settle() / settleWithPermit().

type Permit2SettleArgs struct {
	Permit struct {
		Permitted struct {
			Token  common.Address
			Amount *big.Int
		}
		Nonce    *big.Int
		Deadline *big.Int
	}
	Owner   common.Address
	Witness struct {
		To         common.Address
		ValidAfter *big.Int
	}
	Signature []byte
}
Fields
  • Permit struct { Permitted struct { Token common.Address Amount *big.Int } Nonce *big.Int Deadline *big.Int }
  • Owner common.Address
  • Witness struct { To common.Address ValidAfter *big.Int }
  • Signature []byte

type VerifyPermit2Options

Source: mechanisms/evm/exact/facilitator/permit2.go:19

VerifyPermit2Options controls optional behaviour for VerifyPermit2.

type VerifyPermit2Options struct {
	// Simulate enables onchain simulation. Defaults to true when zero-value.
	Simulate *bool
}
Fields
  • Simulate *bool

    Simulate enables onchain simulation. Defaults to true when zero-value.