Mechanisms

mechanisms/evm/batch-settlement/facilitator

Package facilitator emits canonical batch-settlement EVM rejection tokens.

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

Package facilitator emits canonical batch-settlement EVM rejection tokens. Every facilitator-emitted reason starts with invalid_batch_settlement_evm_, mirroring the invalid_exact_evm_* shape used by the exact EVM facilitator (see go/mechanisms/evm/exact/facilitator/errors.go). Exported symbols stay Err… (Go-idiomatic) - only the string values are part of the wire contract; the constants here describe mechanism-level failures only and intentionally carry no policy/business semantics.

Constants

Source: mechanisms/evm/batch-settlement/facilitator/errors.go:14

const (
	// Payload parsing errors
	ErrInvalidPayload        = "invalid_batch_settlement_evm_payload_type"
	ErrInvalidDepositPayload = "invalid_batch_settlement_evm_deposit_payload"
	ErrInvalidVoucherPayload = "invalid_batch_settlement_evm_voucher_payload"
	ErrInvalidClaimPayload   = "invalid_batch_settlement_evm_claim_payload"
	ErrInvalidSettlePayload  = "invalid_batch_settlement_evm_settle_payload"
	ErrInvalidRefundPayload  = "invalid_batch_settlement_evm_refund_payload"
	ErrInvalidScheme         = "invalid_batch_settlement_evm_scheme"
	ErrNetworkMismatch       = "invalid_batch_settlement_evm_network_mismatch"

	// Channel config validation errors
	ErrReceiverMismatch           = "invalid_batch_settlement_evm_receiver_mismatch"
	ErrReceiverAuthorizerMismatch = "invalid_batch_settlement_evm_receiver_authorizer_mismatch"
	ErrTokenMismatch              = "invalid_batch_settlement_evm_token_mismatch"
	ErrWithdrawDelayOutOfRange    = "invalid_batch_settlement_evm_withdraw_delay_out_of_range"
	ErrWithdrawDelayMismatch      = "invalid_batch_settlement_evm_withdraw_delay_mismatch"
	ErrChannelIdMismatch          = "invalid_batch_settlement_evm_channel_id_mismatch"

	// ERC-3009 authorization errors
	ErrValidBeforeExpired           = "invalid_batch_settlement_evm_payload_authorization_valid_before"
	ErrValidAfterInFuture           = "invalid_batch_settlement_evm_payload_authorization_valid_after"
	ErrErc3009SignatureInvalid      = "invalid_batch_settlement_evm_receive_authorization_signature"
	ErrErc3009AuthorizationRequired = "invalid_batch_settlement_evm_erc3009_authorization_required"

	// ErrMissingEip712Domain signals that the resource server omitted the
	// token's EIP-712 domain (`name` / `version`) from
	// `paymentRequirements.extra`. The ERC-3009 deposit collector verifies the
	// `ReceiveWithAuthorization` signature against the token's EIP-712 domain,
	// so the facilitator cannot proceed without these fields.
	ErrMissingEip712Domain = "invalid_batch_settlement_evm_missing_eip712_domain"

	// Voucher errors
	ErrVoucherSignatureInvalid = "invalid_batch_settlement_evm_voucher_signature"
	// ErrMaxClaimableTooLow is aliased from batchsettlement.ErrCumulativeBelowClaimed
	// so the corrective-recovery client check (client/scheme.go) and the
	// facilitator emitter share a single source of truth and can never drift.
	ErrMaxClaimableTooLow     = batchsettlement.ErrCumulativeBelowClaimed
	ErrMaxClaimableExceedsBal = "invalid_batch_settlement_evm_cumulative_exceeds_balance"
	ErrInsufficientBalance    = "invalid_batch_settlement_evm_insufficient_balance"

	// Permit2 deposit authorization errors.
	ErrPermit2AuthorizationRequired = "invalid_batch_settlement_evm_permit2_authorization_required"
	ErrPermit2InvalidSpender        = "invalid_batch_settlement_evm_permit2_invalid_spender"
	ErrPermit2AmountMismatch        = "invalid_batch_settlement_evm_permit2_amount_mismatch"
	ErrPermit2DeadlineExpired       = "invalid_batch_settlement_evm_permit2_deadline_expired"
	ErrPermit2InvalidSignature      = "invalid_batch_settlement_evm_permit2_invalid_signature"
	ErrPermit2AllowanceRequired     = "invalid_batch_settlement_evm_permit2_allowance_required"

	// EIP-2612 permit segment errors (gas-sponsored Permit2 branch).
	ErrEip2612AmountMismatch   = "invalid_batch_settlement_evm_eip2612_amount_mismatch"
	ErrEip2612OwnerMismatch    = "invalid_batch_settlement_evm_eip2612_owner_mismatch"
	ErrEip2612AssetMismatch    = "invalid_batch_settlement_evm_eip2612_asset_mismatch"
	ErrEip2612SpenderMismatch  = "invalid_batch_settlement_evm_eip2612_spender_mismatch"
	ErrEip2612DeadlineExpired  = "invalid_batch_settlement_evm_eip2612_deadline_expired"
	ErrEip2612InvalidFormat    = "invalid_batch_settlement_evm_eip2612_invalid_format"
	ErrEip2612InvalidSignature = "invalid_batch_settlement_evm_eip2612_invalid_signature"

	// ERC-20 approval gas-sponsoring errors. The facilitator extension signer
	// broadcasts a pre-signed `approve(Permit2, max)` then the deposit() tx;
	// these errors surface format/payer/asset mismatches and missing signers.
	ErrErc20ApprovalUnavailable     = "invalid_batch_settlement_evm_erc20_approval_unavailable"
	ErrErc20ApprovalInvalidFormat   = "invalid_batch_settlement_evm_erc20_approval_invalid_format"
	ErrErc20ApprovalFromMismatch    = "invalid_batch_settlement_evm_erc20_approval_from_mismatch"
	ErrErc20ApprovalAssetMismatch   = "invalid_batch_settlement_evm_erc20_approval_asset_mismatch"
	ErrErc20ApprovalWrongSpender    = "invalid_batch_settlement_evm_erc20_approval_wrong_spender"
	ErrErc20ApprovalBroadcastFailed = "invalid_batch_settlement_evm_erc20_approval_broadcast_failed"

	// Channel state errors
	ErrChannelStateReadFailed = "invalid_batch_settlement_evm_channel_state_read_failed"
	ErrChannelNotFound        = "invalid_batch_settlement_evm_channel_not_found"
	ErrRpcReadFailed          = "invalid_batch_settlement_evm_rpc_read_failed"

	// Transaction errors
	ErrDepositTransactionFailed = "invalid_batch_settlement_evm_deposit_transaction_failed"
	ErrClaimTransactionFailed   = "invalid_batch_settlement_evm_claim_transaction_failed"
	ErrSettleTransactionFailed  = "invalid_batch_settlement_evm_settle_transaction_failed"
	ErrRefundTransactionFailed  = "invalid_batch_settlement_evm_refund_transaction_failed"
	ErrTransactionReverted      = "invalid_batch_settlement_evm_transaction_reverted"
	ErrWaitForReceipt           = "invalid_batch_settlement_evm_wait_for_receipt_failed"

	// Simulation errors
	ErrDepositSimulationFailed = "invalid_batch_settlement_evm_deposit_simulation_failed"
	ErrClaimSimulationFailed   = "invalid_batch_settlement_evm_claim_simulation_failed"
	ErrSettleSimulationFailed  = "invalid_batch_settlement_evm_settle_simulation_failed"
	ErrRefundSimulationFailed  = "invalid_batch_settlement_evm_refund_simulation_failed"

	// ERC-6492 counterfactual deployment errors (ERC-3009 deposit path). Wire values keep the
	// scheme prefix to match the rest of this package's contract.
	//
	// ErrFactoryNotAllowed is returned when a counterfactual deposit references a factory
	// that is not in the facilitator's EIP6492AllowedFactories allowlist.
	ErrFactoryNotAllowed = "invalid_batch_settlement_evm_eip6492_factory_not_allowed"
	// ErrSmartWalletDeploymentFailed is returned when the ERC-6492 factory deployment
	// transaction itself fails or reverts.
	ErrSmartWalletDeploymentFailed = "invalid_batch_settlement_evm_smart_wallet_deployment_failed"

	// Authorizer errors
	ErrAuthorizerAddressMismatch = "invalid_batch_settlement_evm_authorizer_address_mismatch"
	ErrAuthorizerNotConfigured   = "invalid_batch_settlement_evm_authorizer_not_configured"

	// Settle action errors
	ErrUnknownSettleAction = "invalid_batch_settlement_evm_unknown_settle_action"
	ErrNothingToSettle     = "invalid_batch_settlement_evm_nothing_to_settle"
	ErrRefundNoBalance     = batchsettlement.ErrRefundNoBalance
)

