@x402/evm 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/exact/client/index.d.ts +2 -2
- package/dist/cjs/exact/client/index.js +265 -119
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +3 -0
- package/dist/cjs/exact/facilitator/index.js +692 -281
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.js +8 -1
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.js +44 -17
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.js +60 -26
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +458 -31
- package/dist/cjs/index.js +439 -63
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/permit2-BYv82va2.d.ts +103 -0
- package/dist/cjs/v1/index.d.ts +22 -1
- package/dist/cjs/v1/index.js +34 -29
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/chunk-E2YMUI3X.mjs +229 -0
- package/dist/esm/chunk-E2YMUI3X.mjs.map +1 -0
- package/dist/esm/chunk-PFULIQAE.mjs +13 -0
- package/dist/esm/chunk-PFULIQAE.mjs.map +1 -0
- package/dist/esm/chunk-RPL6OFJL.mjs +659 -0
- package/dist/esm/chunk-RPL6OFJL.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +2 -2
- package/dist/esm/exact/client/index.mjs +10 -30
- package/dist/esm/exact/client/index.mjs.map +1 -1
- package/dist/esm/exact/facilitator/index.d.mts +3 -0
- package/dist/esm/exact/facilitator/index.mjs +491 -241
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.mjs +8 -1
- package/dist/esm/exact/server/index.mjs.map +1 -1
- package/dist/esm/exact/v1/client/index.mjs +1 -2
- package/dist/esm/exact/v1/facilitator/index.mjs +2 -3
- package/dist/esm/index.d.mts +458 -31
- package/dist/esm/index.mjs +31 -4
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/permit2-BsAoJiWD.d.mts +103 -0
- package/dist/esm/v1/index.d.mts +22 -1
- package/dist/esm/v1/index.mjs +4 -6
- package/package.json +2 -2
- package/dist/esm/chunk-FOUXRQAV.mjs +0 -88
- package/dist/esm/chunk-FOUXRQAV.mjs.map +0 -1
- package/dist/esm/chunk-JYZWCLMP.mjs +0 -305
- package/dist/esm/chunk-JYZWCLMP.mjs.map +0 -1
- package/dist/esm/chunk-PSA4YVU2.mjs +0 -92
- package/dist/esm/chunk-PSA4YVU2.mjs.map +0 -1
- package/dist/esm/chunk-QLXM7BIB.mjs +0 -23
- package/dist/esm/chunk-QLXM7BIB.mjs.map +0 -1
- package/dist/esm/chunk-ZYXTTU74.mjs +0 -88
- package/dist/esm/chunk-ZYXTTU74.mjs.map +0 -1
|
@@ -25,7 +25,12 @@ __export(facilitator_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(facilitator_exports);
|
|
27
27
|
|
|
28
|
-
// src/
|
|
28
|
+
// src/types.ts
|
|
29
|
+
function isPermit2Payload(payload) {
|
|
30
|
+
return "permit2Authorization" in payload;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/exact/facilitator/eip3009.ts
|
|
29
34
|
var import_viem = require("viem");
|
|
30
35
|
|
|
31
36
|
// src/constants.ts
|
|
@@ -39,6 +44,24 @@ var authorizationTypes = {
|
|
|
39
44
|
{ name: "nonce", type: "bytes32" }
|
|
40
45
|
]
|
|
41
46
|
};
|
|
47
|
+
var permit2WitnessTypes = {
|
|
48
|
+
PermitWitnessTransferFrom: [
|
|
49
|
+
{ name: "permitted", type: "TokenPermissions" },
|
|
50
|
+
{ name: "spender", type: "address" },
|
|
51
|
+
{ name: "nonce", type: "uint256" },
|
|
52
|
+
{ name: "deadline", type: "uint256" },
|
|
53
|
+
{ name: "witness", type: "Witness" }
|
|
54
|
+
],
|
|
55
|
+
TokenPermissions: [
|
|
56
|
+
{ name: "token", type: "address" },
|
|
57
|
+
{ name: "amount", type: "uint256" }
|
|
58
|
+
],
|
|
59
|
+
Witness: [
|
|
60
|
+
{ name: "to", type: "address" },
|
|
61
|
+
{ name: "validAfter", type: "uint256" },
|
|
62
|
+
{ name: "extra", type: "bytes" }
|
|
63
|
+
]
|
|
64
|
+
};
|
|
42
65
|
var eip3009ABI = [
|
|
43
66
|
{
|
|
44
67
|
inputs: [
|
|
@@ -87,6 +110,602 @@ var eip3009ABI = [
|
|
|
87
110
|
type: "function"
|
|
88
111
|
}
|
|
89
112
|
];
|
|
113
|
+
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
114
|
+
var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001";
|
|
115
|
+
var x402ExactPermit2ProxyABI = [
|
|
116
|
+
{
|
|
117
|
+
type: "function",
|
|
118
|
+
name: "PERMIT2",
|
|
119
|
+
inputs: [],
|
|
120
|
+
outputs: [{ name: "", type: "address", internalType: "contract ISignatureTransfer" }],
|
|
121
|
+
stateMutability: "view"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
type: "function",
|
|
125
|
+
name: "WITNESS_TYPEHASH",
|
|
126
|
+
inputs: [],
|
|
127
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
128
|
+
stateMutability: "view"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: "function",
|
|
132
|
+
name: "WITNESS_TYPE_STRING",
|
|
133
|
+
inputs: [],
|
|
134
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
135
|
+
stateMutability: "view"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: "function",
|
|
139
|
+
name: "initialize",
|
|
140
|
+
inputs: [{ name: "_permit2", type: "address", internalType: "address" }],
|
|
141
|
+
outputs: [],
|
|
142
|
+
stateMutability: "nonpayable"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: "function",
|
|
146
|
+
name: "settle",
|
|
147
|
+
inputs: [
|
|
148
|
+
{
|
|
149
|
+
name: "permit",
|
|
150
|
+
type: "tuple",
|
|
151
|
+
internalType: "struct ISignatureTransfer.PermitTransferFrom",
|
|
152
|
+
components: [
|
|
153
|
+
{
|
|
154
|
+
name: "permitted",
|
|
155
|
+
type: "tuple",
|
|
156
|
+
internalType: "struct ISignatureTransfer.TokenPermissions",
|
|
157
|
+
components: [
|
|
158
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
159
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
{ name: "nonce", type: "uint256", internalType: "uint256" },
|
|
163
|
+
{ name: "deadline", type: "uint256", internalType: "uint256" }
|
|
164
|
+
]
|
|
165
|
+
},
|
|
166
|
+
{ name: "owner", type: "address", internalType: "address" },
|
|
167
|
+
{
|
|
168
|
+
name: "witness",
|
|
169
|
+
type: "tuple",
|
|
170
|
+
internalType: "struct x402BasePermit2Proxy.Witness",
|
|
171
|
+
components: [
|
|
172
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
173
|
+
{ name: "validAfter", type: "uint256", internalType: "uint256" },
|
|
174
|
+
{ name: "extra", type: "bytes", internalType: "bytes" }
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
178
|
+
],
|
|
179
|
+
outputs: [],
|
|
180
|
+
stateMutability: "nonpayable"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
type: "function",
|
|
184
|
+
name: "settleWithPermit",
|
|
185
|
+
inputs: [
|
|
186
|
+
{
|
|
187
|
+
name: "permit2612",
|
|
188
|
+
type: "tuple",
|
|
189
|
+
internalType: "struct x402BasePermit2Proxy.EIP2612Permit",
|
|
190
|
+
components: [
|
|
191
|
+
{ name: "value", type: "uint256", internalType: "uint256" },
|
|
192
|
+
{ name: "deadline", type: "uint256", internalType: "uint256" },
|
|
193
|
+
{ name: "r", type: "bytes32", internalType: "bytes32" },
|
|
194
|
+
{ name: "s", type: "bytes32", internalType: "bytes32" },
|
|
195
|
+
{ name: "v", type: "uint8", internalType: "uint8" }
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "permit",
|
|
200
|
+
type: "tuple",
|
|
201
|
+
internalType: "struct ISignatureTransfer.PermitTransferFrom",
|
|
202
|
+
components: [
|
|
203
|
+
{
|
|
204
|
+
name: "permitted",
|
|
205
|
+
type: "tuple",
|
|
206
|
+
internalType: "struct ISignatureTransfer.TokenPermissions",
|
|
207
|
+
components: [
|
|
208
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
209
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{ name: "nonce", type: "uint256", internalType: "uint256" },
|
|
213
|
+
{ name: "deadline", type: "uint256", internalType: "uint256" }
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
{ name: "owner", type: "address", internalType: "address" },
|
|
217
|
+
{
|
|
218
|
+
name: "witness",
|
|
219
|
+
type: "tuple",
|
|
220
|
+
internalType: "struct x402BasePermit2Proxy.Witness",
|
|
221
|
+
components: [
|
|
222
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
223
|
+
{ name: "validAfter", type: "uint256", internalType: "uint256" },
|
|
224
|
+
{ name: "extra", type: "bytes", internalType: "bytes" }
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
228
|
+
],
|
|
229
|
+
outputs: [],
|
|
230
|
+
stateMutability: "nonpayable"
|
|
231
|
+
},
|
|
232
|
+
{ type: "event", name: "Settled", inputs: [], anonymous: false },
|
|
233
|
+
{ type: "event", name: "SettledWithPermit", inputs: [], anonymous: false },
|
|
234
|
+
{ type: "error", name: "AlreadyInitialized", inputs: [] },
|
|
235
|
+
{ type: "error", name: "InvalidDestination", inputs: [] },
|
|
236
|
+
{ type: "error", name: "InvalidOwner", inputs: [] },
|
|
237
|
+
{ type: "error", name: "InvalidPermit2Address", inputs: [] },
|
|
238
|
+
{ type: "error", name: "PaymentTooEarly", inputs: [] },
|
|
239
|
+
{ type: "error", name: "ReentrancyGuardReentrantCall", inputs: [] }
|
|
240
|
+
];
|
|
241
|
+
|
|
242
|
+
// src/exact/facilitator/eip3009.ts
|
|
243
|
+
async function verifyEIP3009(signer, payload, requirements, eip3009Payload) {
|
|
244
|
+
const payer = eip3009Payload.authorization.from;
|
|
245
|
+
if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") {
|
|
246
|
+
return {
|
|
247
|
+
isValid: false,
|
|
248
|
+
invalidReason: "unsupported_scheme",
|
|
249
|
+
payer
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
253
|
+
return {
|
|
254
|
+
isValid: false,
|
|
255
|
+
invalidReason: "missing_eip712_domain",
|
|
256
|
+
payer
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const { name, version } = requirements.extra;
|
|
260
|
+
const erc20Address = (0, import_viem.getAddress)(requirements.asset);
|
|
261
|
+
if (payload.accepted.network !== requirements.network) {
|
|
262
|
+
return {
|
|
263
|
+
isValid: false,
|
|
264
|
+
invalidReason: "network_mismatch",
|
|
265
|
+
payer
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const permitTypedData = {
|
|
269
|
+
types: authorizationTypes,
|
|
270
|
+
primaryType: "TransferWithAuthorization",
|
|
271
|
+
domain: {
|
|
272
|
+
name,
|
|
273
|
+
version,
|
|
274
|
+
chainId: parseInt(requirements.network.split(":")[1]),
|
|
275
|
+
verifyingContract: erc20Address
|
|
276
|
+
},
|
|
277
|
+
message: {
|
|
278
|
+
from: eip3009Payload.authorization.from,
|
|
279
|
+
to: eip3009Payload.authorization.to,
|
|
280
|
+
value: BigInt(eip3009Payload.authorization.value),
|
|
281
|
+
validAfter: BigInt(eip3009Payload.authorization.validAfter),
|
|
282
|
+
validBefore: BigInt(eip3009Payload.authorization.validBefore),
|
|
283
|
+
nonce: eip3009Payload.authorization.nonce
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
try {
|
|
287
|
+
const recoveredAddress = await signer.verifyTypedData({
|
|
288
|
+
address: eip3009Payload.authorization.from,
|
|
289
|
+
...permitTypedData,
|
|
290
|
+
signature: eip3009Payload.signature
|
|
291
|
+
});
|
|
292
|
+
if (!recoveredAddress) {
|
|
293
|
+
return {
|
|
294
|
+
isValid: false,
|
|
295
|
+
invalidReason: "invalid_exact_evm_payload_signature",
|
|
296
|
+
payer
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
const signature = eip3009Payload.signature;
|
|
301
|
+
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
302
|
+
const isSmartWallet = signatureLength > 130;
|
|
303
|
+
if (isSmartWallet) {
|
|
304
|
+
const payerAddress = eip3009Payload.authorization.from;
|
|
305
|
+
const bytecode = await signer.getCode({ address: payerAddress });
|
|
306
|
+
if (!bytecode || bytecode === "0x") {
|
|
307
|
+
const erc6492Data = (0, import_viem.parseErc6492Signature)(signature);
|
|
308
|
+
const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000");
|
|
309
|
+
if (!hasDeploymentInfo) {
|
|
310
|
+
return {
|
|
311
|
+
isValid: false,
|
|
312
|
+
invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet",
|
|
313
|
+
payer: payerAddress
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
} else {
|
|
317
|
+
return {
|
|
318
|
+
isValid: false,
|
|
319
|
+
invalidReason: "invalid_exact_evm_payload_signature",
|
|
320
|
+
payer
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
return {
|
|
325
|
+
isValid: false,
|
|
326
|
+
invalidReason: "invalid_exact_evm_payload_signature",
|
|
327
|
+
payer
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if ((0, import_viem.getAddress)(eip3009Payload.authorization.to) !== (0, import_viem.getAddress)(requirements.payTo)) {
|
|
332
|
+
return {
|
|
333
|
+
isValid: false,
|
|
334
|
+
invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
|
|
335
|
+
payer
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
339
|
+
if (BigInt(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) {
|
|
340
|
+
return {
|
|
341
|
+
isValid: false,
|
|
342
|
+
invalidReason: "invalid_exact_evm_payload_authorization_valid_before",
|
|
343
|
+
payer
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) {
|
|
347
|
+
return {
|
|
348
|
+
isValid: false,
|
|
349
|
+
invalidReason: "invalid_exact_evm_payload_authorization_valid_after",
|
|
350
|
+
payer
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
const balance = await signer.readContract({
|
|
355
|
+
address: erc20Address,
|
|
356
|
+
abi: eip3009ABI,
|
|
357
|
+
functionName: "balanceOf",
|
|
358
|
+
args: [eip3009Payload.authorization.from]
|
|
359
|
+
});
|
|
360
|
+
if (BigInt(balance) < BigInt(requirements.amount)) {
|
|
361
|
+
return {
|
|
362
|
+
isValid: false,
|
|
363
|
+
invalidReason: "insufficient_funds",
|
|
364
|
+
invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,
|
|
365
|
+
payer
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
} catch {
|
|
369
|
+
}
|
|
370
|
+
if (BigInt(eip3009Payload.authorization.value) < BigInt(requirements.amount)) {
|
|
371
|
+
return {
|
|
372
|
+
isValid: false,
|
|
373
|
+
invalidReason: "invalid_exact_evm_payload_authorization_value",
|
|
374
|
+
payer
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
return {
|
|
378
|
+
isValid: true,
|
|
379
|
+
invalidReason: void 0,
|
|
380
|
+
payer
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
async function settleEIP3009(signer, payload, requirements, eip3009Payload, config) {
|
|
384
|
+
const payer = eip3009Payload.authorization.from;
|
|
385
|
+
const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload);
|
|
386
|
+
if (!valid.isValid) {
|
|
387
|
+
return {
|
|
388
|
+
success: false,
|
|
389
|
+
network: payload.accepted.network,
|
|
390
|
+
transaction: "",
|
|
391
|
+
errorReason: valid.invalidReason ?? "invalid_scheme",
|
|
392
|
+
payer
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
try {
|
|
396
|
+
const parseResult = (0, import_viem.parseErc6492Signature)(eip3009Payload.signature);
|
|
397
|
+
const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;
|
|
398
|
+
if (config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) {
|
|
399
|
+
const bytecode = await signer.getCode({ address: payer });
|
|
400
|
+
if (!bytecode || bytecode === "0x") {
|
|
401
|
+
const deployTx = await signer.sendTransaction({
|
|
402
|
+
to: factoryAddress,
|
|
403
|
+
data: factoryCalldata
|
|
404
|
+
});
|
|
405
|
+
await signer.waitForTransactionReceipt({ hash: deployTx });
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
409
|
+
const isECDSA = signatureLength === 130;
|
|
410
|
+
let tx;
|
|
411
|
+
if (isECDSA) {
|
|
412
|
+
const parsedSig = (0, import_viem.parseSignature)(signature);
|
|
413
|
+
tx = await signer.writeContract({
|
|
414
|
+
address: (0, import_viem.getAddress)(requirements.asset),
|
|
415
|
+
abi: eip3009ABI,
|
|
416
|
+
functionName: "transferWithAuthorization",
|
|
417
|
+
args: [
|
|
418
|
+
(0, import_viem.getAddress)(eip3009Payload.authorization.from),
|
|
419
|
+
(0, import_viem.getAddress)(eip3009Payload.authorization.to),
|
|
420
|
+
BigInt(eip3009Payload.authorization.value),
|
|
421
|
+
BigInt(eip3009Payload.authorization.validAfter),
|
|
422
|
+
BigInt(eip3009Payload.authorization.validBefore),
|
|
423
|
+
eip3009Payload.authorization.nonce,
|
|
424
|
+
parsedSig.v || parsedSig.yParity,
|
|
425
|
+
parsedSig.r,
|
|
426
|
+
parsedSig.s
|
|
427
|
+
]
|
|
428
|
+
});
|
|
429
|
+
} else {
|
|
430
|
+
tx = await signer.writeContract({
|
|
431
|
+
address: (0, import_viem.getAddress)(requirements.asset),
|
|
432
|
+
abi: eip3009ABI,
|
|
433
|
+
functionName: "transferWithAuthorization",
|
|
434
|
+
args: [
|
|
435
|
+
(0, import_viem.getAddress)(eip3009Payload.authorization.from),
|
|
436
|
+
(0, import_viem.getAddress)(eip3009Payload.authorization.to),
|
|
437
|
+
BigInt(eip3009Payload.authorization.value),
|
|
438
|
+
BigInt(eip3009Payload.authorization.validAfter),
|
|
439
|
+
BigInt(eip3009Payload.authorization.validBefore),
|
|
440
|
+
eip3009Payload.authorization.nonce,
|
|
441
|
+
signature
|
|
442
|
+
]
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
const receipt = await signer.waitForTransactionReceipt({ hash: tx });
|
|
446
|
+
if (receipt.status !== "success") {
|
|
447
|
+
return {
|
|
448
|
+
success: false,
|
|
449
|
+
errorReason: "invalid_transaction_state",
|
|
450
|
+
transaction: tx,
|
|
451
|
+
network: payload.accepted.network,
|
|
452
|
+
payer
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
success: true,
|
|
457
|
+
transaction: tx,
|
|
458
|
+
network: payload.accepted.network,
|
|
459
|
+
payer
|
|
460
|
+
};
|
|
461
|
+
} catch {
|
|
462
|
+
return {
|
|
463
|
+
success: false,
|
|
464
|
+
errorReason: "transaction_failed",
|
|
465
|
+
transaction: "",
|
|
466
|
+
network: payload.accepted.network,
|
|
467
|
+
payer
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// src/exact/facilitator/permit2.ts
|
|
473
|
+
var import_viem2 = require("viem");
|
|
474
|
+
var erc20AllowanceABI = [
|
|
475
|
+
{
|
|
476
|
+
type: "function",
|
|
477
|
+
name: "allowance",
|
|
478
|
+
inputs: [
|
|
479
|
+
{ name: "owner", type: "address" },
|
|
480
|
+
{ name: "spender", type: "address" }
|
|
481
|
+
],
|
|
482
|
+
outputs: [{ type: "uint256" }],
|
|
483
|
+
stateMutability: "view"
|
|
484
|
+
}
|
|
485
|
+
];
|
|
486
|
+
async function verifyPermit2(signer, payload, requirements, permit2Payload) {
|
|
487
|
+
const payer = permit2Payload.permit2Authorization.from;
|
|
488
|
+
if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") {
|
|
489
|
+
return {
|
|
490
|
+
isValid: false,
|
|
491
|
+
invalidReason: "unsupported_scheme",
|
|
492
|
+
payer
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
if (payload.accepted.network !== requirements.network) {
|
|
496
|
+
return {
|
|
497
|
+
isValid: false,
|
|
498
|
+
invalidReason: "network_mismatch",
|
|
499
|
+
payer
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
const chainId = parseInt(requirements.network.split(":")[1]);
|
|
503
|
+
const tokenAddress = (0, import_viem2.getAddress)(requirements.asset);
|
|
504
|
+
if ((0, import_viem2.getAddress)(permit2Payload.permit2Authorization.spender) !== (0, import_viem2.getAddress)(x402ExactPermit2ProxyAddress)) {
|
|
505
|
+
return {
|
|
506
|
+
isValid: false,
|
|
507
|
+
invalidReason: "invalid_permit2_spender",
|
|
508
|
+
payer
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
if ((0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to) !== (0, import_viem2.getAddress)(requirements.payTo)) {
|
|
512
|
+
return {
|
|
513
|
+
isValid: false,
|
|
514
|
+
invalidReason: "invalid_permit2_recipient_mismatch",
|
|
515
|
+
payer
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
519
|
+
if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) {
|
|
520
|
+
return {
|
|
521
|
+
isValid: false,
|
|
522
|
+
invalidReason: "permit2_deadline_expired",
|
|
523
|
+
payer
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) {
|
|
527
|
+
return {
|
|
528
|
+
isValid: false,
|
|
529
|
+
invalidReason: "permit2_not_yet_valid",
|
|
530
|
+
payer
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
if (BigInt(permit2Payload.permit2Authorization.permitted.amount) < BigInt(requirements.amount)) {
|
|
534
|
+
return {
|
|
535
|
+
isValid: false,
|
|
536
|
+
invalidReason: "permit2_insufficient_amount",
|
|
537
|
+
payer
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
if ((0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {
|
|
541
|
+
return {
|
|
542
|
+
isValid: false,
|
|
543
|
+
invalidReason: "permit2_token_mismatch",
|
|
544
|
+
payer
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
const permit2TypedData = {
|
|
548
|
+
types: permit2WitnessTypes,
|
|
549
|
+
primaryType: "PermitWitnessTransferFrom",
|
|
550
|
+
domain: {
|
|
551
|
+
name: "Permit2",
|
|
552
|
+
chainId,
|
|
553
|
+
verifyingContract: PERMIT2_ADDRESS
|
|
554
|
+
},
|
|
555
|
+
message: {
|
|
556
|
+
permitted: {
|
|
557
|
+
token: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token),
|
|
558
|
+
amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
|
|
559
|
+
},
|
|
560
|
+
spender: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.spender),
|
|
561
|
+
nonce: BigInt(permit2Payload.permit2Authorization.nonce),
|
|
562
|
+
deadline: BigInt(permit2Payload.permit2Authorization.deadline),
|
|
563
|
+
witness: {
|
|
564
|
+
to: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to),
|
|
565
|
+
validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),
|
|
566
|
+
extra: permit2Payload.permit2Authorization.witness.extra
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
try {
|
|
571
|
+
const isValid = await signer.verifyTypedData({
|
|
572
|
+
address: payer,
|
|
573
|
+
...permit2TypedData,
|
|
574
|
+
signature: permit2Payload.signature
|
|
575
|
+
});
|
|
576
|
+
if (!isValid) {
|
|
577
|
+
return {
|
|
578
|
+
isValid: false,
|
|
579
|
+
invalidReason: "invalid_permit2_signature",
|
|
580
|
+
payer
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
} catch {
|
|
584
|
+
return {
|
|
585
|
+
isValid: false,
|
|
586
|
+
invalidReason: "invalid_permit2_signature",
|
|
587
|
+
payer
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
try {
|
|
591
|
+
const allowance = await signer.readContract({
|
|
592
|
+
address: tokenAddress,
|
|
593
|
+
abi: erc20AllowanceABI,
|
|
594
|
+
functionName: "allowance",
|
|
595
|
+
args: [payer, PERMIT2_ADDRESS]
|
|
596
|
+
});
|
|
597
|
+
if (allowance < BigInt(requirements.amount)) {
|
|
598
|
+
return {
|
|
599
|
+
isValid: false,
|
|
600
|
+
invalidReason: "permit2_allowance_required",
|
|
601
|
+
payer
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
} catch {
|
|
605
|
+
}
|
|
606
|
+
try {
|
|
607
|
+
const balance = await signer.readContract({
|
|
608
|
+
address: tokenAddress,
|
|
609
|
+
abi: eip3009ABI,
|
|
610
|
+
functionName: "balanceOf",
|
|
611
|
+
args: [payer]
|
|
612
|
+
});
|
|
613
|
+
if (balance < BigInt(requirements.amount)) {
|
|
614
|
+
return {
|
|
615
|
+
isValid: false,
|
|
616
|
+
invalidReason: "insufficient_funds",
|
|
617
|
+
invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,
|
|
618
|
+
payer
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
} catch {
|
|
622
|
+
}
|
|
623
|
+
return {
|
|
624
|
+
isValid: true,
|
|
625
|
+
invalidReason: void 0,
|
|
626
|
+
payer
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
async function settlePermit2(signer, payload, requirements, permit2Payload) {
|
|
630
|
+
const payer = permit2Payload.permit2Authorization.from;
|
|
631
|
+
const valid = await verifyPermit2(signer, payload, requirements, permit2Payload);
|
|
632
|
+
if (!valid.isValid) {
|
|
633
|
+
return {
|
|
634
|
+
success: false,
|
|
635
|
+
network: payload.accepted.network,
|
|
636
|
+
transaction: "",
|
|
637
|
+
errorReason: valid.invalidReason ?? "invalid_scheme",
|
|
638
|
+
payer
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
const tx = await signer.writeContract({
|
|
643
|
+
address: x402ExactPermit2ProxyAddress,
|
|
644
|
+
abi: x402ExactPermit2ProxyABI,
|
|
645
|
+
functionName: "settle",
|
|
646
|
+
args: [
|
|
647
|
+
{
|
|
648
|
+
permitted: {
|
|
649
|
+
token: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token),
|
|
650
|
+
amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
|
|
651
|
+
},
|
|
652
|
+
nonce: BigInt(permit2Payload.permit2Authorization.nonce),
|
|
653
|
+
deadline: BigInt(permit2Payload.permit2Authorization.deadline)
|
|
654
|
+
},
|
|
655
|
+
(0, import_viem2.getAddress)(payer),
|
|
656
|
+
{
|
|
657
|
+
to: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to),
|
|
658
|
+
validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),
|
|
659
|
+
extra: permit2Payload.permit2Authorization.witness.extra
|
|
660
|
+
},
|
|
661
|
+
permit2Payload.signature
|
|
662
|
+
]
|
|
663
|
+
});
|
|
664
|
+
const receipt = await signer.waitForTransactionReceipt({ hash: tx });
|
|
665
|
+
if (receipt.status !== "success") {
|
|
666
|
+
return {
|
|
667
|
+
success: false,
|
|
668
|
+
errorReason: "invalid_transaction_state",
|
|
669
|
+
transaction: tx,
|
|
670
|
+
network: payload.accepted.network,
|
|
671
|
+
payer
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
return {
|
|
675
|
+
success: true,
|
|
676
|
+
transaction: tx,
|
|
677
|
+
network: payload.accepted.network,
|
|
678
|
+
payer
|
|
679
|
+
};
|
|
680
|
+
} catch (error) {
|
|
681
|
+
let errorReason = "transaction_failed";
|
|
682
|
+
if (error instanceof Error) {
|
|
683
|
+
const message = error.message;
|
|
684
|
+
if (message.includes("AmountExceedsPermitted")) {
|
|
685
|
+
errorReason = "permit2_amount_exceeds_permitted";
|
|
686
|
+
} else if (message.includes("InvalidDestination")) {
|
|
687
|
+
errorReason = "permit2_invalid_destination";
|
|
688
|
+
} else if (message.includes("InvalidOwner")) {
|
|
689
|
+
errorReason = "permit2_invalid_owner";
|
|
690
|
+
} else if (message.includes("PaymentTooEarly")) {
|
|
691
|
+
errorReason = "permit2_payment_too_early";
|
|
692
|
+
} else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) {
|
|
693
|
+
errorReason = "permit2_invalid_signature";
|
|
694
|
+
} else if (message.includes("InvalidNonce")) {
|
|
695
|
+
errorReason = "permit2_invalid_nonce";
|
|
696
|
+
} else {
|
|
697
|
+
errorReason = `transaction_failed: ${message.slice(0, 500)}`;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
return {
|
|
701
|
+
success: false,
|
|
702
|
+
errorReason,
|
|
703
|
+
transaction: "",
|
|
704
|
+
network: payload.accepted.network,
|
|
705
|
+
payer
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
}
|
|
90
709
|
|
|
91
710
|
// src/exact/facilitator/scheme.ts
|
|
92
711
|
var ExactEvmScheme = class {
|
|
@@ -126,277 +745,81 @@ var ExactEvmScheme = class {
|
|
|
126
745
|
}
|
|
127
746
|
/**
|
|
128
747
|
* Verifies a payment payload.
|
|
748
|
+
* Routes to the appropriate verification logic based on payload type.
|
|
129
749
|
*
|
|
130
750
|
* @param payload - The payment payload to verify
|
|
131
751
|
* @param requirements - The payment requirements
|
|
132
752
|
* @returns Promise resolving to verification response
|
|
133
753
|
*/
|
|
134
754
|
async verify(payload, requirements) {
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
137
|
-
return
|
|
138
|
-
isValid: false,
|
|
139
|
-
invalidReason: "unsupported_scheme",
|
|
140
|
-
payer: exactEvmPayload.authorization.from
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
144
|
-
return {
|
|
145
|
-
isValid: false,
|
|
146
|
-
invalidReason: "missing_eip712_domain",
|
|
147
|
-
payer: exactEvmPayload.authorization.from
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
const { name, version } = requirements.extra;
|
|
151
|
-
const erc20Address = (0, import_viem.getAddress)(requirements.asset);
|
|
152
|
-
if (payload.accepted.network !== requirements.network) {
|
|
153
|
-
return {
|
|
154
|
-
isValid: false,
|
|
155
|
-
invalidReason: "network_mismatch",
|
|
156
|
-
payer: exactEvmPayload.authorization.from
|
|
157
|
-
};
|
|
755
|
+
const rawPayload = payload.payload;
|
|
756
|
+
if (isPermit2Payload(rawPayload)) {
|
|
757
|
+
return verifyPermit2(this.signer, payload, requirements, rawPayload);
|
|
158
758
|
}
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
primaryType: "TransferWithAuthorization",
|
|
162
|
-
domain: {
|
|
163
|
-
name,
|
|
164
|
-
version,
|
|
165
|
-
chainId: parseInt(requirements.network.split(":")[1]),
|
|
166
|
-
verifyingContract: erc20Address
|
|
167
|
-
},
|
|
168
|
-
message: {
|
|
169
|
-
from: exactEvmPayload.authorization.from,
|
|
170
|
-
to: exactEvmPayload.authorization.to,
|
|
171
|
-
value: BigInt(exactEvmPayload.authorization.value),
|
|
172
|
-
validAfter: BigInt(exactEvmPayload.authorization.validAfter),
|
|
173
|
-
validBefore: BigInt(exactEvmPayload.authorization.validBefore),
|
|
174
|
-
nonce: exactEvmPayload.authorization.nonce
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
try {
|
|
178
|
-
const recoveredAddress = await this.signer.verifyTypedData({
|
|
179
|
-
address: exactEvmPayload.authorization.from,
|
|
180
|
-
...permitTypedData,
|
|
181
|
-
signature: exactEvmPayload.signature
|
|
182
|
-
});
|
|
183
|
-
if (!recoveredAddress) {
|
|
184
|
-
return {
|
|
185
|
-
isValid: false,
|
|
186
|
-
invalidReason: "invalid_exact_evm_payload_signature",
|
|
187
|
-
payer: exactEvmPayload.authorization.from
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
} catch {
|
|
191
|
-
const signature = exactEvmPayload.signature;
|
|
192
|
-
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
193
|
-
const isSmartWallet = signatureLength > 130;
|
|
194
|
-
if (isSmartWallet) {
|
|
195
|
-
const payerAddress = exactEvmPayload.authorization.from;
|
|
196
|
-
const bytecode = await this.signer.getCode({ address: payerAddress });
|
|
197
|
-
if (!bytecode || bytecode === "0x") {
|
|
198
|
-
const erc6492Data = (0, import_viem.parseErc6492Signature)(signature);
|
|
199
|
-
const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000");
|
|
200
|
-
if (!hasDeploymentInfo) {
|
|
201
|
-
return {
|
|
202
|
-
isValid: false,
|
|
203
|
-
invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet",
|
|
204
|
-
payer: payerAddress
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
} else {
|
|
208
|
-
return {
|
|
209
|
-
isValid: false,
|
|
210
|
-
invalidReason: "invalid_exact_evm_payload_signature",
|
|
211
|
-
payer: exactEvmPayload.authorization.from
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
} else {
|
|
215
|
-
return {
|
|
216
|
-
isValid: false,
|
|
217
|
-
invalidReason: "invalid_exact_evm_payload_signature",
|
|
218
|
-
payer: exactEvmPayload.authorization.from
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if ((0, import_viem.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem.getAddress)(requirements.payTo)) {
|
|
223
|
-
return {
|
|
224
|
-
isValid: false,
|
|
225
|
-
invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
|
|
226
|
-
payer: exactEvmPayload.authorization.from
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
230
|
-
if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {
|
|
231
|
-
return {
|
|
232
|
-
isValid: false,
|
|
233
|
-
invalidReason: "invalid_exact_evm_payload_authorization_valid_before",
|
|
234
|
-
payer: exactEvmPayload.authorization.from
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {
|
|
238
|
-
return {
|
|
239
|
-
isValid: false,
|
|
240
|
-
invalidReason: "invalid_exact_evm_payload_authorization_valid_after",
|
|
241
|
-
payer: exactEvmPayload.authorization.from
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
try {
|
|
245
|
-
const balance = await this.signer.readContract({
|
|
246
|
-
address: erc20Address,
|
|
247
|
-
abi: eip3009ABI,
|
|
248
|
-
functionName: "balanceOf",
|
|
249
|
-
args: [exactEvmPayload.authorization.from]
|
|
250
|
-
});
|
|
251
|
-
if (BigInt(balance) < BigInt(requirements.amount)) {
|
|
252
|
-
return {
|
|
253
|
-
isValid: false,
|
|
254
|
-
invalidReason: "insufficient_funds",
|
|
255
|
-
payer: exactEvmPayload.authorization.from
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
} catch {
|
|
259
|
-
}
|
|
260
|
-
if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirements.amount)) {
|
|
261
|
-
return {
|
|
262
|
-
isValid: false,
|
|
263
|
-
invalidReason: "invalid_exact_evm_payload_authorization_value",
|
|
264
|
-
payer: exactEvmPayload.authorization.from
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
return {
|
|
268
|
-
isValid: true,
|
|
269
|
-
invalidReason: void 0,
|
|
270
|
-
payer: exactEvmPayload.authorization.from
|
|
271
|
-
};
|
|
759
|
+
const eip3009Payload = rawPayload;
|
|
760
|
+
return verifyEIP3009(this.signer, payload, requirements, eip3009Payload);
|
|
272
761
|
}
|
|
273
762
|
/**
|
|
274
763
|
* Settles a payment by executing the transfer.
|
|
764
|
+
* Routes to the appropriate settlement logic based on payload type.
|
|
275
765
|
*
|
|
276
766
|
* @param payload - The payment payload to settle
|
|
277
767
|
* @param requirements - The payment requirements
|
|
278
768
|
* @returns Promise resolving to settlement response
|
|
279
769
|
*/
|
|
280
770
|
async settle(payload, requirements) {
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return {
|
|
285
|
-
success: false,
|
|
286
|
-
network: payload.accepted.network,
|
|
287
|
-
transaction: "",
|
|
288
|
-
errorReason: valid.invalidReason ?? "invalid_scheme",
|
|
289
|
-
payer: exactEvmPayload.authorization.from
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
try {
|
|
293
|
-
const parseResult = (0, import_viem.parseErc6492Signature)(exactEvmPayload.signature);
|
|
294
|
-
const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;
|
|
295
|
-
if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) {
|
|
296
|
-
const payerAddress = exactEvmPayload.authorization.from;
|
|
297
|
-
const bytecode = await this.signer.getCode({ address: payerAddress });
|
|
298
|
-
if (!bytecode || bytecode === "0x") {
|
|
299
|
-
try {
|
|
300
|
-
console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);
|
|
301
|
-
const deployTx = await this.signer.sendTransaction({
|
|
302
|
-
to: factoryAddress,
|
|
303
|
-
data: factoryCalldata
|
|
304
|
-
});
|
|
305
|
-
await this.signer.waitForTransactionReceipt({ hash: deployTx });
|
|
306
|
-
console.log(`Successfully deployed smart wallet for ${payerAddress}`);
|
|
307
|
-
} catch (deployError) {
|
|
308
|
-
console.error("Smart wallet deployment failed:", deployError);
|
|
309
|
-
throw deployError;
|
|
310
|
-
}
|
|
311
|
-
} else {
|
|
312
|
-
console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
316
|
-
const isECDSA = signatureLength === 130;
|
|
317
|
-
let tx;
|
|
318
|
-
if (isECDSA) {
|
|
319
|
-
const parsedSig = (0, import_viem.parseSignature)(signature);
|
|
320
|
-
tx = await this.signer.writeContract({
|
|
321
|
-
address: (0, import_viem.getAddress)(requirements.asset),
|
|
322
|
-
abi: eip3009ABI,
|
|
323
|
-
functionName: "transferWithAuthorization",
|
|
324
|
-
args: [
|
|
325
|
-
(0, import_viem.getAddress)(exactEvmPayload.authorization.from),
|
|
326
|
-
(0, import_viem.getAddress)(exactEvmPayload.authorization.to),
|
|
327
|
-
BigInt(exactEvmPayload.authorization.value),
|
|
328
|
-
BigInt(exactEvmPayload.authorization.validAfter),
|
|
329
|
-
BigInt(exactEvmPayload.authorization.validBefore),
|
|
330
|
-
exactEvmPayload.authorization.nonce,
|
|
331
|
-
parsedSig.v || parsedSig.yParity,
|
|
332
|
-
parsedSig.r,
|
|
333
|
-
parsedSig.s
|
|
334
|
-
]
|
|
335
|
-
});
|
|
336
|
-
} else {
|
|
337
|
-
tx = await this.signer.writeContract({
|
|
338
|
-
address: (0, import_viem.getAddress)(requirements.asset),
|
|
339
|
-
abi: eip3009ABI,
|
|
340
|
-
functionName: "transferWithAuthorization",
|
|
341
|
-
args: [
|
|
342
|
-
(0, import_viem.getAddress)(exactEvmPayload.authorization.from),
|
|
343
|
-
(0, import_viem.getAddress)(exactEvmPayload.authorization.to),
|
|
344
|
-
BigInt(exactEvmPayload.authorization.value),
|
|
345
|
-
BigInt(exactEvmPayload.authorization.validAfter),
|
|
346
|
-
BigInt(exactEvmPayload.authorization.validBefore),
|
|
347
|
-
exactEvmPayload.authorization.nonce,
|
|
348
|
-
signature
|
|
349
|
-
]
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
|
|
353
|
-
if (receipt.status !== "success") {
|
|
354
|
-
return {
|
|
355
|
-
success: false,
|
|
356
|
-
errorReason: "invalid_transaction_state",
|
|
357
|
-
transaction: tx,
|
|
358
|
-
network: payload.accepted.network,
|
|
359
|
-
payer: exactEvmPayload.authorization.from
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
return {
|
|
363
|
-
success: true,
|
|
364
|
-
transaction: tx,
|
|
365
|
-
network: payload.accepted.network,
|
|
366
|
-
payer: exactEvmPayload.authorization.from
|
|
367
|
-
};
|
|
368
|
-
} catch (error) {
|
|
369
|
-
console.error("Failed to settle transaction:", error);
|
|
370
|
-
return {
|
|
371
|
-
success: false,
|
|
372
|
-
errorReason: "transaction_failed",
|
|
373
|
-
transaction: "",
|
|
374
|
-
network: payload.accepted.network,
|
|
375
|
-
payer: exactEvmPayload.authorization.from
|
|
376
|
-
};
|
|
771
|
+
const rawPayload = payload.payload;
|
|
772
|
+
if (isPermit2Payload(rawPayload)) {
|
|
773
|
+
return settlePermit2(this.signer, payload, requirements, rawPayload);
|
|
377
774
|
}
|
|
775
|
+
const eip3009Payload = rawPayload;
|
|
776
|
+
return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config);
|
|
378
777
|
}
|
|
379
778
|
};
|
|
380
779
|
|
|
381
780
|
// src/exact/v1/facilitator/scheme.ts
|
|
781
|
+
var import_viem5 = require("viem");
|
|
782
|
+
|
|
783
|
+
// src/utils.ts
|
|
784
|
+
var import_viem4 = require("viem");
|
|
785
|
+
|
|
786
|
+
// src/exact/v1/client/scheme.ts
|
|
382
787
|
var import_viem3 = require("viem");
|
|
383
788
|
|
|
789
|
+
// src/v1/index.ts
|
|
790
|
+
var EVM_NETWORK_CHAIN_ID_MAP = {
|
|
791
|
+
ethereum: 1,
|
|
792
|
+
sepolia: 11155111,
|
|
793
|
+
abstract: 2741,
|
|
794
|
+
"abstract-testnet": 11124,
|
|
795
|
+
"base-sepolia": 84532,
|
|
796
|
+
base: 8453,
|
|
797
|
+
"avalanche-fuji": 43113,
|
|
798
|
+
avalanche: 43114,
|
|
799
|
+
iotex: 4689,
|
|
800
|
+
sei: 1329,
|
|
801
|
+
"sei-testnet": 1328,
|
|
802
|
+
polygon: 137,
|
|
803
|
+
"polygon-amoy": 80002,
|
|
804
|
+
peaq: 3338,
|
|
805
|
+
story: 1514,
|
|
806
|
+
educhain: 41923,
|
|
807
|
+
"skale-base-sepolia": 324705682,
|
|
808
|
+
megaeth: 4326
|
|
809
|
+
};
|
|
810
|
+
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
811
|
+
|
|
384
812
|
// src/utils.ts
|
|
385
|
-
var import_viem2 = require("viem");
|
|
386
813
|
function getEvmChainId(network) {
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
polygon: 137,
|
|
393
|
-
"polygon-amoy": 80002
|
|
394
|
-
};
|
|
395
|
-
return networkMap[network] || 1;
|
|
814
|
+
const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
|
|
815
|
+
if (!chainId) {
|
|
816
|
+
throw new Error(`Unsupported network: ${network}`);
|
|
817
|
+
}
|
|
818
|
+
return chainId;
|
|
396
819
|
}
|
|
397
820
|
|
|
398
821
|
// src/exact/v1/facilitator/scheme.ts
|
|
399
|
-
var
|
|
822
|
+
var ExactEvmSchemeV12 = class {
|
|
400
823
|
/**
|
|
401
824
|
* Creates a new ExactEvmFacilitatorV1 instance.
|
|
402
825
|
*
|
|
@@ -449,7 +872,16 @@ var ExactEvmSchemeV1 = class {
|
|
|
449
872
|
payer: exactEvmPayload.authorization.from
|
|
450
873
|
};
|
|
451
874
|
}
|
|
452
|
-
|
|
875
|
+
let chainId;
|
|
876
|
+
try {
|
|
877
|
+
chainId = getEvmChainId(payloadV1.network);
|
|
878
|
+
} catch {
|
|
879
|
+
return {
|
|
880
|
+
isValid: false,
|
|
881
|
+
invalidReason: `invalid_network`,
|
|
882
|
+
payer: exactEvmPayload.authorization.from
|
|
883
|
+
};
|
|
884
|
+
}
|
|
453
885
|
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
454
886
|
return {
|
|
455
887
|
isValid: false,
|
|
@@ -458,7 +890,7 @@ var ExactEvmSchemeV1 = class {
|
|
|
458
890
|
};
|
|
459
891
|
}
|
|
460
892
|
const { name, version } = requirements.extra;
|
|
461
|
-
const erc20Address = (0,
|
|
893
|
+
const erc20Address = (0, import_viem5.getAddress)(requirements.asset);
|
|
462
894
|
if (payloadV1.network !== requirements.network) {
|
|
463
895
|
return {
|
|
464
896
|
isValid: false,
|
|
@@ -505,8 +937,8 @@ var ExactEvmSchemeV1 = class {
|
|
|
505
937
|
const payerAddress = exactEvmPayload.authorization.from;
|
|
506
938
|
const bytecode = await this.signer.getCode({ address: payerAddress });
|
|
507
939
|
if (!bytecode || bytecode === "0x") {
|
|
508
|
-
const erc6492Data = (0,
|
|
509
|
-
const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0,
|
|
940
|
+
const erc6492Data = (0, import_viem5.parseErc6492Signature)(signature);
|
|
941
|
+
const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem5.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000");
|
|
510
942
|
if (!hasDeploymentInfo) {
|
|
511
943
|
return {
|
|
512
944
|
isValid: false,
|
|
@@ -529,7 +961,7 @@ var ExactEvmSchemeV1 = class {
|
|
|
529
961
|
};
|
|
530
962
|
}
|
|
531
963
|
}
|
|
532
|
-
if ((0,
|
|
964
|
+
if ((0, import_viem5.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem5.getAddress)(requirements.payTo)) {
|
|
533
965
|
return {
|
|
534
966
|
isValid: false,
|
|
535
967
|
invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
|
|
@@ -562,6 +994,7 @@ var ExactEvmSchemeV1 = class {
|
|
|
562
994
|
return {
|
|
563
995
|
isValid: false,
|
|
564
996
|
invalidReason: "insufficient_funds",
|
|
997
|
+
invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,
|
|
565
998
|
payer: exactEvmPayload.authorization.from
|
|
566
999
|
};
|
|
567
1000
|
}
|
|
@@ -601,9 +1034,9 @@ var ExactEvmSchemeV1 = class {
|
|
|
601
1034
|
};
|
|
602
1035
|
}
|
|
603
1036
|
try {
|
|
604
|
-
const parseResult = (0,
|
|
1037
|
+
const parseResult = (0, import_viem5.parseErc6492Signature)(exactEvmPayload.signature);
|
|
605
1038
|
const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;
|
|
606
|
-
if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0,
|
|
1039
|
+
if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem5.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) {
|
|
607
1040
|
const payerAddress = exactEvmPayload.authorization.from;
|
|
608
1041
|
const bytecode = await this.signer.getCode({ address: payerAddress });
|
|
609
1042
|
if (!bytecode || bytecode === "0x") {
|
|
@@ -627,14 +1060,14 @@ var ExactEvmSchemeV1 = class {
|
|
|
627
1060
|
const isECDSA = signatureLength === 130;
|
|
628
1061
|
let tx;
|
|
629
1062
|
if (isECDSA) {
|
|
630
|
-
const parsedSig = (0,
|
|
1063
|
+
const parsedSig = (0, import_viem5.parseSignature)(signature);
|
|
631
1064
|
tx = await this.signer.writeContract({
|
|
632
|
-
address: (0,
|
|
1065
|
+
address: (0, import_viem5.getAddress)(requirements.asset),
|
|
633
1066
|
abi: eip3009ABI,
|
|
634
1067
|
functionName: "transferWithAuthorization",
|
|
635
1068
|
args: [
|
|
636
|
-
(0,
|
|
637
|
-
(0,
|
|
1069
|
+
(0, import_viem5.getAddress)(exactEvmPayload.authorization.from),
|
|
1070
|
+
(0, import_viem5.getAddress)(exactEvmPayload.authorization.to),
|
|
638
1071
|
BigInt(exactEvmPayload.authorization.value),
|
|
639
1072
|
BigInt(exactEvmPayload.authorization.validAfter),
|
|
640
1073
|
BigInt(exactEvmPayload.authorization.validBefore),
|
|
@@ -646,12 +1079,12 @@ var ExactEvmSchemeV1 = class {
|
|
|
646
1079
|
});
|
|
647
1080
|
} else {
|
|
648
1081
|
tx = await this.signer.writeContract({
|
|
649
|
-
address: (0,
|
|
1082
|
+
address: (0, import_viem5.getAddress)(requirements.asset),
|
|
650
1083
|
abi: eip3009ABI,
|
|
651
1084
|
functionName: "transferWithAuthorization",
|
|
652
1085
|
args: [
|
|
653
|
-
(0,
|
|
654
|
-
(0,
|
|
1086
|
+
(0, import_viem5.getAddress)(exactEvmPayload.authorization.from),
|
|
1087
|
+
(0, import_viem5.getAddress)(exactEvmPayload.authorization.to),
|
|
655
1088
|
BigInt(exactEvmPayload.authorization.value),
|
|
656
1089
|
BigInt(exactEvmPayload.authorization.validAfter),
|
|
657
1090
|
BigInt(exactEvmPayload.authorization.validBefore),
|
|
@@ -689,28 +1122,6 @@ var ExactEvmSchemeV1 = class {
|
|
|
689
1122
|
}
|
|
690
1123
|
};
|
|
691
1124
|
|
|
692
|
-
// src/exact/v1/client/scheme.ts
|
|
693
|
-
var import_viem4 = require("viem");
|
|
694
|
-
|
|
695
|
-
// src/v1/index.ts
|
|
696
|
-
var NETWORKS = [
|
|
697
|
-
"abstract",
|
|
698
|
-
"abstract-testnet",
|
|
699
|
-
"base-sepolia",
|
|
700
|
-
"base",
|
|
701
|
-
"avalanche-fuji",
|
|
702
|
-
"avalanche",
|
|
703
|
-
"iotex",
|
|
704
|
-
"sei",
|
|
705
|
-
"sei-testnet",
|
|
706
|
-
"polygon",
|
|
707
|
-
"polygon-amoy",
|
|
708
|
-
"peaq",
|
|
709
|
-
"story",
|
|
710
|
-
"educhain",
|
|
711
|
-
"skale-base-sepolia"
|
|
712
|
-
];
|
|
713
|
-
|
|
714
1125
|
// src/exact/facilitator/register.ts
|
|
715
1126
|
function registerExactEvmScheme(facilitator, config) {
|
|
716
1127
|
facilitator.register(
|
|
@@ -721,7 +1132,7 @@ function registerExactEvmScheme(facilitator, config) {
|
|
|
721
1132
|
);
|
|
722
1133
|
facilitator.registerV1(
|
|
723
1134
|
NETWORKS,
|
|
724
|
-
new
|
|
1135
|
+
new ExactEvmSchemeV12(config.signer, {
|
|
725
1136
|
deployERC4337WithEIP6492: config.deployERC4337WithEIP6492
|
|
726
1137
|
})
|
|
727
1138
|
);
|