Mechanisms

mechanisms/evm

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

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

Constants

Source: mechanisms/evm/constants.go:9

const (
	// Scheme identifiers
	SchemeExact   = "exact"
	SchemeUpto    = "upto"
	SchemeBatched = "batch-settlement"

	// Default token decimals for USDC
	DefaultDecimals = 6

	// EIP-3009 function names
	FunctionTransferWithAuthorization = "transferWithAuthorization"
	FunctionReceiveWithAuthorization  = "receiveWithAuthorization"
	FunctionAuthorizationState        = "authorizationState"
	FunctionTryAggregate              = "tryAggregate"

	// Permit2 function names
	FunctionSettle           = "settle"
	FunctionSettleWithPermit = "settleWithPermit"

	// Transaction status
	TxStatusSuccess = 1
	TxStatusFailed  = 0

	// Default validity period (1 hour)
	DefaultValidityPeriod = 3600 // seconds

	// ERC-6492 magic value (last 32 bytes of wrapped signature)
	// This is bytes32(uint256(keccak256("erc6492.invalid.signature")) - 1)
	ERC6492MagicValue = "0x6492649264926492649264926492649264926492649264926492649264926492"

	// EIP-1271 magic value (returned by isValidSignature on success)
	EIP1271MagicValue = "0x1626ba7e"

	// Shared error constants (used by verify_universal.go and other shared utilities)
	ErrUndeployedSmartWallet = "invalid_exact_evm_payload_undeployed_smart_wallet"

	// Permit2 constants
	// PERMIT2Address is the canonical Uniswap Permit2 contract address.
	// Same address on all EVM chains via CREATE2 deployment.
	PERMIT2Address = "0x000000000022D473030F116dDEE9F6B43aC78BA3"

	// MULTICALL3Address is the canonical Multicall3 deployment address.
	// Same address on all EVM chains via CREATE2 deployment.
	MULTICALL3Address = "0xcA11bde05977b3631167028862bE2a173976CA11"

	// X402ExactPermit2ProxyAddress is the x402 exact payment proxy.
	// Vanity address: 0x4020...0001 for easy recognition.
	X402ExactPermit2ProxyAddress = "0x402085c248EeA27D92E8b30b2C58ed07f9E20001"

	// X402UptoPermit2ProxyAddress is the x402 upto payment proxy.
	// Vanity address: 0x4020...0002 for easy recognition.
	X402UptoPermit2ProxyAddress = "0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002"

	// Permit2DeadlineBuffer is the time buffer (in seconds) added when checking
	// deadline expiration to account for block propagation time.
	Permit2DeadlineBuffer = 6

	// ERC20ApproveGasLimit is the gas limit for a standard ERC-20 approve() transaction.
	ERC20ApproveGasLimit = 70000

	// DefaultMaxFeePerGas is the fallback max fee per gas (1 gwei) for gas cost estimation.
	DefaultMaxFeePerGas = 1_000_000_000
)

Shared Permit2 error constants used by both the exact and upto facilitators. Both schemes write these strings to JSON responses and facilitate cross-SDK parity, so the values must never change without a coordinated update across all SDKs.

Source: mechanisms/evm/permit2_errors.go:16

const (
	// Verification errors
	ErrPermit2InvalidSpender    = "invalid_permit2_spender"
	ErrPermit2RecipientMismatch = "invalid_permit2_recipient_mismatch"
	ErrPermit2DeadlineExpired   = "permit2_deadline_expired"
	ErrPermit2NotYetValid       = "permit2_not_yet_valid"
	ErrPermit2AmountMismatch    = "permit2_amount_mismatch"
	ErrPermit2TokenMismatch     = "permit2_token_mismatch"
	ErrPermit2InvalidSignature  = "invalid_permit2_signature"
	ErrPermit2AllowanceRequired = "permit2_allowance_required"

	// Settle errors (from contract reverts)
	ErrPermit2InvalidAmount      = "permit2_invalid_amount"
	ErrPermit2InvalidDestination = "permit2_invalid_destination"
	ErrPermit2InvalidOwner       = "permit2_invalid_owner"
	ErrPermit2PaymentTooEarly    = "permit2_payment_too_early"
	ErrPermit2InvalidNonce       = "permit2_invalid_nonce"
	ErrPermit2612AmountMismatch  = "permit2_2612_amount_mismatch"

	// Simulation errors
	ErrPermit2SimulationFailed    = "permit2_simulation_failed"
	ErrPermit2InsufficientBalance = "permit2_insufficient_balance"
	ErrPermit2ProxyNotDeployed    = "permit2_proxy_not_deployed"

	// ERC-20 approval gas-sponsoring errors
	ErrErc20ApprovalInsufficientEth = "erc20_approval_insufficient_eth_for_gas"
	ErrErc20ApprovalBroadcastFailed = "erc20_approval_broadcast_failed"
)

BuilderCodeKey is the extension key for the ERC-8021 builder-code extension. It is replicated here (rather than imported from the buildercode extension package) so the base evm mechanism stays a dependency-free leaf - the buildercode package defines its own matching public constant and imports evm, mirroring the TS shared/extensions BUILDER_CODE_KEY pattern.

Source: mechanisms/evm/datasuffix.go:13

const BuilderCodeKey = "builder-code"

Shared EVM error constants used across all EVM payment types. Values must never change without a coordinated update across all SDKs.

Source: mechanisms/evm/permit2_errors.go:8

const (
	// ErrAssetNotDeployedContract is returned when the payment asset address has no bytecode.
	// EOAs return empty data on any eth_call without reverting, causing silent no-op settlements.
	ErrAssetNotDeployedContract = "asset_not_deployed_contract"
)

Source: mechanisms/evm/types.go:42

const (
	// AssetTransferMethodEIP3009 uses EIP-3009 transferWithAuthorization
	AssetTransferMethodEIP3009 AssetTransferMethod = "eip3009"
	// AssetTransferMethodPermit2 uses Permit2 + x402Permit2Proxy
	AssetTransferMethodPermit2 AssetTransferMethod = "permit2"
)

Variables

Source: mechanisms/evm/constants.go:73