Functions

func BuildSettleExtra(channelId string, state *batchsettlement.ChannelState) map[string]interface{}

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:296

BuildSettleExtra creates the Extensions map for SETTLE responses:

{ "channelState": { channelId, balance, totalClaimed, withdrawRequestedAt,
                    refundNonce } }

Server-side AfterSettleHook reads extra.channelState.* and the resource server's enrichSettlementResponse hook then adds chargedCumulativeAmount (and, for deposits, chargedAmount) on top via additive enrichment.

func BuildVerifyExtra(channelId string, state *batchsettlement.ChannelState) map[string]interface{}

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:284

BuildVerifyExtra creates the Extensions map for VERIFY responses:

{ channelId, balance, totalClaimed, withdrawRequestedAt, refundNonce }

Server-side AfterVerifyHook reads these fields directly off extra (e.g. extra["balance"]); wrapping them in channelState like the settle response would silently break state tracking.

func Erc3009AuthorizationTimeInvalidReason(validAfter, validBefore *big.Int) string

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:304

Erc3009AuthorizationTimeInvalidReason checks the validity window of an ERC-3009 authorization. Returns an error code string if invalid, or empty string if valid.

func ExecuteClaimWithSignature( ctx context.Context, signer evm.FacilitatorEvmSigner, payload *batchsettlement.BatchSettlementClaimPayload, requirements types.PaymentRequirements, authorizerSigner batchsettlement.AuthorizerSigner, dataSuffix []byte, ) (*x402.SettleResponse, error)

Source: mechanisms/evm/batch-settlement/facilitator/claim.go:18

ExecuteClaimWithSignature executes a batch claim with receiverAuthorizer signature. If ClaimAuthorizerSignature is absent from the payload, the authorizerSigner auto-signs the ClaimBatch digest.

func ExecuteRefundWithSignature( ctx context.Context, signer evm.FacilitatorEvmSigner, payload *batchsettlement.BatchSettlementEnrichedRefundPayload, requirements types.PaymentRequirements, authorizerSigner batchsettlement.AuthorizerSigner, dataSuffix []byte, ) (*x402.SettleResponse, error)

Source: mechanisms/evm/batch-settlement/facilitator/refund.go:70

ExecuteRefundWithSignature executes a cooperative refund using receiverAuthorizer signature. If RefundAuthorizerSignature or ClaimAuthorizerSignature are absent, the authorizerSigner auto-signs them.

func ExecuteSettle( ctx context.Context, signer evm.FacilitatorEvmSigner, payload *batchsettlement.BatchSettlementSettlePayload, requirements types.PaymentRequirements, dataSuffix []byte, ) (*x402.SettleResponse, error)

Source: mechanisms/evm/batch-settlement/facilitator/settle.go:18

ExecuteSettle executes a settle action, transferring claimed funds to the receiver. Calls settle(receiver, token) on the BatchSettlement contract.

func NewBatchSettlementEvmScheme(signer evm.FacilitatorEvmSigner, authorizerSigner batchsettlement.AuthorizerSigner) *BatchSettlementEvmScheme

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:36