var (
	// Network chain IDs
	ChainIDBase          = big.NewInt(8453)
	ChainIDBaseSepolia   = big.NewInt(84532)
	ChainIDMegaETH       = big.NewInt(4326)
	ChainIDMonad         = big.NewInt(143)
	ChainIDMezo          = big.NewInt(31612)
	ChainIDMezoTestnet   = big.NewInt(31611)
	ChainIDStable        = big.NewInt(988)
	ChainIDStableTestnet = big.NewInt(2201)
	ChainIDPolygon       = big.NewInt(137)
	ChainIDArbOne        = big.NewInt(42161)
	ChainIDArbSepolia    = big.NewInt(421614)
	ChainIDRadius        = big.NewInt(723487)
	ChainIDRadiusTestnet = big.NewInt(72344)
	ChainIDADI           = big.NewInt(36900)
	ChainIDHPP           = big.NewInt(190415)
	ChainIDHPPSepolia    = big.NewInt(181228)
	ChainIDXDC           = big.NewInt(50)
	ChainIDXDCApothem    = big.NewInt(51)
	ChainIDIgra          = big.NewInt(38833)
	ChainIDFlare         = big.NewInt(14)
	ChainIDCelo          = big.NewInt(42220)
	ChainIDCeloSepolia   = big.NewInt(11142220)

	// Network configurations
	// See DEFAULT_ASSETS.md for guidelines on adding new chains
	//
	// Default Asset Selection Policy:
	// - Each chain has the right to determine its own default stablecoin
	// - If the chain has officially endorsed a stablecoin, that asset should be used
	// - If no official stance exists, the chain team should make the selection
	//
	// Both EIP-3009 (transferWithAuthorization) and Permit2 asset transfer methods are supported.
	// EIP-3009 is the default. Set AssetTransferMethod to AssetTransferMethodPermit2 for tokens
	// that don't support EIP-3009. See DEFAULT_ASSETS.md for details.
	NetworkConfigs = map[string]NetworkConfig{

		"eip155:8453": {
			ChainID: ChainIDBase,
			DefaultAsset: AssetInfo{
				Address:  "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
				Name:     "USD Coin",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:84532": {
			ChainID: ChainIDBaseSepolia,
			DefaultAsset: AssetInfo{
				Address:  "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
				Name:     "USDC",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:4326": {
			ChainID: ChainIDMegaETH,
			DefaultAsset: AssetInfo{
				Address:             "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7",
				Name:                "MegaUSD",
				Version:             "1",
				Decimals:            18,
				AssetTransferMethod: AssetTransferMethodPermit2,
				SupportsEip2612:     true,
			},
		},

		"eip155:143": {
			ChainID: ChainIDMonad,
			DefaultAsset: AssetInfo{
				Address:  "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
				Name:     "USD Coin",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:31612": {
			ChainID: ChainIDMezo,
			DefaultAsset: AssetInfo{
				Address:             "0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186",
				Name:                "Mezo USD",
				Version:             "1",
				Decimals:            18,
				AssetTransferMethod: AssetTransferMethodPermit2,
				SupportsEip2612:     true,
			},
		},

		"eip155:31611": {
			ChainID: ChainIDMezoTestnet,
			DefaultAsset: AssetInfo{
				Address:             "0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503",
				Name:                "Mezo USD",
				Version:             "1",
				Decimals:            18,
				AssetTransferMethod: AssetTransferMethodPermit2,
				SupportsEip2612:     true,
			},
		},

		"eip155:988": {
			ChainID: ChainIDStable,
			DefaultAsset: AssetInfo{
				Address:  "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
				Name:     "USDT0",
				Version:  "1",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:2201": {
			ChainID: ChainIDStableTestnet,
			DefaultAsset: AssetInfo{
				Address:  "0x78Cf24370174180738C5B8E352B6D14c83a6c9A9",
				Name:     "USDT0",
				Version:  "1",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:137": {
			ChainID: ChainIDPolygon,
			DefaultAsset: AssetInfo{
				Address:  "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
				Name:     "USD Coin",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:42161": {
			ChainID: ChainIDArbOne,
			DefaultAsset: AssetInfo{
				Address:  "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
				Name:     "USD Coin",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:421614": {
			ChainID: ChainIDArbSepolia,
			DefaultAsset: AssetInfo{
				Address:  "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
				Name:     "USD Coin",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:723487": {
			ChainID: ChainIDRadius,
			DefaultAsset: AssetInfo{
				Address:             "0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb",
				Name:                "Stable Coin",
				Version:             "1",
				Decimals:            DefaultDecimals,
				AssetTransferMethod: AssetTransferMethodPermit2,
				SupportsEip2612:     true,
			},
		},

		"eip155:72344": {
			ChainID: ChainIDRadiusTestnet,
			DefaultAsset: AssetInfo{
				Address:             "0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb",
				Name:                "Stable Coin",
				Version:             "1",
				Decimals:            DefaultDecimals,
				AssetTransferMethod: AssetTransferMethodPermit2,
				SupportsEip2612:     true,
			},
		},

		"eip155:36900": {
			ChainID: ChainIDADI,
			DefaultAsset: AssetInfo{
				Address:  "0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2",
				Name:     "USDC.e",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:190415": {
			ChainID: ChainIDHPP,
			DefaultAsset: AssetInfo{
				Address:  "0x401eCb1D350407f13ba348573E5630B83638E30D",
				Name:     "Bridged USDC",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:181228": {
			ChainID: ChainIDHPPSepolia,
			DefaultAsset: AssetInfo{
				Address:  "0x401eCb1D350407f13ba348573E5630B83638E30D",
				Name:     "Bridged USDC",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:50": {
			ChainID: ChainIDXDC,
			DefaultAsset: AssetInfo{
				Address:  "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1",
				Name:     "USDC",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:51": {
			ChainID: ChainIDXDCApothem,
			DefaultAsset: AssetInfo{
				Address:  "0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4",
				Name:     "USDC",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:38833": {
			ChainID: ChainIDIgra,
			DefaultAsset: AssetInfo{
				Address:             "0xA5b8BF902b2844dA17d4506cc827F7F1681735E7",
				Name:                "USDC",
				Version:             "1",
				Decimals:            DefaultDecimals,
				AssetTransferMethod: AssetTransferMethodPermit2,
			},
		},

		"eip155:14": {
			ChainID: ChainIDFlare,
			DefaultAsset: AssetInfo{
				Address:  "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
				Name:     "USD₮0",
				Version:  "1",
				Decimals: DefaultDecimals,
			},
		},
		"eip155:42220": {
			ChainID: ChainIDCelo,
			DefaultAsset: AssetInfo{
				Address:  "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
				Name:     "USDC",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},

		"eip155:11142220": {
			ChainID: ChainIDCeloSepolia,
			DefaultAsset: AssetInfo{
				Address:  "0x01C5C0122039549AD1493B8220cABEdD739BC44E",
				Name:     "USDC",
				Version:  "2",
				Decimals: DefaultDecimals,
			},
		},
	}

	// EIP-3009 ABI for transferWithAuthorization with v,r,s (EOA signatures)
	TransferWithAuthorizationVRSABI = []byte(`[
		{
			"inputs": [
				{"name": "from", "type": "address"},
				{"name": "to", "type": "address"},
				{"name": "value", "type": "uint256"},
				{"name": "validAfter", "type": "uint256"},
				{"name": "validBefore", "type": "uint256"},
				{"name": "nonce", "type": "bytes32"},
				{"name": "v", "type": "uint8"},
				{"name": "r", "type": "bytes32"},
				{"name": "s", "type": "bytes32"}
			],
			"name": "transferWithAuthorization",
			"outputs": [],
			"stateMutability": "nonpayable",
			"type": "function"
		}
	]`)

	// EIP-3009 ABI for transferWithAuthorization with bytes signature (smart wallets)
	TransferWithAuthorizationBytesABI = []byte(`[
		{
			"inputs": [
				{"name": "from", "type": "address"},
				{"name": "to", "type": "address"},
				{"name": "value", "type": "uint256"},
				{"name": "validAfter", "type": "uint256"},
				{"name": "validBefore", "type": "uint256"},
				{"name": "nonce", "type": "bytes32"},
				{"name": "signature", "type": "bytes"}
			],
			"name": "transferWithAuthorization",
			"outputs": [],
			"stateMutability": "nonpayable",
			"type": "function"
		}
	]`)

	// Legacy: Combined ABI (deprecated, use specific ABIs above)
	TransferWithAuthorizationABI = TransferWithAuthorizationVRSABI

	// ERC20TransferEventABI for parsing Transfer event logs
	ERC20TransferEventABI = []byte(`[
		{
			"anonymous": false,
			"inputs": [
				{"indexed": true, "name": "from", "type": "address"},
				{"indexed": true, "name": "to", "type": "address"},
				{"indexed": false, "name": "value", "type": "uint256"}
			],
			"name": "Transfer",
			"type": "event"
		}
	]`)

	// ABI for authorizationState check
	AuthorizationStateABI = []byte(`[
		{
			"inputs": [
				{"name": "authorizer", "type": "address"},
				{"name": "nonce", "type": "bytes32"}
			],
			"name": "authorizationState",
			"outputs": [{"name": "", "type": "bool"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// Multicall3TryAggregateABI batches arbitrary eth_call requests.
	Multicall3TryAggregateABI = []byte(`[
		{
			"inputs": [
				{"name": "requireSuccess", "type": "bool"},
				{
					"name": "calls",
					"type": "tuple[]",
					"components": [
						{"name": "target", "type": "address"},
						{"name": "callData", "type": "bytes"}
					]
				}
			],
			"name": "tryAggregate",
			"outputs": [
				{
					"name": "returnData",
					"type": "tuple[]",
					"components": [
						{"name": "success", "type": "bool"},
						{"name": "returnData", "type": "bytes"}
					]
				}
			],
			"stateMutability": "payable",
			"type": "function"
		}
	]`)

	// ERC20AllowanceABI for checking Permit2 approval
	ERC20AllowanceABI = []byte(`[
		{
			"inputs": [
				{"name": "owner", "type": "address"},
				{"name": "spender", "type": "address"}
			],
			"name": "allowance",
			"outputs": [{"name": "", "type": "uint256"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// ERC20ApproveABI for approving Permit2
	ERC20ApproveABI = []byte(`[
		{
			"inputs": [
				{"name": "spender", "type": "address"},
				{"name": "amount", "type": "uint256"}
			],
			"name": "approve",
			"outputs": [{"name": "", "type": "bool"}],
			"stateMutability": "nonpayable",
			"type": "function"
		}
	]`)

	// ERC20BalanceOfABI for checking token balance
	ERC20BalanceOfABI = []byte(`[
		{
			"inputs": [
				{"name": "account", "type": "address"}
			],
			"name": "balanceOf",
			"outputs": [{"name": "", "type": "uint256"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// ERC20NameABI for checking EIP-712 domain name diagnostics.
	ERC20NameABI = []byte(`[
		{
			"inputs": [],
			"name": "name",
			"outputs": [{"name": "", "type": "string"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// ERC20VersionABI for checking EIP-712 domain version diagnostics.
	ERC20VersionABI = []byte(`[
		{
			"inputs": [],
			"name": "version",
			"outputs": [{"name": "", "type": "string"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// X402ExactPermit2ProxySettleABI for calling settle on x402ExactPermit2Proxy
	X402ExactPermit2ProxySettleABI = []byte(`[
		{
			"type": "function",
			"name": "settle",
			"inputs": [
				{
					"name": "permit",
					"type": "tuple",
					"components": [
						{
							"name": "permitted",
							"type": "tuple",
							"components": [
								{"name": "token", "type": "address"},
								{"name": "amount", "type": "uint256"}
							]
						},
						{"name": "nonce", "type": "uint256"},
						{"name": "deadline", "type": "uint256"}
					]
				},
				{"name": "owner", "type": "address"},
				{
					"name": "witness",
					"type": "tuple",
					"components": [
						{"name": "to", "type": "address"},
						{"name": "validAfter", "type": "uint256"}
					]
				},
				{"name": "signature", "type": "bytes"}
			],
			"outputs": [],
			"stateMutability": "nonpayable"
		}
	]`)

	// X402ExactPermit2ProxyPermit2ABI for verifying proxy deployment
	X402ExactPermit2ProxyPermit2ABI = []byte(`[
		{
			"inputs": [],
			"name": "PERMIT2",
			"outputs": [{"name": "", "type": "address"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// Multicall3GetEthBalanceABI for querying native ETH balance via Multicall3.
	Multicall3GetEthBalanceABI = []byte(`[
		{
			"inputs": [
				{"name": "addr", "type": "address"}
			],
			"name": "getEthBalance",
			"outputs": [{"name": "balance", "type": "uint256"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// X402UptoPermit2ProxySettleABI for calling settle on x402UptoPermit2Proxy.
	// Differs from exact: takes an additional `amount` param and witness includes `facilitator`.
	X402UptoPermit2ProxySettleABI = []byte(`[
		{
			"type": "function",
			"name": "settle",
			"inputs": [
				{
					"name": "permit",
					"type": "tuple",
					"components": [
						{
							"name": "permitted",
							"type": "tuple",
							"components": [
								{"name": "token", "type": "address"},
								{"name": "amount", "type": "uint256"}
							]
						},
						{"name": "nonce", "type": "uint256"},
						{"name": "deadline", "type": "uint256"}
					]
				},
				{"name": "amount", "type": "uint256"},
				{"name": "owner", "type": "address"},
				{
					"name": "witness",
					"type": "tuple",
					"components": [
						{"name": "to", "type": "address"},
						{"name": "facilitator", "type": "address"},
						{"name": "validAfter", "type": "uint256"}
					]
				},
				{"name": "signature", "type": "bytes"}
			],
			"outputs": [],
			"stateMutability": "nonpayable"
		}
	]`)

	// X402UptoPermit2ProxySettleWithPermitABI for calling settleWithPermit on x402UptoPermit2Proxy (EIP-2612 extension).
	X402UptoPermit2ProxySettleWithPermitABI = []byte(`[
		{
			"type": "function",
			"name": "settleWithPermit",
			"inputs": [
				{
					"name": "permit2612",
					"type": "tuple",
					"components": [
						{"name": "value", "type": "uint256"},
						{"name": "deadline", "type": "uint256"},
						{"name": "r", "type": "bytes32"},
						{"name": "s", "type": "bytes32"},
						{"name": "v", "type": "uint8"}
					]
				},
				{
					"name": "permit",
					"type": "tuple",
					"components": [
						{
							"name": "permitted",
							"type": "tuple",
							"components": [
								{"name": "token", "type": "address"},
								{"name": "amount", "type": "uint256"}
							]
						},
						{"name": "nonce", "type": "uint256"},
						{"name": "deadline", "type": "uint256"}
					]
				},
				{"name": "amount", "type": "uint256"},
				{"name": "owner", "type": "address"},
				{
					"name": "witness",
					"type": "tuple",
					"components": [
						{"name": "to", "type": "address"},
						{"name": "facilitator", "type": "address"},
						{"name": "validAfter", "type": "uint256"}
					]
				},
				{"name": "signature", "type": "bytes"}
			],
			"outputs": [],
			"stateMutability": "nonpayable"
		}
	]`)

	// X402UptoPermit2ProxyPermit2ABI for verifying upto proxy deployment
	X402UptoPermit2ProxyPermit2ABI = []byte(`[
		{
			"inputs": [],
			"name": "PERMIT2",
			"outputs": [{"name": "", "type": "address"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// EIP2612NoncesABI for querying EIP-2612 nonces
	EIP2612NoncesABI = []byte(`[
		{
			"inputs": [
				{"name": "owner", "type": "address"}
			],
			"name": "nonces",
			"outputs": [{"name": "", "type": "uint256"}],
			"stateMutability": "view",
			"type": "function"
		}
	]`)

	// X402ExactPermit2ProxySettleWithPermitABI for calling settleWithPermit (EIP-2612 extension)
	X402ExactPermit2ProxySettleWithPermitABI = []byte(`[
		{
			"type": "function",
			"name": "settleWithPermit",
			"inputs": [
				{
					"name": "permit2612",
					"type": "tuple",
					"components": [
						{"name": "value", "type": "uint256"},
						{"name": "deadline", "type": "uint256"},
						{"name": "r", "type": "bytes32"},
						{"name": "s", "type": "bytes32"},
						{"name": "v", "type": "uint8"}
					]
				},
				{
					"name": "permit",
					"type": "tuple",
					"components": [
						{
							"name": "permitted",
							"type": "tuple",
							"components": [
								{"name": "token", "type": "address"},
								{"name": "amount", "type": "uint256"}
							]
						},
						{"name": "nonce", "type": "uint256"},
						{"name": "deadline", "type": "uint256"}
					]
				},
				{"name": "owner", "type": "address"},
				{
					"name": "witness",
					"type": "tuple",
					"components": [
						{"name": "to", "type": "address"},
						{"name": "validAfter", "type": "uint256"}
					]
				},
				{"name": "signature", "type": "bytes"}
			],
			"outputs": [],
			"stateMutability": "nonpayable"
		}
	]`)

	// EIP712DomainTypes defines the standard EIP-712 domain type for Permit2.
	// Permit2 uses name + chainId + verifyingContract (no version field).
	EIP712DomainTypes = []TypedDataField{
		{Name: "name", Type: "string"},
		{Name: "chainId", Type: "uint256"},
		{Name: "verifyingContract", Type: "address"},
	}

	// Permit2WitnessTypes defines the EIP-712 types for Permit2 with witness.
	// Field order MUST match the on-chain Permit2 contract and TypeScript implementation.
	Permit2WitnessTypes = map[string][]TypedDataField{
		"PermitWitnessTransferFrom": {
			{Name: "permitted", Type: "TokenPermissions"},
			{Name: "spender", Type: "address"},
			{Name: "nonce", Type: "uint256"},
			{Name: "deadline", Type: "uint256"},
			{Name: "witness", Type: "Witness"},
		},
		"TokenPermissions": {
			{Name: "token", Type: "address"},
			{Name: "amount", Type: "uint256"},
		},
		"Witness": {
			{Name: "to", Type: "address"},
			{Name: "validAfter", Type: "uint256"},
		},
	}
)

EIP2612PermitTypes defines the EIP-712 types for EIP-2612 permit signing.

Source: mechanisms/evm/constants.go:774

var EIP2612PermitTypes = map[string][]TypedDataField{
	"Permit": {
		{Name: "owner", Type: "address"},
		{Name: "spender", Type: "address"},
		{Name: "value", Type: "uint256"},
		{Name: "nonce", Type: "uint256"},
		{Name: "deadline", Type: "uint256"},
	},
}

EIP712DomainTypesWithVersion is the standard EIP-712 domain type with version field. Used by EIP-2612 tokens (unlike Permit2 which omits version).

Source: mechanisms/evm/constants.go:786

var EIP712DomainTypesWithVersion = []TypedDataField{
	{Name: "name", Type: "string"},
	{Name: "version", Type: "string"},
	{Name: "chainId", Type: "uint256"},
	{Name: "verifyingContract", Type: "address"},
}

UptoPermit2WitnessTypes defines the EIP-712 types for the upto Permit2 witness. The upto witness includes a facilitator field absent from the exact witness. Only the address matching witness.facilitator can call settle() on-chain. Field order MUST match the on-chain x402UptoPermit2Proxy contract and TypeScript implementation.

Source: mechanisms/evm/constants.go:805

var UptoPermit2WitnessTypes = map[string][]TypedDataField{
	"PermitWitnessTransferFrom": {
		{Name: "permitted", Type: "TokenPermissions"},
		{Name: "spender", Type: "address"},
		{Name: "nonce", Type: "uint256"},
		{Name: "deadline", Type: "uint256"},
		{Name: "witness", Type: "Witness"},
	},
	"TokenPermissions": {
		{Name: "token", Type: "address"},
		{Name: "amount", Type: "uint256"},
	},
	"Witness": {
		{Name: "to", Type: "address"},
		{Name: "facilitator", Type: "address"},
		{Name: "validAfter", Type: "uint256"},
	},
}

Functions

func AppendDataSuffix(calldata, suffix []byte) []byte

Source: mechanisms/evm/datasuffix.go:54

AppendDataSuffix appends an ERC-8021 data suffix to ABI-encoded calldata, returning the calldata unchanged when suffix is empty. Signers call this after packing the call so the suffix lands on-chain. Mirrors TS appendDataSuffix.

func BuildPermit2WitnessMap(to string, validAfter *big.Int) map[string]interface{}

Source: mechanisms/evm/eip712.go:254

BuildPermit2WitnessMap returns the witness map used in EIP-712 message construction. Centralizing this ensures eip712.go and exact/client/permit2.go stay in sync when the witness struct changes.

func BuildUptoPermit2WitnessMap(to string, facilitator string, validAfter *big.Int) map[string]interface{}

Source: mechanisms/evm/eip712.go:193

BuildUptoPermit2WitnessMap returns the witness map for upto EIP-712 message construction. Includes the facilitator field absent from the exact witness.

func BytesToHex(data []byte) string

Source: mechanisms/evm/utils.go:229

BytesToHex converts bytes to a hex string with 0x prefix

func CreateNonce() (string, error)

Source: mechanisms/evm/utils.go:27

CreateNonce generates a random 32-byte nonce for EIP-3009

func CreatePermit2Nonce() (string, error)

Source: mechanisms/evm/utils.go:38

CreatePermit2Nonce generates a random 256-bit nonce for Permit2. Permit2 uses uint256 nonces (not bytes32 like EIP-3009).

func CreateValidityWindow(duration time.Duration) (validAfter, validBefore *big.Int)

Source: mechanisms/evm/utils.go:214

CreateValidityWindow creates valid after/before timestamps

func FormatAmount(amount *big.Int, decimals int) string

Source: mechanisms/evm/utils.go:121

FormatAmount converts an amount in wei to a decimal string

func GetAssetInfo(network string, assetSymbolOrAddress string) (*AssetInfo, error)

Source: mechanisms/evm/utils.go:177

GetAssetInfo returns information about an asset on a network. If assetSymbolOrAddress is a valid address, returns info for that specific token. If assetSymbolOrAddress is empty or a symbol, attempts to use the network's default asset.

Args:

  • network: The network identifier
  • assetSymbolOrAddress: Either an asset address (0x...) or empty for default

Returns:

  • AssetInfo for the requested asset
  • Error if default asset is requested but not configured for this network

func GetEIP2612EIP712Types() map[string][]TypedDataField

Source: mechanisms/evm/constants.go:794

GetEIP2612EIP712Types returns the complete EIP-712 types map for EIP-2612 signing.

func GetERC7702DelegateAddress(code []byte) (common.Address, bool)

Source: mechanisms/evm/erc7702.go:25

GetERC7702DelegateAddress extracts the 20-byte delegate address from a 7702 designation. Returns a checksummed EIP-55 common.Address. The Python and TypeScript equivalents return lowercase hex strings - normalise before comparing cross-SDK outputs. Returns (common.Address{}, false) if code is not a valid delegation.

func GetEvmChainId(network string) (*big.Int, error)

Source: mechanisms/evm/utils.go:14

GetEvmChainId returns the chain ID for a given CAIP-2 network identifier (eip155:CHAIN_ID).

func GetNetworkConfig(network string) (*NetworkConfig, error)

Source: mechanisms/evm/utils.go:148

GetNetworkConfig returns the configuration for a CAIP-2 network identifier (eip155:CHAIN_ID). For networks with configured defaults, returns the full config. For other valid EIP-155 networks, returns a config with just the chain ID (no default asset).

func GetPermit2EIP712Types() map[string][]TypedDataField

Source: mechanisms/evm/constants.go:764

GetPermit2EIP712Types returns the complete EIP-712 types map for Permit2 signing. This combines the EIP712Domain with the Permit2-specific types. Use this function instead of defining types locally to ensure consistency.

func GetUptoPermit2EIP712Types() map[string][]TypedDataField

Source: mechanisms/evm/constants.go:826

GetUptoPermit2EIP712Types returns the complete EIP-712 types map for upto Permit2 signing. This combines the EIP712Domain with the upto-specific Permit2 types (including facilitator in witness).

func HasEIP6492Deployment(sigData *ERC6492SignatureData) bool

Source: mechanisms/evm/erc6492_deploy.go:16

HasEIP6492Deployment reports whether sigData carries ERC-6492 factory deployment information (a non-zero factory address and non-empty factory calldata).

Shared across facilitator schemes (exact, batch-settlement) so the counterfactual deployment routing is identical everywhere.

func HashEIP3009Authorization( authorization ExactEIP3009Authorization, chainID *big.Int, verifyingContract string, tokenName string, tokenVersion string, ) ([]byte, error)

Source: mechanisms/evm/eip712.go:123

HashEIP3009Authorization hashes a TransferWithAuthorization message for EIP-3009

This is a convenience function that wraps HashTypedData with the specific types and structure used by EIP-3009's transferWithAuthorization.

Args:

authorization: The EIP-3009 authorization data
chainID: The chain ID for the EIP-712 domain
verifyingContract: The token contract address
tokenName: The token name (e.g., "USD Coin")
tokenVersion: The token version (e.g., "2")

Returns:

32-byte hash suitable for signing or verification
error if hashing fails

func HashEIP712TypedData( domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}, ) ([32]byte, error)

Source: mechanisms/evm/verify_strict.go:53

HashEIP712TypedData computes the canonical EIP-712 digest: keccak256("\x19\x01" || domainSeparator || hashStruct(message))

func HashPermit2Authorization( authorization Permit2Authorization, chainID *big.Int, ) ([]byte, error)

Source: mechanisms/evm/eip712.go:275

HashPermit2Authorization hashes a PermitWitnessTransferFrom message for Permit2.

This function creates the EIP-712 hash for Permit2's PermitWitnessTransferFrom with the x402 witness structure.

Args:

authorization: The Permit2 authorization data
chainID: The chain ID for the EIP-712 domain

Returns:

32-byte hash suitable for signing or verification
error if hashing fails

func HashTypedData( domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}, ) ([]byte, error)

Source: mechanisms/evm/eip712.go:29

HashTypedData hashes EIP-712 typed data according to the specification

This function creates the EIP-712 hash that should be signed or verified. The hash is computed as: keccak256("\x19\x01" + domainSeparator + structHash)

Args:

domain: The EIP-712 domain separator parameters
types: The type definitions for the structured data
primaryType: The name of the primary type being hashed
message: The message data to hash

Returns:

32-byte hash suitable for signing or verification
error if hashing fails

func HashUptoPermit2Authorization( authorization UptoPermit2Authorization, chainID *big.Int, ) ([]byte, error)

Source: mechanisms/evm/eip712.go:203

HashUptoPermit2Authorization hashes a PermitWitnessTransferFrom message for the upto Permit2 scheme. Uses upto-specific witness types that include the facilitator address.

func HexToBytes(hexStr string) ([]byte, error)

Source: mechanisms/evm/utils.go:222

HexToBytes converts a hex string to bytes

func IsContractRevert(err error) bool

Source: mechanisms/evm/erc6492_deploy.go:28

IsContractRevert reports whether err looks like an on-chain contract revert (as opposed to a transport/RPC failure). Used to avoid misreporting an RPC blip during a post-deploy simulation as a deterministic "signature unsupported" rejection. Matches the revert-substring heuristic the EIP-3009 revert-reason parsers already rely on.

func IsEIP3009Payload(data map[string]interface{}) bool

Source: mechanisms/evm/types.go:183

IsEIP3009Payload checks if a payload map is an EIP-3009 payload.

func IsERC6492Signature(sig []byte) bool

Source: mechanisms/evm/erc6492.go:29

IsERC6492Signature checks if a signature has the ERC-6492 magic suffix

ERC-6492 signatures are wrapped signatures for counterfactual smart contract accounts. They end with a specific 32-byte magic value to distinguish them from regular signatures.

Args:

sig: The signature bytes to check

Returns:

true if the signature ends with the ERC-6492 magic value

func IsERC7702Delegation(code []byte) bool

Source: mechanisms/evm/erc7702.go:14

IsERC7702Delegation reports whether code is a valid ERC-7702 delegation designation: exactly 23 bytes (3-byte prefix + 20-byte delegate address).

NOTE: this is a diagnostic helper - the verification path does not branch on 7702 detection. It routes by code.length (via VerifySignatureStrict) and the delegate decides via isValidSignature, which mirrors on-chain SignatureChecker semantics.

func IsFactoryAllowed(factory [20]byte, allowedFactories []string) bool

Source: mechanisms/evm/erc6492_deploy.go:37

IsFactoryAllowed reports whether factory is present in allowedFactories (case-insensitive). An empty allowlist denies all factories, preventing unconstrained arbitrary call injection.

func IsPermit2Payload(data map[string]interface{}) bool

Source: mechanisms/evm/types.go:177

IsPermit2Payload checks if a payload map is a Permit2 payload.

func IsUptoPermit2Payload(data map[string]interface{}) bool

Source: mechanisms/evm/types.go:496

IsUptoPermit2Payload checks if a payload map is an upto Permit2 payload. Validates structural presence of all required fields including witness.facilitator.

func IsValidAddress(address string) bool

Source: mechanisms/evm/utils.go:67

IsValidAddress checks if a string is a valid Ethereum address

func MaxUint256() *big.Int

Source: mechanisms/evm/utils.go:50

MaxUint256 returns the maximum value for uint256 (used for unlimited approval).

func Multicall( ctx context.Context, signer FacilitatorEvmSigner, calls []MulticallCall, ) ([]MulticallResult, error)

Source: mechanisms/evm/multicall.go:46

Multicall batches typed and raw eth_call requests via Multicall3.

func NormalizeAddress(address string) string

Source: mechanisms/evm/utils.go:58

NormalizeAddress ensures an Ethereum address is in the correct format

func ParseAmount(amount string, decimals int) (*big.Int, error)

Source: mechanisms/evm/utils.go:82

ParseAmount converts a decimal string amount to wei based on token decimals

func ParseERC6492Signature(sig []byte) (*ERC6492SignatureData, error)

Source: mechanisms/evm/erc6492.go:53

ParseERC6492Signature unwraps an ERC-6492 signature to extract its components

ERC-6492 Format:

abi.encode((address factory, bytes factoryCalldata, bytes signature)) + magicBytes

If the signature is not ERC-6492 format, it returns the original signature as the InnerSignature with empty Factory and FactoryCalldata.

Args:

sig: The signature bytes (may or may not be ERC-6492 wrapped)

Returns:

ERC6492SignatureData containing the parsed components
error if the ERC-6492 format is invalid

func PayloadFromMap(data map[string]interface{}) (*ExactEIP3009Payload, error)

Source: mechanisms/evm/types.go:335

PayloadFromMap creates an ExactEIP3009Payload from a map

func Permit2PayloadFromMap(data map[string]interface{}) (*ExactPermit2Payload, error)

Source: mechanisms/evm/types.go:103

Permit2PayloadFromMap creates an ExactPermit2Payload from a map. Returns an error if required fields are missing or malformed.

func ResolveDataSuffix(fctx *x402.FacilitatorContext, ctx DataSuffixContext) ([]byte, error)

Source: mechanisms/evm/datasuffix.go:33

ResolveDataSuffix fetches the builder-code facilitator extension from fctx and returns the data suffix it produces. Returns nil when fctx is nil, no matching extension is registered, or the extension produces no suffix.

func ResolveRPCURL(config *RPCConfig, network string) string

Source: mechanisms/evm/rpc.go:30

ResolveRPCURL returns the appropriate RPC URL for the given network.

func ResolveReadSigner( ctx context.Context, signer ClientEvmSigner, rpcURL string, ) (ClientEvmSignerWithReadContract, error)

Source: mechanisms/evm/rpc.go:215

ResolveReadSigner returns a ClientEvmSignerWithReadContract. If the signer already implements a functional ReadContract, it is returned as-is. Otherwise an RPC-backed wrapper is created using rpcURL; if rpcURL is empty, nil is returned without error.

func ResolveTxSigner( ctx context.Context, signer ClientEvmSigner, rpcURL string, ) (ClientEvmSignerWithTxSigning, error)

Source: mechanisms/evm/rpc.go:242

ResolveTxSigner returns a ClientEvmSignerWithTxSigning. Nonce and fee-estimation capabilities are taken from the signer when available, and fall back to the provided rpcURL. Returns nil without error when the signer cannot sign transactions or when RPC capabilities are needed but rpcURL is empty.

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

Source: mechanisms/evm/erc6492_deploy.go:50

SendFactoryDeployTransaction submits the ERC-6492 factory deployment transaction and waits for the receipt, returning an error if the deployment transaction reverted. It is a no-op (nil) when sigData carries no deployment information.

func SplitEip2612Signature(signature string) (uint8, [32]byte, [32]byte, error)

Source: mechanisms/evm/eip2612.go:42

SplitEip2612Signature splits a 65-byte hex-encoded signature into v, r, s components.

func UptoPermit2PayloadFromMap(data map[string]interface{}) (*UptoPermit2Payload, error)

Source: mechanisms/evm/types.go:415

UptoPermit2PayloadFromMap creates an UptoPermit2Payload from a map. Returns an error if required fields are missing or malformed.

func ValidateAssetIsContract(ctx context.Context, signer FacilitatorEvmSigner, asset string) (string, error)

Source: mechanisms/evm/utils.go:236

ValidateAssetIsContract checks whether the payment asset is a deployed contract. Returns (ErrAssetNotDeployedContract, nil) for an EOA/empty address, ("", nil) for a deployed contract, or ("", err) if eth_getCode itself fails.

func ValidateEip2612PermitForPayment(info *eip2612gassponsor.Info, payer string, tokenAddress string) string

Source: mechanisms/evm/eip2612.go:14

ValidateEip2612PermitForPayment validates EIP-2612 extension data for a Permit2 payment. Returns an empty string if valid, or an error-reason string on failure.

func VerifyEIP1271Signature( ctx context.Context, signer FacilitatorEvmSigner, wallet string, hash [32]byte, signature []byte, ) (bool, error)

Source: mechanisms/evm/verify_1271.go:42

VerifyEIP1271Signature verifies a signature from a smart contract wallet using EIP-1271

EIP-1271 defines a standard way for contracts to verify signatures. This function calls the isValidSignature(bytes32,bytes) function on the smart contract wallet and checks if it returns the magic value 0x1626ba7e.

Args:

ctx: Context for cancellation and timeout control
signer: The facilitator signer that can perform contract calls
wallet: The smart contract wallet address (as hex string)
hash: The 32-byte message hash that was signed
signature: The signature bytes (format is wallet-specific)

Returns:

true if the contract returns the EIP-1271 magic value
error if the contract call fails or returns an invalid response

func VerifyEOASignature( hash []byte, signature []byte, expectedAddress common.Address, ) (bool, error)

Source: mechanisms/evm/verify_eoa.go:26

VerifyEOASignature verifies an ECDSA signature from an externally owned account (EOA)

This function uses secp256k1 public key recovery to verify that the signature was created by the expected address. It handles the Ethereum-specific v value adjustment (27/28 → 0/1 for recovery).

Args:

hash: The 32-byte message hash that was signed
signature: The 65-byte ECDSA signature (r: 32 bytes, s: 32 bytes, v: 1 byte)
expectedAddress: The Ethereum address that should have signed the message

Returns:

true if the signature is valid and recovers to the expected address
error if the signature is malformed or recovery fails

func VerifyEOATypedData( address string, domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}, signature []byte, ) (bool, error)

Source: mechanisms/evm/verify_strict.go:129

VerifyEOATypedData verifies an EIP-712 typed-data signature using pure ECDSA (no on-chain call). Use this for the payerAuthorizer path in batch-settlement where the on-chain contract also uses ECDSA.recoverCalldata - regardless of code presence at the address.

func VerifySignatureStrict( ctx context.Context, signer FacilitatorEvmSigner, address string, hash [32]byte, signature []byte, ) (bool, error)

Source: mechanisms/evm/verify_strict.go:23

VerifySignatureStrict verifies a raw 32-byte digest against an address using the same code-routing rule as on-chain SignatureChecker (Permit2, USDC v2.2, OpenZeppelin):

  • address has no bytecode → ecrecover (EOA path)
  • address has bytecode → IERC1271.isValidSignature (strict EIP-1271, no ECDSA fallback)

This prevents the pre-verify/on-chain divergence that arises when an ECDSA fallback accepts signatures that the on-chain verifier routes to EIP-1271 and rejects - most visibly for ERC-7702 delegated EOAs whose delegate does not accept raw owner ECDSA.

func VerifyTypedDataStrict( ctx context.Context, signer FacilitatorEvmSigner, address string, domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}, signature []byte, ) (bool, error)

Source: mechanisms/evm/verify_strict.go:109

VerifyTypedDataStrict verifies an EIP-712 typed-data signature using the strict code-routed primitive. Replaces signer.VerifyTypedData in facilitator code paths where the on-chain verifier routes by code.length (Permit2, USDC v2.2, OZ SignatureChecker).

func VerifyUniversalSignature( ctx context.Context, facilitatorSigner FacilitatorEvmSigner, signerAddress string, hash [32]byte, signature []byte, allowUndeployed bool, ) (bool, *ERC6492SignatureData, error)

Source: mechanisms/evm/verify_universal.go:40

VerifyUniversalSignature verifies signatures from EOA, EIP-1271, and ERC-6492 sources.

This function mirrors on-chain SignatureChecker semantics - routing is determined by code.length at the signer address, not by the byte-length of the signature. The old 65-byte EOA fast-path (that skipped GetCode) was removed because it caused pre-verify to accept signatures that on-chain verifiers routed to isValidSignature and rejected, most visibly for ERC-7702-delegated EOAs whose delegate rejects raw owner ECDSA.

The verification flow:

  1. Parse ERC-6492 wrapper if present to extract inner signature
  2. GetCode - always required; determines whether to use ECDSA or EIP-1271
  3. If undeployed + has deployment info + allowUndeployed: classify as counterfactual, do not treat as valid until a later onchain simulation succeeds
  4. If undeployed without deployment info: ECDSA fallback (covers plain EOAs)
  5. If deployed (any address with code, including ERC-7702): strict EIP-1271

Args:

ctx: Context for cancellation and timeout control
facilitatorSigner: The facilitator signer for blockchain interactions
signerAddress: The address that should have signed (hex string)
hash: The 32-byte message hash that was signed
signature: The signature bytes (may be wrapped in ERC-6492 format)
allowUndeployed: Whether to accept ERC-6492 signatures from undeployed wallets

Returns:

valid: true if the signature is valid
sigData: Parsed ERC-6492 data (if applicable)
error: Any error that occurred during verification

Types

type AssetInfo

Source: mechanisms/evm/types.go:300

AssetInfo contains information about an ERC20 token

type AssetInfo struct {
	Address             string
	Name                string
	Version             string
	Decimals            int
	AssetTransferMethod AssetTransferMethod
	SupportsEip2612     bool
}
Fields
  • Address string
  • Name string
  • Version string
  • Decimals int
  • AssetTransferMethod AssetTransferMethod
  • SupportsEip2612 bool

type AssetTransferMethod

Source: mechanisms/evm/types.go:38

AssetTransferMethod defines how assets are transferred on EVM chains. The choice affects which on-chain mechanism is used for token transfers:

  • eip3009: Uses transferWithAuthorization (USDC, etc.) - recommended for compatible tokens
  • permit2: Uses Permit2 + x402Permit2Proxy - universal fallback for any ERC-20
type AssetTransferMethod string

type BuilderCodeFacilitatorExtension

Source: mechanisms/evm/datasuffix.go:25

BuilderCodeFacilitatorExtension is implemented by the builder-code facilitator extension. BuildDataSuffix returns the encoded ERC-8021 suffix for the given settlement, or nil when there is nothing to attribute.

type BuilderCodeFacilitatorExtension interface {
	x402.FacilitatorExtension
	BuildDataSuffix(ctx DataSuffixContext) ([]byte, error)
}
Methods
  • x402.FacilitatorExtension
  • BuildDataSuffix func(ctx DataSuffixContext) ([]byte, error)

type ClientEvmSigner

Source: mechanisms/evm/types.go:235

ClientEvmSigner defines the minimal interface for client-side EVM signing operations.

Base payment signing only requires address + typed-data signing. Optional extension flows can use additional capability interfaces like ClientEvmSignerWithReadContract and ClientEvmSignerWithTxSigning.

type ClientEvmSigner interface {
	// Address returns the signer's Ethereum address
	Address() string

	// SignTypedData signs EIP-712 typed data
	SignTypedData(ctx context.Context, domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}) ([]byte, error)
}
Methods
  • Address func() string

    Address returns the signer's Ethereum address

  • SignTypedData func(ctx context.Context, domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}) ([]byte, error)

    SignTypedData signs EIP-712 typed data

type ClientEvmSignerWithEstimateFeesPerGas

Source: mechanisms/evm/types.go:214

ClientEvmSignerWithEstimateFeesPerGas extends ClientEvmSigner with fee estimation.

type ClientEvmSignerWithEstimateFeesPerGas interface {
	ClientEvmSigner

	// EstimateFeesPerGas returns the EIP-1559 maxFeePerGas and maxPriorityFeePerGas.
	EstimateFeesPerGas(ctx context.Context) (maxFeePerGas, maxPriorityFeePerGas *big.Int, err error)
}
Methods
  • ClientEvmSigner
  • EstimateFeesPerGas func(ctx context.Context) (maxFeePerGas, maxPriorityFeePerGas *big.Int, err error)

    EstimateFeesPerGas returns the EIP-1559 maxFeePerGas and maxPriorityFeePerGas.

type ClientEvmSignerWithGetTransactionCount

Source: mechanisms/evm/types.go:206

ClientEvmSignerWithGetTransactionCount extends ClientEvmSigner with nonce lookup.

type ClientEvmSignerWithGetTransactionCount interface {
	ClientEvmSigner

	// GetTransactionCount returns the pending nonce for an address.
	GetTransactionCount(ctx context.Context, address string) (uint64, error)
}
Methods
  • ClientEvmSigner
  • GetTransactionCount func(ctx context.Context, address string) (uint64, error)

    GetTransactionCount returns the pending nonce for an address.

type ClientEvmSignerWithReadContract

Source: mechanisms/evm/types.go:223

ClientEvmSignerWithReadContract extends ClientEvmSigner with on-chain read capability. Used by extension enrichment paths (EIP-2612 nonce lookup, allowance checks).

type ClientEvmSignerWithReadContract interface {
	ClientEvmSigner

	// ReadContract reads data from a smart contract.
	ReadContract(ctx context.Context, address string, abi []byte, functionName string, args ...interface{}) (interface{}, error)
}
Methods
  • ClientEvmSigner
  • ReadContract func(ctx context.Context, address string, abi []byte, functionName string, args ...interface{}) (interface{}, error)

    ReadContract reads data from a smart contract.

type ClientEvmSignerWithSignTransaction

Source: mechanisms/evm/types.go:198

ClientEvmSignerWithSignTransaction extends ClientEvmSigner with raw tx signing.

type ClientEvmSignerWithSignTransaction interface {
	ClientEvmSigner

	// SignTransaction signs an EIP-1559 transaction and returns the RLP-encoded bytes.
	SignTransaction(ctx context.Context, tx *goethtypes.Transaction) ([]byte, error)
}
Methods
  • ClientEvmSigner
  • SignTransaction func(ctx context.Context, tx *goethtypes.Transaction) ([]byte, error)

    SignTransaction signs an EIP-1559 transaction and returns the RLP-encoded bytes.

type ClientEvmSignerWithTxSigning

Source: mechanisms/evm/types.go:191

ClientEvmSignerWithTxSigning extends ClientEvmSigner with raw transaction signing capabilities. Required for the ERC-20 approval gas sponsoring extension, where the client signs (but does not broadcast) an approve(Permit2, MaxUint256) transaction.

type ClientEvmSignerWithTxSigning interface {
	ClientEvmSignerWithSignTransaction
	ClientEvmSignerWithGetTransactionCount
	ClientEvmSignerWithEstimateFeesPerGas
}
Methods
  • ClientEvmSignerWithSignTransaction
  • ClientEvmSignerWithGetTransactionCount
  • ClientEvmSignerWithEstimateFeesPerGas

type DataSuffixContext

Source: mechanisms/evm/datasuffix.go:17

DataSuffixContext carries the settlement payload and requirements a facilitator extension inspects when building an ERC-8021 calldata suffix.

type DataSuffixContext struct {
	Payload      types.PaymentPayload
	Requirements types.PaymentRequirements
}
Fields
  • Payload types.PaymentPayload
  • Requirements types.PaymentRequirements

type ERC6492SignatureData

Source: mechanisms/evm/types.go:529

ERC6492SignatureData represents the parsed components of an ERC-6492 signature ERC-6492 allows signatures from undeployed smart contract accounts by wrapping the signature with deployment information (factory address and calldata)

type ERC6492SignatureData struct {
	Factory         [20]byte // CREATE2 factory address (zero address if not ERC-6492)
	FactoryCalldata []byte   // Calldata to deploy the wallet (empty if not ERC-6492)
	InnerSignature  []byte   // The actual signature (EIP-1271 or EOA)
}
Fields
  • Factory [20]byte

    CREATE2 factory address (zero address if not ERC-6492)

  • FactoryCalldata []byte

    Calldata to deploy the wallet (empty if not ERC-6492)

  • InnerSignature []byte

    The actual signature (EIP-1271 or EOA)

type ExactEIP3009Authorization

Source: mechanisms/evm/types.go:12

ExactEIP3009Authorization represents the EIP-3009 TransferWithAuthorization data

type ExactEIP3009Authorization struct {
	From        string `json:"from"`        // Ethereum address (hex)
	To          string `json:"to"`          // Ethereum address (hex)
	Value       string `json:"value"`       // Amount in wei as string
	ValidAfter  string `json:"validAfter"`  // Unix timestamp as string
	ValidBefore string `json:"validBefore"` // Unix timestamp as string
	Nonce       string `json:"nonce"`       // 32-byte nonce as hex string
}
Fields
  • From string `json:"from"`

    Ethereum address (hex)

  • To string `json:"to"`

    Ethereum address (hex)

  • Value string `json:"value"`

    Amount in wei as string

  • ValidAfter string `json:"validAfter"`

    Unix timestamp as string

  • ValidBefore string `json:"validBefore"`

    Unix timestamp as string

  • Nonce string `json:"nonce"`

    32-byte nonce as hex string

type ExactEIP3009Payload

Source: mechanisms/evm/types.go:22

ExactEIP3009Payload represents the exact payment payload for EVM networks

type ExactEIP3009Payload struct {
	Signature     string                    `json:"signature,omitempty"`
	Authorization ExactEIP3009Authorization `json:"authorization"`
}
Fields
  • Signature string `json:"signature,omitempty"`
  • Authorization ExactEIP3009Authorization `json:"authorization"`

func ToMap() map[string]interface{}

Source: mechanisms/evm/types.go:317

PayloadToMap converts an ExactEIP3009Payload to a map for JSON marshaling

type ExactEvmPayloadV1

Source: mechanisms/evm/types.go:28

ExactEvmPayloadV1 is an alias for ExactEIP3009Payload (v1 compatibility)

type ExactEvmPayloadV1 = ExactEIP3009Payload

type ExactEvmPayloadV2

Source: mechanisms/evm/types.go:32

ExactEvmPayloadV2 is an alias for ExactEIP3009Payload (v2 compatibility) Note: V2 also supports ExactPermit2Payload - use IsPermit2Payload() to check

type ExactEvmPayloadV2 = ExactEIP3009Payload

type ExactPermit2Payload

Source: mechanisms/evm/types.go:75

ExactPermit2Payload represents the Permit2 payment payload sent by clients. This is the complete payment data including the EIP-712 signature.

type ExactPermit2Payload struct {
	Signature            string               `json:"signature"`            // EIP-712 signature (hex, 65 bytes for EOA)
	Permit2Authorization Permit2Authorization `json:"permit2Authorization"` // Authorization parameters that were signed
}
Fields
  • Signature string `json:"signature"`

    EIP-712 signature (hex, 65 bytes for EOA)

  • Permit2Authorization Permit2Authorization `json:"permit2Authorization"`

    Authorization parameters that were signed

func ToMap() map[string]interface{}

Source: mechanisms/evm/types.go:81

ToMap converts an ExactPermit2Payload to a map for JSON marshaling.

type FacilitatorEvmSigner

Source: mechanisms/evm/types.go:245

FacilitatorEvmSigner defines the interface for facilitator EVM operations Supports multiple addresses for load balancing, key rotation, and high availability

type FacilitatorEvmSigner interface {
	// GetAddresses returns all addresses this facilitator can use for signing
	// Enables dynamic address selection for load balancing and key rotation
	GetAddresses() []string

	// ReadContract reads data from a smart contract
	ReadContract(ctx context.Context, address string, abi []byte, functionName string, args ...interface{}) (interface{}, error)

	// VerifyTypedData verifies an EIP-712 signature
	VerifyTypedData(ctx context.Context, address string, domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}, signature []byte) (bool, error)

	// WriteContract executes a smart contract transaction
	WriteContract(ctx context.Context, address string, abi []byte, functionName string, dataSuffix []byte, args ...interface{}) (string, error)

	// SendTransaction sends a raw transaction with arbitrary calldata
	// Used for smart wallet deployment where calldata is pre-encoded
	SendTransaction(ctx context.Context, to string, data []byte) (string, error)

	// WaitForTransactionReceipt waits for a transaction to be mined
	WaitForTransactionReceipt(ctx context.Context, txHash string) (*TransactionReceipt, error)

	// GetBalance gets the balance of an address for a specific token
	GetBalance(ctx context.Context, address string, tokenAddress string) (*big.Int, error)

	// GetChainID returns the chain ID of the connected network
	GetChainID(ctx context.Context) (*big.Int, error)

	// GetCode returns the bytecode at the given address
	// Returns empty slice if address is an EOA or doesn't exist
	GetCode(ctx context.Context, address string) ([]byte, error)
}
Methods
  • GetAddresses func() []string

    GetAddresses returns all addresses this facilitator can use for signing Enables dynamic address selection for load balancing and key rotation

  • ReadContract func(ctx context.Context, address string, abi []byte, functionName string, args ...interface{}) (interface{}, error)

    ReadContract reads data from a smart contract

  • VerifyTypedData func(ctx context.Context, address string, domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}, signature []byte) (bool, error)

    VerifyTypedData verifies an EIP-712 signature

  • WriteContract func(ctx context.Context, address string, abi []byte, functionName string, dataSuffix []byte, args ...interface{}) (string, error)

    WriteContract executes a smart contract transaction

  • SendTransaction func(ctx context.Context, to string, data []byte) (string, error)

    SendTransaction sends a raw transaction with arbitrary calldata Used for smart wallet deployment where calldata is pre-encoded

  • WaitForTransactionReceipt func(ctx context.Context, txHash string) (*TransactionReceipt, error)

    WaitForTransactionReceipt waits for a transaction to be mined

  • GetBalance func(ctx context.Context, address string, tokenAddress string) (*big.Int, error)

    GetBalance gets the balance of an address for a specific token

  • GetChainID func(ctx context.Context) (*big.Int, error)

    GetChainID returns the chain ID of the connected network

  • GetCode func(ctx context.Context, address string) ([]byte, error)

    GetCode returns the bytecode at the given address Returns empty slice if address is an EOA or doesn't exist

type MulticallCall

Source: mechanisms/evm/multicall.go:15

MulticallCall describes one batched call. Use CallData for pre-encoded raw calls, or ABI/FunctionName/Args for typed calls.

type MulticallCall struct {
	Address      string
	ABI          []byte
	FunctionName string
	Args         []interface{}
	CallData     []byte
}
Fields
  • Address string
  • ABI []byte
  • FunctionName string
  • Args []interface{}
  • CallData []byte

type MulticallResult

Source: mechanisms/evm/multicall.go:24

MulticallResult is the decoded outcome of one batched call.

type MulticallResult struct {
	Status string
	Result interface{}
	Error  error
}
Fields
  • Status string
  • Result interface{}
  • Error error

func Success() bool

Source: mechanisms/evm/multicall.go:41

Success reports whether the call completed successfully.

type NetworkConfig

Source: mechanisms/evm/types.go:311

NetworkConfig contains network-specific configuration See DEFAULT_ASSETS.md for guidelines on adding new chains

type NetworkConfig struct {
	ChainID      *big.Int
	DefaultAsset AssetInfo
}
Fields
  • ChainID *big.Int
  • DefaultAsset AssetInfo

type Permit2Authorization

Source: mechanisms/evm/types.go:64

Permit2Authorization represents the Permit2 authorization parameters. This maps to the PermitWitnessTransferFrom struct used by the Permit2 contract.

type Permit2Authorization struct {
	From      string                  `json:"from"`      // Signer/owner address (hex)
	Permitted Permit2TokenPermissions `json:"permitted"` // Token and amount permitted
	Spender   string                  `json:"spender"`   // Must be x402Permit2Proxy address
	Nonce     string                  `json:"nonce"`     // uint256 nonce as decimal string (unique per signature)
	Deadline  string                  `json:"deadline"`  // Unix timestamp as decimal string - signature expires after this
	Witness   Permit2Witness          `json:"witness"`   // Witness data verified by x402Permit2Proxy
}
Fields
  • From string `json:"from"`

    Signer/owner address (hex)

  • Permitted Permit2TokenPermissions `json:"permitted"`

    Token and amount permitted

  • Spender string `json:"spender"`

    Must be x402Permit2Proxy address

  • Nonce string `json:"nonce"`

    uint256 nonce as decimal string (unique per signature)

  • Deadline string `json:"deadline"`

    Unix timestamp as decimal string - signature expires after this

  • Witness Permit2Witness `json:"witness"`

    Witness data verified by x402Permit2Proxy

type Permit2TokenPermissions

Source: mechanisms/evm/types.go:49

Permit2TokenPermissions represents the permitted token and amount for Permit2. This is part of the PermitWitnessTransferFrom message structure that gets signed.

type Permit2TokenPermissions struct {
	Token  string `json:"token"`  // Token contract address (hex, e.g., "0x036CbD53842c5426634e7929541eC2318f3dCF7e")
	Amount string `json:"amount"` // Amount in smallest unit as decimal string (e.g., "1000000" for 1 USDC)
}
Fields
  • Token string `json:"token"`

    Token contract address (hex, e.g., "0x036CbD53842c5426634e7929541eC2318f3dCF7e")

  • Amount string `json:"amount"`

    Amount in smallest unit as decimal string (e.g., "1000000" for 1 USDC)

type Permit2Witness

Source: mechanisms/evm/types.go:57

Permit2Witness represents the witness data structure for x402Permit2Proxy. The witness is included in the EIP-712 signature and verified on-chain by the proxy. Note: Upper time bound is enforced by Permit2's deadline field, not a witness field.

type Permit2Witness struct {
	To         string `json:"to"`         // Destination address for funds (hex)
	ValidAfter string `json:"validAfter"` // Unix timestamp (decimal string) - payment invalid before this time
}
Fields
  • To string `json:"to"`

    Destination address for funds (hex)

  • ValidAfter string `json:"validAfter"`

    Unix timestamp (decimal string) - payment invalid before this time

type RPCChainConfig

Source: mechanisms/evm/rpc.go:18

RPCChainConfig configures RPC behavior for a specific chain.

type RPCChainConfig struct {
	RPCURL string
}
Fields
  • RPCURL string

type RPCConfig

Source: mechanisms/evm/rpc.go:24

RPCConfig configures RPC behavior for EVM clients that need on-chain reads or fee estimation. Chain-specific entries in RPCByChainID take precedence over the top-level RPCURL.

type RPCConfig struct {
	RPCURL       string
	RPCByChainID map[int64]RPCChainConfig
}
Fields
  • RPCURL string
  • RPCByChainID map[int64]RPCChainConfig

type TransactionReceipt

Source: mechanisms/evm/types.go:292

TransactionReceipt represents the receipt of a mined transaction

type TransactionReceipt struct {
	Status      uint64            `json:"status"`
	BlockNumber uint64            `json:"blockNumber"`
	TxHash      string            `json:"transactionHash"`
	Logs        []*goethtypes.Log `json:"logs,omitempty"`
}
Fields
  • Status uint64 `json:"status"`
  • BlockNumber uint64 `json:"blockNumber"`
  • TxHash string `json:"transactionHash"`
  • Logs []*goethtypes.Log `json:"logs,omitempty"`

type TypedDataDomain

Source: mechanisms/evm/types.go:278

TypedDataDomain represents the EIP-712 domain separator

type TypedDataDomain struct {
	Name              string   `json:"name"`
	Version           string   `json:"version"`
	ChainID           *big.Int `json:"chainId"`
	VerifyingContract string   `json:"verifyingContract"`
}
Fields
  • Name string `json:"name"`
  • Version string `json:"version"`
  • ChainID *big.Int `json:"chainId"`
  • VerifyingContract string `json:"verifyingContract"`

type TypedDataField

Source: mechanisms/evm/types.go:286

TypedDataField represents a field in EIP-712 typed data

type TypedDataField struct {
	Name string `json:"name"`
	Type string `json:"type"`
}
Fields
  • Name string `json:"name"`
  • Type string `json:"type"`

type UptoPermit2Authorization

Source: mechanisms/evm/types.go:376

UptoPermit2Authorization represents the Permit2 authorization parameters for the upto scheme.

type UptoPermit2Authorization struct {
	From      string                  `json:"from"`      // Signer/owner address (hex)
	Permitted Permit2TokenPermissions `json:"permitted"` // Token and amount permitted (max charge)
	Spender   string                  `json:"spender"`   // Must be x402UptoPermit2Proxy address
	Nonce     string                  `json:"nonce"`     // uint256 nonce as decimal string
	Deadline  string                  `json:"deadline"`  // Unix timestamp as decimal string
	Witness   UptoPermit2Witness      `json:"witness"`   // Witness data including facilitator
}
Fields
  • From string `json:"from"`

    Signer/owner address (hex)

  • Permitted Permit2TokenPermissions `json:"permitted"`

    Token and amount permitted (max charge)

  • Spender string `json:"spender"`

    Must be x402UptoPermit2Proxy address

  • Nonce string `json:"nonce"`

    uint256 nonce as decimal string

  • Deadline string `json:"deadline"`

    Unix timestamp as decimal string

  • Witness UptoPermit2Witness `json:"witness"`

    Witness data including facilitator

type UptoPermit2Payload

Source: mechanisms/evm/types.go:386

UptoPermit2Payload represents the upto Permit2 payment payload sent by clients.

type UptoPermit2Payload struct {
	Signature            string                   `json:"signature"`            // EIP-712 signature (hex)
	Permit2Authorization UptoPermit2Authorization `json:"permit2Authorization"` // Authorization parameters
}
Fields
  • Signature string `json:"signature"`

    EIP-712 signature (hex)

  • Permit2Authorization UptoPermit2Authorization `json:"permit2Authorization"`

    Authorization parameters

func ToMap() map[string]interface{}

Source: mechanisms/evm/types.go:392

ToMap converts an UptoPermit2Payload to a map for JSON marshaling.

type UptoPermit2Witness

Source: mechanisms/evm/types.go:369

UptoPermit2Witness represents the witness data for x402UptoPermit2Proxy. Differs from Permit2Witness by including a Facilitator address field. Only the address matching Facilitator can call settle() on-chain.

type UptoPermit2Witness struct {
	To          string `json:"to"`          // Destination address for funds (hex)
	Facilitator string `json:"facilitator"` // Facilitator address authorized to settle (hex)
	ValidAfter  string `json:"validAfter"`  // Unix timestamp (decimal string)
}
Fields
  • To string `json:"to"`

    Destination address for funds (hex)

  • Facilitator string `json:"facilitator"`

    Facilitator address authorized to settle (hex)

  • ValidAfter string `json:"validAfter"`

    Unix timestamp (decimal string)