NewBatchSettlementEvmScheme creates a new batch settlement facilitator scheme. The authorizerSigner is an optional dedicated key that provides EIP-712 signatures for claimWithSignature / refundWithSignature. When provided, the facilitator advertises its address as receiverAuthorizer in /supported and auto-signs when the server omits signatures from the payload. When nil, no receiverAuthorizer is advertised and servers must supply their own authorizer signatures.

func NewBatchSettlementEvmSchemeWithConfig( signer evm.FacilitatorEvmSigner, authorizerSigner batchsettlement.AuthorizerSigner, config *BatchSettlementEvmSchemeConfig, ) *BatchSettlementEvmScheme

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:44

NewBatchSettlementEvmSchemeWithConfig creates a batch settlement facilitator scheme with optional configuration (e.g. the ERC-6492 factory allowlist for counterfactual deposits). A nil config behaves identically to NewBatchSettlementEvmScheme. The authorizerSigner is optional; see NewBatchSettlementEvmScheme for its semantics.

func ReadChannelState( ctx context.Context, signer evm.FacilitatorEvmSigner, channelId string, ) (*batchsettlement.ChannelState, error)

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:59

ReadChannelState reads onchain channel state via a 3-call multicall: channels(channelId), pendingWithdrawals(channelId), refundNonce(channelId). Returns an error tagged with ErrRpcReadFailed when any sub-call fails so callers can distinguish RPC failures from a missing channel (which returns zero balance/totalClaimed/refundNonce).

func SettleDeposit( ctx context.Context, signer evm.FacilitatorEvmSigner, payload *batchsettlement.BatchSettlementDepositPayload, requirements types.PaymentRequirements, extensions map[string]interface{}, fctx *x402.FacilitatorContext, dataSuffix []byte, allowedFactories []string, ) (*x402.SettleResponse, error)

Source: mechanisms/evm/batch-settlement/facilitator/deposit.go:297

SettleDeposit executes a deposit onchain. Calls deposit(config, amount, collector, collectorData) on the BatchSettlement contract.

extensions is the top-level payment.extensions envelope and fctx is the facilitator's registered extension context. They activate the ERC-20 approval gas-sponsoring branch (which broadcasts a pre-signed approve() before the deposit() via Erc20ApprovalGasSponsoringSigner.SendTransactions) and the EIP-2612 permit segment (encoded into collectorData). Both may be nil for the standard Permit2 path or for ERC-3009 deposits.

func ToContractChannelConfig(config batchsettlement.ChannelConfig) ContractChannelConfigTuple

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:36

ToContractChannelConfig normalizes a ChannelConfig into the address-checksummed Solidity tuple expected by the batch-settlement contract's deposit / refund / claim entry points.

func ValidateChannelConfig( config batchsettlement.ChannelConfig, channelId string, requirements types.PaymentRequirements, ) error

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:126

ValidateChannelConfig validates a ChannelConfig against payment requirements.

func VerifyBatchedVoucherTypedData( ctx context.Context, signer evm.FacilitatorEvmSigner, channelId string, maxClaimableAmount string, payerAuthorizer string, payer string, signature string, chainId *big.Int, ) (bool, error)

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:201

VerifyBatchedVoucherTypedData verifies a voucher signature using dual-path verification. If payerAuthorizer != 0x0: ECDSA verification against payerAuthorizer (fast, stateless). If payerAuthorizer == 0x0: ERC-1271 verification against payer (smart wallet path).

func VerifyDeposit( ctx context.Context, signer evm.FacilitatorEvmSigner, payload *batchsettlement.BatchSettlementDepositPayload, requirements types.PaymentRequirements, extensions map[string]interface{}, fctx *x402.FacilitatorContext, allowedFactories []string, ) (*x402.VerifyResponse, error)

Source: mechanisms/evm/batch-settlement/facilitator/deposit.go:52

VerifyDeposit verifies a batched deposit payload. Dispatches on the deposit transfer method (ERC-3009 or Permit2), validates the matching authorization, voucher signature, payer balance, and maxClaimableAmount, then simulates the onchain deposit to surface revert reasons before settle.

extensions is the top-level payment.extensions envelope and fctx is the facilitator's registered extension context. Together they enable the EIP-2612 and ERC-20 approval gas-sponsoring branches for Permit2 deposits. Both may be nil for the standard Permit2 path or for ERC-3009 deposits.

func VerifyRefundVoucher( ctx context.Context, signer evm.FacilitatorEvmSigner, payload *batchsettlement.BatchSettlementRefundPayload, requirements types.PaymentRequirements, channelConfig batchsettlement.ChannelConfig, ) (*x402.VerifyResponse, error)

Source: mechanisms/evm/batch-settlement/facilitator/voucher.go:29

VerifyRefundVoucher verifies a cooperative-refund payload's voucher. The voucher is zero-charge: maxClaimableAmount == chargedCumulativeAmount, which on a fresh channel may equal totalClaimed exactly.

func VerifyVoucher( ctx context.Context, signer evm.FacilitatorEvmSigner, payload *batchsettlement.BatchSettlementVoucherPayload, requirements types.PaymentRequirements, channelConfig batchsettlement.ChannelConfig, ) (*x402.VerifyResponse, error)

Source: mechanisms/evm/batch-settlement/facilitator/voucher.go:16

VerifyVoucher verifies a batched voucher-only payload. Checks voucher signature, reads onchain channel state, validates cumulative ceiling.

Types

type BatchSettlementEvmScheme

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:24

BatchSettlementEvmScheme implements SchemeNetworkFacilitator for batch settlement on EVM.

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

func CaipFamily() string

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:62

CaipFamily returns the CAIP family pattern this facilitator supports.

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

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:69

GetExtra returns mechanism-specific extra data for the supported kinds endpoint. Exposes the receiverAuthorizer address so server and client can embed it in ChannelConfig. Returns nil when no authorizer signer is configured, so no receiverAuthorizer is advertised.

func GetSigners(_ x402.Network) []string

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:79

GetSigners returns signer addresses used by this facilitator.

func Scheme) Scheme() string

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:57

Scheme returns the scheme identifier.

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

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:136

Settle settles a batched payment onchain. Routes based on payload type or settleAction field.

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

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:85

Verify verifies a batched payment payload. Routes to deposit or voucher verification based on payload type.

type BatchSettlementEvmSchemeConfig

Source: mechanisms/evm/batch-settlement/facilitator/scheme.go:14

BatchSettlementEvmSchemeConfig holds optional facilitator configuration.

type BatchSettlementEvmSchemeConfig struct {
	// EIP6492AllowedFactories is the allowlist of factory contract addresses (hex strings,
	// case-insensitive) the facilitator will call to deploy an undeployed (ERC-6492
	// counterfactual) smart wallet before an ERC-3009 deposit. A non-empty list enables
	// counterfactual deposit support; an empty list (the default) denies all factory
	// deployment, so counterfactual deposits are rejected with ErrFactoryNotAllowed.
	EIP6492AllowedFactories []string
}
Fields
  • EIP6492AllowedFactories []string

    EIP6492AllowedFactories is the allowlist of factory contract addresses (hex strings, case-insensitive) the facilitator will call to deploy an undeployed (ERC-6492 counterfactual) smart wallet before an ERC-3009 deposit. A non-empty list enables counterfactual deposit support; an empty list (the default) denies all factory deployment, so counterfactual deposits are rejected with ErrFactoryNotAllowed.

type ContractChannelConfigTuple

Source: mechanisms/evm/batch-settlement/facilitator/utils.go:23

ContractChannelConfigTuple is the concrete struct shape passed to BatchSettlement contract calls (deposit, refund, claim). Field names and ordering match the Solidity ChannelConfig struct so go-ethereum's ABI packer can map them by reflection.

type ContractChannelConfigTuple struct {
	Payer              common.Address
	PayerAuthorizer    common.Address
	Receiver           common.Address
	ReceiverAuthorizer common.Address
	Token              common.Address
	WithdrawDelay      *big.Int
	Salt               [32]byte
}
Fields
  • Payer common.Address
  • PayerAuthorizer common.Address
  • Receiver common.Address
  • ReceiverAuthorizer common.Address
  • Token common.Address
  • WithdrawDelay *big.Int
  • Salt [32]byte