@kohaku-eth/tornado-cash 0.0.2-alpha.15 → 0.0.2-alpha.17
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/index.d.ts +27 -6
- package/dist/index.js +5 -1
- package/dist/state-manager.worker.js +177 -70
- package/dist/state-manager.worker.node.js +177 -70
- package/dist/worker-loader.browser.d.ts +18 -6
- package/dist/worker-loader.node.d.ts +18 -6
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -33,6 +33,15 @@ type DeriveDepositSecretParams = BaseDeriveSecretParams & {
|
|
|
33
33
|
interface ISecretManager {
|
|
34
34
|
getDepositSecrets: (params: DeriveDepositSecretParams) => Promise<Secret>;
|
|
35
35
|
deriveEphemeralSigner: (params: DeriveDepositSecretParams) => Promise<`0x${string}`>;
|
|
36
|
+
/**
|
|
37
|
+
* Derives a delegator key from a classical wallet BIP-32 `path`, WITHOUT the
|
|
38
|
+
* `coalesceSecret` privacy transform, so it resolves to a recoverable,
|
|
39
|
+
* classical Ethereum address. Used for the tail-call batch delegator when the
|
|
40
|
+
* integrator supplies a wallet path (see `paymasterWithdrawThunk`).
|
|
41
|
+
*/
|
|
42
|
+
deriveDelegatorSigner: (params: {
|
|
43
|
+
path: string;
|
|
44
|
+
}) => Promise<`0x${string}`>;
|
|
36
45
|
}
|
|
37
46
|
interface SecretManagerParams {
|
|
38
47
|
host: Pick<Host, 'keystore'>;
|
|
@@ -352,6 +361,24 @@ declare enum DepositStrategy {
|
|
|
352
361
|
MinFee = 1
|
|
353
362
|
}
|
|
354
363
|
|
|
364
|
+
/**
|
|
365
|
+
* How the batch delegator for a tail-call paymaster withdrawal is produced.
|
|
366
|
+
* Only honored when `tailCalls` are present (see `paymasterWithdrawThunk`).
|
|
367
|
+
*
|
|
368
|
+
* - `deterministic` (default): recoverable. With `path`, the delegator is a
|
|
369
|
+
* classical wallet-path address; without `path`, an ephemeral address keyed by
|
|
370
|
+
* the batch's first deposit.
|
|
371
|
+
* - `random`: a throwaway, unrecoverable EOA — an explicit opt-out of
|
|
372
|
+
* recoverability. Never the default, because in the tail-call path the
|
|
373
|
+
* delegator holds the withdrawn funds.
|
|
374
|
+
*/
|
|
375
|
+
type DelegationConfig = {
|
|
376
|
+
mode: 'deterministic';
|
|
377
|
+
path?: string;
|
|
378
|
+
} | {
|
|
379
|
+
mode: 'random';
|
|
380
|
+
};
|
|
381
|
+
|
|
355
382
|
interface SerializedAuth {
|
|
356
383
|
address: Address$1;
|
|
357
384
|
chainId: Hex;
|
|
@@ -410,12 +437,6 @@ interface IPaymasterBroadcasterClient {
|
|
|
410
437
|
broadcast(withdrawals: IPaymasterWithdrawalPayload[]): Promise<PaymasterBroadcastResult[]>;
|
|
411
438
|
}
|
|
412
439
|
|
|
413
|
-
type DelegationConfig = {
|
|
414
|
-
mode: 'deterministic';
|
|
415
|
-
path?: string;
|
|
416
|
-
} | {
|
|
417
|
-
mode: 'random';
|
|
418
|
-
};
|
|
419
440
|
type StringAddress = `0x${string}`;
|
|
420
441
|
interface IPaymasterConfig {
|
|
421
442
|
paymasterAddress: StringAddress;
|
package/dist/index.js
CHANGED
|
@@ -764,9 +764,13 @@ async function SecretManager({
|
|
|
764
764
|
const coalesced = coalesceSecret({ secret: raw, chainId, poolAddress });
|
|
765
765
|
return `0x${coalesced.toString(16).padStart(64, "0")}`;
|
|
766
766
|
};
|
|
767
|
+
const deriveDelegatorSigner = async ({ path }) => {
|
|
768
|
+
return Promise.resolve(keystore.deriveAt(path));
|
|
769
|
+
};
|
|
767
770
|
return {
|
|
768
771
|
getDepositSecrets: (params) => deriveSecrets(params),
|
|
769
|
-
deriveEphemeralSigner
|
|
772
|
+
deriveEphemeralSigner,
|
|
773
|
+
deriveDelegatorSigner
|
|
770
774
|
};
|
|
771
775
|
}
|
|
772
776
|
function tcPath({ accountIndex, secretType, depositIndex }) {
|
|
@@ -17281,9 +17281,13 @@ async function SecretManager({
|
|
|
17281
17281
|
const coalesced = coalesceSecret({ secret: raw, chainId, poolAddress });
|
|
17282
17282
|
return `0x${coalesced.toString(16).padStart(64, "0")}`;
|
|
17283
17283
|
};
|
|
17284
|
+
const deriveDelegatorSigner = async ({ path }) => {
|
|
17285
|
+
return Promise.resolve(keystore.deriveAt(path));
|
|
17286
|
+
};
|
|
17284
17287
|
return {
|
|
17285
17288
|
getDepositSecrets: (params) => deriveSecrets(params),
|
|
17286
|
-
deriveEphemeralSigner
|
|
17289
|
+
deriveEphemeralSigner,
|
|
17290
|
+
deriveDelegatorSigner
|
|
17287
17291
|
};
|
|
17288
17292
|
}
|
|
17289
17293
|
function tcPath({ accountIndex, secretType, depositIndex }) {
|
|
@@ -22190,6 +22194,15 @@ var withdrawThunk = createAsyncThunk("withdraw/executeWithdrawals", async ({
|
|
|
22190
22194
|
return getWithdrawalsProofs();
|
|
22191
22195
|
});
|
|
22192
22196
|
|
|
22197
|
+
// ../provider/dist/index.js
|
|
22198
|
+
var createTx = (address, payload, value = BigInt(0)) => {
|
|
22199
|
+
return {
|
|
22200
|
+
to: address,
|
|
22201
|
+
data: payload,
|
|
22202
|
+
value
|
|
22203
|
+
};
|
|
22204
|
+
};
|
|
22205
|
+
|
|
22193
22206
|
// ../../node_modules/.pnpm/viem@2.48.4_typescript@5.9.3_zod@4.4.3/node_modules/viem/_esm/index.js
|
|
22194
22207
|
init_exports();
|
|
22195
22208
|
init_encodeAbiParameters2();
|
|
@@ -22364,8 +22377,14 @@ function privateKeyToAccount(privateKey, options = {}) {
|
|
|
22364
22377
|
};
|
|
22365
22378
|
}
|
|
22366
22379
|
|
|
22380
|
+
// src/state/thunks/paymasterWithdrawThunk.ts
|
|
22381
|
+
init_esm();
|
|
22382
|
+
|
|
22367
22383
|
// src/paymaster/fee.ts
|
|
22368
22384
|
var ERC20_TRANSFER_GAS = 100000n;
|
|
22385
|
+
var PER_DIRECT_WITHDRAW_GAS = 400000n;
|
|
22386
|
+
var PER_DIRECT_WITHDRAW_GAS_ERC20 = 500000n;
|
|
22387
|
+
var FORWARD_GAS = 60000n;
|
|
22369
22388
|
var baseGasUnits = {
|
|
22370
22389
|
preVerificationGas: 80000n,
|
|
22371
22390
|
verificationGasLimit: 50000n,
|
|
@@ -22380,6 +22399,15 @@ function reasonableGasUnits(isERC20) {
|
|
|
22380
22399
|
paymasterVerificationGasLimit: baseGasUnits.paymasterVerificationGasLimit + ERC20_TRANSFER_GAS
|
|
22381
22400
|
};
|
|
22382
22401
|
}
|
|
22402
|
+
function reasonableGasUnitsForBatch(isERC20, extraWithdrawals, hasUserTailCalls) {
|
|
22403
|
+
const base = reasonableGasUnits(isERC20);
|
|
22404
|
+
const perWithdraw = isERC20 ? PER_DIRECT_WITHDRAW_GAS_ERC20 : PER_DIRECT_WITHDRAW_GAS;
|
|
22405
|
+
const executionTail = hasUserTailCalls ? base.callGasLimit : FORWARD_GAS;
|
|
22406
|
+
return {
|
|
22407
|
+
...base,
|
|
22408
|
+
callGasLimit: BigInt(extraWithdrawals) * perWithdraw + executionTail
|
|
22409
|
+
};
|
|
22410
|
+
}
|
|
22383
22411
|
function computeMinimumViableFee(reasonableGasUnits2, maxFeePerGas) {
|
|
22384
22412
|
const baseFeeMultiplier = 1.2;
|
|
22385
22413
|
const decimals = baseFeeMultiplier.toString().split(".")[1]?.length ?? 0;
|
|
@@ -22387,10 +22415,6 @@ function computeMinimumViableFee(reasonableGasUnits2, maxFeePerGas) {
|
|
|
22387
22415
|
const multiply = (base) => base * BigInt(Math.ceil(baseFeeMultiplier * denominator)) / BigInt(denominator);
|
|
22388
22416
|
const requiredGas = reasonableGasUnits2.verificationGasLimit + reasonableGasUnits2.callGasLimit + reasonableGasUnits2.paymasterVerificationGasLimit + reasonableGasUnits2.preVerificationGas + reasonableGasUnits2.paymasterPostOpGasLimit;
|
|
22389
22417
|
const requiredPrefund = requiredGas * maxFeePerGas;
|
|
22390
|
-
console.log("totalGasUnits", requiredGas);
|
|
22391
|
-
console.log("maxFeePerGas", maxFeePerGas);
|
|
22392
|
-
console.log("requiredPrefund", requiredPrefund);
|
|
22393
|
-
console.log("multiply", 1.2);
|
|
22394
22418
|
return multiply(requiredPrefund);
|
|
22395
22419
|
}
|
|
22396
22420
|
|
|
@@ -24087,11 +24111,21 @@ async function getUserOperationGasPrice(client) {
|
|
|
24087
24111
|
fast: parse(result.fast)
|
|
24088
24112
|
};
|
|
24089
24113
|
}
|
|
24090
|
-
function
|
|
24091
|
-
|
|
24114
|
+
async function estimateUserOperationGas2(client, op, entryPoint) {
|
|
24115
|
+
const result = await client.request({
|
|
24116
|
+
method: "eth_estimateUserOperationGas",
|
|
24117
|
+
params: [op, entryPoint]
|
|
24118
|
+
});
|
|
24119
|
+
return {
|
|
24120
|
+
callGasLimit: BigInt(result.callGasLimit),
|
|
24121
|
+
verificationGasLimit: BigInt(result.verificationGasLimit),
|
|
24122
|
+
preVerificationGas: BigInt(result.preVerificationGas),
|
|
24123
|
+
paymasterVerificationGasLimit: BigInt(result.paymasterVerificationGasLimit ?? 0),
|
|
24124
|
+
paymasterPostOpGasLimit: BigInt(result.paymasterPostOpGasLimit ?? 0)
|
|
24125
|
+
};
|
|
24092
24126
|
}
|
|
24093
24127
|
async function buildSignedTornadoUserOp({
|
|
24094
|
-
|
|
24128
|
+
signer,
|
|
24095
24129
|
chainId,
|
|
24096
24130
|
paymasterAddress,
|
|
24097
24131
|
paymasterData,
|
|
@@ -24101,7 +24135,7 @@ async function buildSignedTornadoUserOp({
|
|
|
24101
24135
|
tailCalls = async () => [],
|
|
24102
24136
|
nonce = 0n
|
|
24103
24137
|
}) {
|
|
24104
|
-
const owner =
|
|
24138
|
+
const owner = signer;
|
|
24105
24139
|
const calls = await tailCalls(owner.address);
|
|
24106
24140
|
let callData = "0x";
|
|
24107
24141
|
if (calls.length === 1) {
|
|
@@ -24174,6 +24208,12 @@ function serializeAuth(auth) {
|
|
|
24174
24208
|
}
|
|
24175
24209
|
|
|
24176
24210
|
// src/state/thunks/paymasterWithdrawThunk.ts
|
|
24211
|
+
var BIP32_PATH = /^m(\/\d+'?)+$/;
|
|
24212
|
+
function assertValidDelegatorPath(path) {
|
|
24213
|
+
if (!BIP32_PATH.test(path)) {
|
|
24214
|
+
throw new Error(`Invalid delegation path "${path}": expected a BIP-32 path like m/44'/60'/0'/0/0`);
|
|
24215
|
+
}
|
|
24216
|
+
}
|
|
24177
24217
|
var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdrawals", async ({
|
|
24178
24218
|
dataService,
|
|
24179
24219
|
assetAddress,
|
|
@@ -24214,43 +24254,23 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
24214
24254
|
);
|
|
24215
24255
|
const bundlerClient = createPaymasterBundlerClient(bundlerUrl);
|
|
24216
24256
|
const { standard: { maxFeePerGas, maxPriorityFeePerGas } } = await getUserOperationGasPrice(bundlerClient);
|
|
24217
|
-
const gasUnits = reasonableGasUnits(poolInfo.isERC20);
|
|
24218
|
-
const ethFee = computeMinimumViableFee(gasUnits, maxFeePerGas);
|
|
24219
|
-
const fee = poolInfo.isERC20 ? await dataService.quoteWeiInToken(BigInt(paymasterAddress), poolInfo.asset, ethFee) : ethFee;
|
|
24220
24257
|
const relayerAddress = BigInt(paymasterAddress);
|
|
24221
24258
|
const bigintChainId = await dataService.getChainId();
|
|
24222
24259
|
const { recipient: originalRecipient, ...restWithoutRecipient } = rest;
|
|
24223
|
-
const
|
|
24224
|
-
const
|
|
24225
|
-
|
|
24226
|
-
|
|
24227
|
-
|
|
24228
|
-
|
|
24229
|
-
|
|
24230
|
-
|
|
24231
|
-
|
|
24232
|
-
|
|
24233
|
-
|
|
24234
|
-
const recipient = sharedPrivateKey ? BigInt(ephemeralSenderAddress(privateKey)) : originalRecipient;
|
|
24235
|
-
const effectiveTailCalls = isLast ? tailCalls : void 0;
|
|
24236
|
-
const gas = { ...gasUnits, callGasLimit: effectiveTailCalls ? gasUnits.callGasLimit : 0n };
|
|
24237
|
-
const withdrawResultAction = await dispatch(
|
|
24238
|
-
withdrawalsProofThunk({
|
|
24239
|
-
...restWithoutRecipient,
|
|
24240
|
-
recipient,
|
|
24241
|
-
deposit,
|
|
24242
|
-
relayerAddress,
|
|
24243
|
-
fee
|
|
24244
|
-
})
|
|
24245
|
-
);
|
|
24246
|
-
const proof = { ...unwrapResult(withdrawResultAction), poolAddress: deposit.pool };
|
|
24247
|
-
proofOutputs.push(proof);
|
|
24248
|
-
const { poolAddress, ...proofArgs } = proof;
|
|
24249
|
-
const [root, nullifierHash, proofRecipient, relayerArg, feeArg, refundArg] = proofArgs.args;
|
|
24250
|
-
const paymasterData = encodePaymasterData(
|
|
24260
|
+
const quoteFee = async (ethFee) => poolInfo.isERC20 ? dataService.quoteWeiInToken(BigInt(paymasterAddress), poolInfo.asset, ethFee) : ethFee;
|
|
24261
|
+
const prove = async (deposit, recipient, relayer, depositFee) => unwrapResult(await dispatch(withdrawalsProofThunk({
|
|
24262
|
+
...restWithoutRecipient,
|
|
24263
|
+
recipient,
|
|
24264
|
+
deposit,
|
|
24265
|
+
relayerAddress: relayer,
|
|
24266
|
+
fee: depositFee
|
|
24267
|
+
})));
|
|
24268
|
+
const buildPaymasterData = (poolAddress, proof) => {
|
|
24269
|
+
const [root, nullifierHash, proofRecipient, relayerArg, feeArg, refundArg] = proof.args;
|
|
24270
|
+
return encodePaymasterData(
|
|
24251
24271
|
poolAcountsMap.get(poolAddress),
|
|
24252
24272
|
encodeTornadoAdapterData(
|
|
24253
|
-
|
|
24273
|
+
proof.proof,
|
|
24254
24274
|
root,
|
|
24255
24275
|
nullifierHash,
|
|
24256
24276
|
proofRecipient,
|
|
@@ -24259,43 +24279,130 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
24259
24279
|
BigInt(refundArg)
|
|
24260
24280
|
)
|
|
24261
24281
|
);
|
|
24262
|
-
|
|
24263
|
-
|
|
24264
|
-
|
|
24265
|
-
|
|
24266
|
-
|
|
24267
|
-
|
|
24268
|
-
|
|
24269
|
-
|
|
24270
|
-
|
|
24271
|
-
|
|
24272
|
-
|
|
24273
|
-
|
|
24274
|
-
|
|
24275
|
-
|
|
24276
|
-
|
|
24282
|
+
};
|
|
24283
|
+
const ephemeralSigner = async (deposit) => privateKeyToAccount(await secretManager.deriveEphemeralSigner({
|
|
24284
|
+
depositIndex: deposit.index,
|
|
24285
|
+
chainId: bigintChainId,
|
|
24286
|
+
poolAddress: deposit.pool
|
|
24287
|
+
}));
|
|
24288
|
+
const resolveBatchDelegator = async () => {
|
|
24289
|
+
if (delegation?.mode === "random") return privateKeyToAccount(generatePrivateKey());
|
|
24290
|
+
if (delegation?.mode === "deterministic" && delegation.path) {
|
|
24291
|
+
assertValidDelegatorPath(delegation.path);
|
|
24292
|
+
return privateKeyToAccount(await secretManager.deriveDelegatorSigner({ path: delegation.path }));
|
|
24293
|
+
}
|
|
24294
|
+
return ephemeralSigner(deposits[0]);
|
|
24295
|
+
};
|
|
24296
|
+
const resolveIndependentSigner = (deposit) => delegation?.mode === "deterministic" ? ephemeralSigner(deposit) : Promise.resolve(privateKeyToAccount(generatePrivateKey()));
|
|
24297
|
+
const needsConsolidation = deposits.length > 1 || tailCalls != null;
|
|
24298
|
+
if (!needsConsolidation) {
|
|
24299
|
+
const deposit = deposits[0];
|
|
24300
|
+
const signer2 = await resolveIndependentSigner(deposit);
|
|
24301
|
+
const gasUnits = reasonableGasUnits(poolInfo.isERC20);
|
|
24302
|
+
const fee2 = await quoteFee(computeMinimumViableFee(gasUnits, maxFeePerGas));
|
|
24303
|
+
const proof = await prove(deposit, originalRecipient, relayerAddress, fee2);
|
|
24304
|
+
const userOperation2 = await buildSignedTornadoUserOp({
|
|
24305
|
+
signer: signer2,
|
|
24306
|
+
chainId,
|
|
24307
|
+
paymasterAddress,
|
|
24308
|
+
paymasterData: buildPaymasterData(deposit.pool, proof),
|
|
24309
|
+
gas: { ...gasUnits, callGasLimit: 0n },
|
|
24310
|
+
maxFeePerGas,
|
|
24311
|
+
maxPriorityFeePerGas,
|
|
24312
|
+
nonce: 0n
|
|
24313
|
+
});
|
|
24314
|
+
return [{
|
|
24315
|
+
mode: "paymaster",
|
|
24316
|
+
proof,
|
|
24317
|
+
poolAddress: deposit.pool,
|
|
24318
|
+
isERC20: poolInfo.isERC20,
|
|
24319
|
+
paymasterAddress,
|
|
24320
|
+
entryPointAddress,
|
|
24321
|
+
bundlerUrl,
|
|
24322
|
+
userOperation: userOperation2
|
|
24323
|
+
}];
|
|
24324
|
+
}
|
|
24325
|
+
const signer = await resolveBatchDelegator();
|
|
24326
|
+
const senderAddress = BigInt(signer.address);
|
|
24327
|
+
const sponsoringDeposit = deposits[0];
|
|
24328
|
+
const directDeposits = deposits.slice(1);
|
|
24329
|
+
const ZERO_ADDRESS = 0n;
|
|
24330
|
+
const directWithdrawCalls = [];
|
|
24331
|
+
for (const deposit of directDeposits) {
|
|
24332
|
+
const proof = await prove(deposit, senderAddress, ZERO_ADDRESS, 0n);
|
|
24333
|
+
const [root, nullifierHash, proofRecipient, relayerArg, feeArg, refundArg] = proof.args;
|
|
24334
|
+
const data = encodeFunctionData({
|
|
24335
|
+
abi: poolAbi,
|
|
24336
|
+
functionName: "withdraw",
|
|
24337
|
+
args: [proof.proof, root, nullifierHash, proofRecipient, relayerArg, BigInt(feeArg), BigInt(refundArg)]
|
|
24338
|
+
});
|
|
24339
|
+
directWithdrawCalls.push(createTx(addressToHex(deposit.pool), data, 0n));
|
|
24277
24340
|
}
|
|
24278
|
-
|
|
24341
|
+
const totalDenomination = deposits.reduce(
|
|
24342
|
+
(sum, d) => sum + pools.get(d.pool).denomination,
|
|
24343
|
+
0n
|
|
24344
|
+
);
|
|
24345
|
+
const forwardCalls = (fee2) => {
|
|
24346
|
+
const amount2 = totalDenomination - fee2;
|
|
24347
|
+
if (poolInfo.isERC20) {
|
|
24348
|
+
const data = encodeFunctionData({
|
|
24349
|
+
abi: erc20Abi,
|
|
24350
|
+
functionName: "transfer",
|
|
24351
|
+
args: [addressToHex(originalRecipient), amount2]
|
|
24352
|
+
});
|
|
24353
|
+
return [createTx(addressToHex(poolInfo.asset), data, 0n)];
|
|
24354
|
+
}
|
|
24355
|
+
return [createTx(addressToHex(originalRecipient), "0x", amount2)];
|
|
24356
|
+
};
|
|
24357
|
+
const composeTailCalls = (fee2) => async (addr) => [
|
|
24358
|
+
...directWithdrawCalls,
|
|
24359
|
+
...tailCalls ? await tailCalls(addr) : forwardCalls(fee2)
|
|
24360
|
+
];
|
|
24361
|
+
const buildOp = (gas2, fee2, paymasterData) => buildSignedTornadoUserOp({
|
|
24362
|
+
signer,
|
|
24363
|
+
chainId,
|
|
24364
|
+
paymasterAddress,
|
|
24365
|
+
paymasterData,
|
|
24366
|
+
gas: gas2,
|
|
24367
|
+
maxFeePerGas,
|
|
24368
|
+
maxPriorityFeePerGas,
|
|
24369
|
+
tailCalls: composeTailCalls(fee2),
|
|
24370
|
+
nonce: 0n
|
|
24371
|
+
});
|
|
24372
|
+
const baselineGas = reasonableGasUnitsForBatch(poolInfo.isERC20, directDeposits.length, tailCalls != null);
|
|
24373
|
+
let fee = await quoteFee(computeMinimumViableFee(baselineGas, maxFeePerGas));
|
|
24374
|
+
let gas = baselineGas;
|
|
24375
|
+
let sponsoringProof = await prove(sponsoringDeposit, senderAddress, relayerAddress, fee);
|
|
24376
|
+
let userOperation = await buildOp(gas, fee, buildPaymasterData(sponsoringDeposit.pool, sponsoringProof));
|
|
24377
|
+
try {
|
|
24378
|
+
const estimated = await estimateUserOperationGas2(bundlerClient, userOperation, entryPointAddress);
|
|
24379
|
+
const buffer2 = (x) => x * 12n / 10n;
|
|
24380
|
+
const orBaseline = (e, b) => e > 0n ? buffer2(e) : b;
|
|
24381
|
+
const refinedGas = {
|
|
24382
|
+
callGasLimit: orBaseline(estimated.callGasLimit, baselineGas.callGasLimit),
|
|
24383
|
+
verificationGasLimit: orBaseline(estimated.verificationGasLimit, baselineGas.verificationGasLimit),
|
|
24384
|
+
preVerificationGas: orBaseline(estimated.preVerificationGas, baselineGas.preVerificationGas),
|
|
24385
|
+
paymasterVerificationGasLimit: orBaseline(estimated.paymasterVerificationGasLimit, baselineGas.paymasterVerificationGasLimit),
|
|
24386
|
+
paymasterPostOpGasLimit: orBaseline(estimated.paymasterPostOpGasLimit, baselineGas.paymasterPostOpGasLimit)
|
|
24387
|
+
};
|
|
24388
|
+
fee = await quoteFee(computeMinimumViableFee(refinedGas, maxFeePerGas));
|
|
24389
|
+
gas = refinedGas;
|
|
24390
|
+
sponsoringProof = await prove(sponsoringDeposit, senderAddress, relayerAddress, fee);
|
|
24391
|
+
userOperation = await buildOp(gas, fee, buildPaymasterData(sponsoringDeposit.pool, sponsoringProof));
|
|
24392
|
+
} catch {
|
|
24393
|
+
}
|
|
24394
|
+
return [{
|
|
24279
24395
|
mode: "paymaster",
|
|
24280
|
-
proof,
|
|
24281
|
-
poolAddress,
|
|
24396
|
+
proof: sponsoringProof,
|
|
24397
|
+
poolAddress: sponsoringDeposit.pool,
|
|
24282
24398
|
isERC20: poolInfo.isERC20,
|
|
24283
24399
|
paymasterAddress,
|
|
24284
24400
|
entryPointAddress,
|
|
24285
24401
|
bundlerUrl,
|
|
24286
|
-
userOperation
|
|
24287
|
-
}
|
|
24402
|
+
userOperation
|
|
24403
|
+
}];
|
|
24288
24404
|
});
|
|
24289
24405
|
|
|
24290
|
-
// ../provider/dist/index.js
|
|
24291
|
-
var createTx = (address, payload, value = BigInt(0)) => {
|
|
24292
|
-
return {
|
|
24293
|
-
to: address,
|
|
24294
|
-
data: payload,
|
|
24295
|
-
value
|
|
24296
|
-
};
|
|
24297
|
-
};
|
|
24298
|
-
|
|
24299
24406
|
// src/account/tx/shield.ts
|
|
24300
24407
|
init_esm();
|
|
24301
24408
|
init_esm();
|
|
@@ -16853,9 +16853,13 @@ async function SecretManager({
|
|
|
16853
16853
|
const coalesced = coalesceSecret({ secret: raw, chainId, poolAddress });
|
|
16854
16854
|
return `0x${coalesced.toString(16).padStart(64, "0")}`;
|
|
16855
16855
|
};
|
|
16856
|
+
const deriveDelegatorSigner = async ({ path }) => {
|
|
16857
|
+
return Promise.resolve(keystore.deriveAt(path));
|
|
16858
|
+
};
|
|
16856
16859
|
return {
|
|
16857
16860
|
getDepositSecrets: (params) => deriveSecrets(params),
|
|
16858
|
-
deriveEphemeralSigner
|
|
16861
|
+
deriveEphemeralSigner,
|
|
16862
|
+
deriveDelegatorSigner
|
|
16859
16863
|
};
|
|
16860
16864
|
}
|
|
16861
16865
|
function tcPath({ accountIndex, secretType, depositIndex }) {
|
|
@@ -21416,6 +21420,15 @@ var withdrawThunk = createAsyncThunk("withdraw/executeWithdrawals", async ({
|
|
|
21416
21420
|
return getWithdrawalsProofs();
|
|
21417
21421
|
});
|
|
21418
21422
|
|
|
21423
|
+
// ../provider/dist/index.js
|
|
21424
|
+
var createTx = (address, payload, value = BigInt(0)) => {
|
|
21425
|
+
return {
|
|
21426
|
+
to: address,
|
|
21427
|
+
data: payload,
|
|
21428
|
+
value
|
|
21429
|
+
};
|
|
21430
|
+
};
|
|
21431
|
+
|
|
21419
21432
|
// ../../node_modules/.pnpm/viem@2.48.4_typescript@5.9.3_zod@4.4.3/node_modules/viem/_esm/index.js
|
|
21420
21433
|
init_exports();
|
|
21421
21434
|
init_encodeAbiParameters2();
|
|
@@ -21590,8 +21603,14 @@ function privateKeyToAccount(privateKey, options = {}) {
|
|
|
21590
21603
|
};
|
|
21591
21604
|
}
|
|
21592
21605
|
|
|
21606
|
+
// src/state/thunks/paymasterWithdrawThunk.ts
|
|
21607
|
+
init_esm();
|
|
21608
|
+
|
|
21593
21609
|
// src/paymaster/fee.ts
|
|
21594
21610
|
var ERC20_TRANSFER_GAS = 100000n;
|
|
21611
|
+
var PER_DIRECT_WITHDRAW_GAS = 400000n;
|
|
21612
|
+
var PER_DIRECT_WITHDRAW_GAS_ERC20 = 500000n;
|
|
21613
|
+
var FORWARD_GAS = 60000n;
|
|
21595
21614
|
var baseGasUnits = {
|
|
21596
21615
|
preVerificationGas: 80000n,
|
|
21597
21616
|
verificationGasLimit: 50000n,
|
|
@@ -21606,6 +21625,15 @@ function reasonableGasUnits(isERC20) {
|
|
|
21606
21625
|
paymasterVerificationGasLimit: baseGasUnits.paymasterVerificationGasLimit + ERC20_TRANSFER_GAS
|
|
21607
21626
|
};
|
|
21608
21627
|
}
|
|
21628
|
+
function reasonableGasUnitsForBatch(isERC20, extraWithdrawals, hasUserTailCalls) {
|
|
21629
|
+
const base = reasonableGasUnits(isERC20);
|
|
21630
|
+
const perWithdraw = isERC20 ? PER_DIRECT_WITHDRAW_GAS_ERC20 : PER_DIRECT_WITHDRAW_GAS;
|
|
21631
|
+
const executionTail = hasUserTailCalls ? base.callGasLimit : FORWARD_GAS;
|
|
21632
|
+
return {
|
|
21633
|
+
...base,
|
|
21634
|
+
callGasLimit: BigInt(extraWithdrawals) * perWithdraw + executionTail
|
|
21635
|
+
};
|
|
21636
|
+
}
|
|
21609
21637
|
function computeMinimumViableFee(reasonableGasUnits2, maxFeePerGas) {
|
|
21610
21638
|
const baseFeeMultiplier = 1.2;
|
|
21611
21639
|
const decimals = baseFeeMultiplier.toString().split(".")[1]?.length ?? 0;
|
|
@@ -21613,10 +21641,6 @@ function computeMinimumViableFee(reasonableGasUnits2, maxFeePerGas) {
|
|
|
21613
21641
|
const multiply = (base) => base * BigInt(Math.ceil(baseFeeMultiplier * denominator)) / BigInt(denominator);
|
|
21614
21642
|
const requiredGas = reasonableGasUnits2.verificationGasLimit + reasonableGasUnits2.callGasLimit + reasonableGasUnits2.paymasterVerificationGasLimit + reasonableGasUnits2.preVerificationGas + reasonableGasUnits2.paymasterPostOpGasLimit;
|
|
21615
21643
|
const requiredPrefund = requiredGas * maxFeePerGas;
|
|
21616
|
-
console.log("totalGasUnits", requiredGas);
|
|
21617
|
-
console.log("maxFeePerGas", maxFeePerGas);
|
|
21618
|
-
console.log("requiredPrefund", requiredPrefund);
|
|
21619
|
-
console.log("multiply", 1.2);
|
|
21620
21644
|
return multiply(requiredPrefund);
|
|
21621
21645
|
}
|
|
21622
21646
|
|
|
@@ -23313,11 +23337,21 @@ async function getUserOperationGasPrice(client) {
|
|
|
23313
23337
|
fast: parse(result.fast)
|
|
23314
23338
|
};
|
|
23315
23339
|
}
|
|
23316
|
-
function
|
|
23317
|
-
|
|
23340
|
+
async function estimateUserOperationGas2(client, op, entryPoint) {
|
|
23341
|
+
const result = await client.request({
|
|
23342
|
+
method: "eth_estimateUserOperationGas",
|
|
23343
|
+
params: [op, entryPoint]
|
|
23344
|
+
});
|
|
23345
|
+
return {
|
|
23346
|
+
callGasLimit: BigInt(result.callGasLimit),
|
|
23347
|
+
verificationGasLimit: BigInt(result.verificationGasLimit),
|
|
23348
|
+
preVerificationGas: BigInt(result.preVerificationGas),
|
|
23349
|
+
paymasterVerificationGasLimit: BigInt(result.paymasterVerificationGasLimit ?? 0),
|
|
23350
|
+
paymasterPostOpGasLimit: BigInt(result.paymasterPostOpGasLimit ?? 0)
|
|
23351
|
+
};
|
|
23318
23352
|
}
|
|
23319
23353
|
async function buildSignedTornadoUserOp({
|
|
23320
|
-
|
|
23354
|
+
signer,
|
|
23321
23355
|
chainId,
|
|
23322
23356
|
paymasterAddress,
|
|
23323
23357
|
paymasterData,
|
|
@@ -23327,7 +23361,7 @@ async function buildSignedTornadoUserOp({
|
|
|
23327
23361
|
tailCalls = async () => [],
|
|
23328
23362
|
nonce = 0n
|
|
23329
23363
|
}) {
|
|
23330
|
-
const owner =
|
|
23364
|
+
const owner = signer;
|
|
23331
23365
|
const calls = await tailCalls(owner.address);
|
|
23332
23366
|
let callData = "0x";
|
|
23333
23367
|
if (calls.length === 1) {
|
|
@@ -23400,6 +23434,12 @@ function serializeAuth(auth) {
|
|
|
23400
23434
|
}
|
|
23401
23435
|
|
|
23402
23436
|
// src/state/thunks/paymasterWithdrawThunk.ts
|
|
23437
|
+
var BIP32_PATH = /^m(\/\d+'?)+$/;
|
|
23438
|
+
function assertValidDelegatorPath(path) {
|
|
23439
|
+
if (!BIP32_PATH.test(path)) {
|
|
23440
|
+
throw new Error(`Invalid delegation path "${path}": expected a BIP-32 path like m/44'/60'/0'/0/0`);
|
|
23441
|
+
}
|
|
23442
|
+
}
|
|
23403
23443
|
var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdrawals", async ({
|
|
23404
23444
|
dataService,
|
|
23405
23445
|
assetAddress,
|
|
@@ -23440,43 +23480,23 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
23440
23480
|
);
|
|
23441
23481
|
const bundlerClient = createPaymasterBundlerClient(bundlerUrl);
|
|
23442
23482
|
const { standard: { maxFeePerGas, maxPriorityFeePerGas } } = await getUserOperationGasPrice(bundlerClient);
|
|
23443
|
-
const gasUnits = reasonableGasUnits(poolInfo.isERC20);
|
|
23444
|
-
const ethFee = computeMinimumViableFee(gasUnits, maxFeePerGas);
|
|
23445
|
-
const fee = poolInfo.isERC20 ? await dataService.quoteWeiInToken(BigInt(paymasterAddress), poolInfo.asset, ethFee) : ethFee;
|
|
23446
23483
|
const relayerAddress = BigInt(paymasterAddress);
|
|
23447
23484
|
const bigintChainId = await dataService.getChainId();
|
|
23448
23485
|
const { recipient: originalRecipient, ...restWithoutRecipient } = rest;
|
|
23449
|
-
const
|
|
23450
|
-
const
|
|
23451
|
-
|
|
23452
|
-
|
|
23453
|
-
|
|
23454
|
-
|
|
23455
|
-
|
|
23456
|
-
|
|
23457
|
-
|
|
23458
|
-
|
|
23459
|
-
|
|
23460
|
-
const recipient = sharedPrivateKey ? BigInt(ephemeralSenderAddress(privateKey)) : originalRecipient;
|
|
23461
|
-
const effectiveTailCalls = isLast ? tailCalls : void 0;
|
|
23462
|
-
const gas = { ...gasUnits, callGasLimit: effectiveTailCalls ? gasUnits.callGasLimit : 0n };
|
|
23463
|
-
const withdrawResultAction = await dispatch(
|
|
23464
|
-
withdrawalsProofThunk({
|
|
23465
|
-
...restWithoutRecipient,
|
|
23466
|
-
recipient,
|
|
23467
|
-
deposit,
|
|
23468
|
-
relayerAddress,
|
|
23469
|
-
fee
|
|
23470
|
-
})
|
|
23471
|
-
);
|
|
23472
|
-
const proof = { ...unwrapResult(withdrawResultAction), poolAddress: deposit.pool };
|
|
23473
|
-
proofOutputs.push(proof);
|
|
23474
|
-
const { poolAddress, ...proofArgs } = proof;
|
|
23475
|
-
const [root, nullifierHash, proofRecipient, relayerArg, feeArg, refundArg] = proofArgs.args;
|
|
23476
|
-
const paymasterData = encodePaymasterData(
|
|
23486
|
+
const quoteFee = async (ethFee) => poolInfo.isERC20 ? dataService.quoteWeiInToken(BigInt(paymasterAddress), poolInfo.asset, ethFee) : ethFee;
|
|
23487
|
+
const prove = async (deposit, recipient, relayer, depositFee) => unwrapResult(await dispatch(withdrawalsProofThunk({
|
|
23488
|
+
...restWithoutRecipient,
|
|
23489
|
+
recipient,
|
|
23490
|
+
deposit,
|
|
23491
|
+
relayerAddress: relayer,
|
|
23492
|
+
fee: depositFee
|
|
23493
|
+
})));
|
|
23494
|
+
const buildPaymasterData = (poolAddress, proof) => {
|
|
23495
|
+
const [root, nullifierHash, proofRecipient, relayerArg, feeArg, refundArg] = proof.args;
|
|
23496
|
+
return encodePaymasterData(
|
|
23477
23497
|
poolAcountsMap.get(poolAddress),
|
|
23478
23498
|
encodeTornadoAdapterData(
|
|
23479
|
-
|
|
23499
|
+
proof.proof,
|
|
23480
23500
|
root,
|
|
23481
23501
|
nullifierHash,
|
|
23482
23502
|
proofRecipient,
|
|
@@ -23485,43 +23505,130 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
23485
23505
|
BigInt(refundArg)
|
|
23486
23506
|
)
|
|
23487
23507
|
);
|
|
23488
|
-
|
|
23489
|
-
|
|
23490
|
-
|
|
23491
|
-
|
|
23492
|
-
|
|
23493
|
-
|
|
23494
|
-
|
|
23495
|
-
|
|
23496
|
-
|
|
23497
|
-
|
|
23498
|
-
|
|
23499
|
-
|
|
23500
|
-
|
|
23501
|
-
|
|
23502
|
-
|
|
23508
|
+
};
|
|
23509
|
+
const ephemeralSigner = async (deposit) => privateKeyToAccount(await secretManager.deriveEphemeralSigner({
|
|
23510
|
+
depositIndex: deposit.index,
|
|
23511
|
+
chainId: bigintChainId,
|
|
23512
|
+
poolAddress: deposit.pool
|
|
23513
|
+
}));
|
|
23514
|
+
const resolveBatchDelegator = async () => {
|
|
23515
|
+
if (delegation?.mode === "random") return privateKeyToAccount(generatePrivateKey());
|
|
23516
|
+
if (delegation?.mode === "deterministic" && delegation.path) {
|
|
23517
|
+
assertValidDelegatorPath(delegation.path);
|
|
23518
|
+
return privateKeyToAccount(await secretManager.deriveDelegatorSigner({ path: delegation.path }));
|
|
23519
|
+
}
|
|
23520
|
+
return ephemeralSigner(deposits[0]);
|
|
23521
|
+
};
|
|
23522
|
+
const resolveIndependentSigner = (deposit) => delegation?.mode === "deterministic" ? ephemeralSigner(deposit) : Promise.resolve(privateKeyToAccount(generatePrivateKey()));
|
|
23523
|
+
const needsConsolidation = deposits.length > 1 || tailCalls != null;
|
|
23524
|
+
if (!needsConsolidation) {
|
|
23525
|
+
const deposit = deposits[0];
|
|
23526
|
+
const signer2 = await resolveIndependentSigner(deposit);
|
|
23527
|
+
const gasUnits = reasonableGasUnits(poolInfo.isERC20);
|
|
23528
|
+
const fee2 = await quoteFee(computeMinimumViableFee(gasUnits, maxFeePerGas));
|
|
23529
|
+
const proof = await prove(deposit, originalRecipient, relayerAddress, fee2);
|
|
23530
|
+
const userOperation2 = await buildSignedTornadoUserOp({
|
|
23531
|
+
signer: signer2,
|
|
23532
|
+
chainId,
|
|
23533
|
+
paymasterAddress,
|
|
23534
|
+
paymasterData: buildPaymasterData(deposit.pool, proof),
|
|
23535
|
+
gas: { ...gasUnits, callGasLimit: 0n },
|
|
23536
|
+
maxFeePerGas,
|
|
23537
|
+
maxPriorityFeePerGas,
|
|
23538
|
+
nonce: 0n
|
|
23539
|
+
});
|
|
23540
|
+
return [{
|
|
23541
|
+
mode: "paymaster",
|
|
23542
|
+
proof,
|
|
23543
|
+
poolAddress: deposit.pool,
|
|
23544
|
+
isERC20: poolInfo.isERC20,
|
|
23545
|
+
paymasterAddress,
|
|
23546
|
+
entryPointAddress,
|
|
23547
|
+
bundlerUrl,
|
|
23548
|
+
userOperation: userOperation2
|
|
23549
|
+
}];
|
|
23550
|
+
}
|
|
23551
|
+
const signer = await resolveBatchDelegator();
|
|
23552
|
+
const senderAddress = BigInt(signer.address);
|
|
23553
|
+
const sponsoringDeposit = deposits[0];
|
|
23554
|
+
const directDeposits = deposits.slice(1);
|
|
23555
|
+
const ZERO_ADDRESS = 0n;
|
|
23556
|
+
const directWithdrawCalls = [];
|
|
23557
|
+
for (const deposit of directDeposits) {
|
|
23558
|
+
const proof = await prove(deposit, senderAddress, ZERO_ADDRESS, 0n);
|
|
23559
|
+
const [root, nullifierHash, proofRecipient, relayerArg, feeArg, refundArg] = proof.args;
|
|
23560
|
+
const data = encodeFunctionData({
|
|
23561
|
+
abi: poolAbi,
|
|
23562
|
+
functionName: "withdraw",
|
|
23563
|
+
args: [proof.proof, root, nullifierHash, proofRecipient, relayerArg, BigInt(feeArg), BigInt(refundArg)]
|
|
23564
|
+
});
|
|
23565
|
+
directWithdrawCalls.push(createTx(addressToHex(deposit.pool), data, 0n));
|
|
23503
23566
|
}
|
|
23504
|
-
|
|
23567
|
+
const totalDenomination = deposits.reduce(
|
|
23568
|
+
(sum, d) => sum + pools.get(d.pool).denomination,
|
|
23569
|
+
0n
|
|
23570
|
+
);
|
|
23571
|
+
const forwardCalls = (fee2) => {
|
|
23572
|
+
const amount2 = totalDenomination - fee2;
|
|
23573
|
+
if (poolInfo.isERC20) {
|
|
23574
|
+
const data = encodeFunctionData({
|
|
23575
|
+
abi: erc20Abi,
|
|
23576
|
+
functionName: "transfer",
|
|
23577
|
+
args: [addressToHex(originalRecipient), amount2]
|
|
23578
|
+
});
|
|
23579
|
+
return [createTx(addressToHex(poolInfo.asset), data, 0n)];
|
|
23580
|
+
}
|
|
23581
|
+
return [createTx(addressToHex(originalRecipient), "0x", amount2)];
|
|
23582
|
+
};
|
|
23583
|
+
const composeTailCalls = (fee2) => async (addr) => [
|
|
23584
|
+
...directWithdrawCalls,
|
|
23585
|
+
...tailCalls ? await tailCalls(addr) : forwardCalls(fee2)
|
|
23586
|
+
];
|
|
23587
|
+
const buildOp = (gas2, fee2, paymasterData) => buildSignedTornadoUserOp({
|
|
23588
|
+
signer,
|
|
23589
|
+
chainId,
|
|
23590
|
+
paymasterAddress,
|
|
23591
|
+
paymasterData,
|
|
23592
|
+
gas: gas2,
|
|
23593
|
+
maxFeePerGas,
|
|
23594
|
+
maxPriorityFeePerGas,
|
|
23595
|
+
tailCalls: composeTailCalls(fee2),
|
|
23596
|
+
nonce: 0n
|
|
23597
|
+
});
|
|
23598
|
+
const baselineGas = reasonableGasUnitsForBatch(poolInfo.isERC20, directDeposits.length, tailCalls != null);
|
|
23599
|
+
let fee = await quoteFee(computeMinimumViableFee(baselineGas, maxFeePerGas));
|
|
23600
|
+
let gas = baselineGas;
|
|
23601
|
+
let sponsoringProof = await prove(sponsoringDeposit, senderAddress, relayerAddress, fee);
|
|
23602
|
+
let userOperation = await buildOp(gas, fee, buildPaymasterData(sponsoringDeposit.pool, sponsoringProof));
|
|
23603
|
+
try {
|
|
23604
|
+
const estimated = await estimateUserOperationGas2(bundlerClient, userOperation, entryPointAddress);
|
|
23605
|
+
const buffer2 = (x) => x * 12n / 10n;
|
|
23606
|
+
const orBaseline = (e, b) => e > 0n ? buffer2(e) : b;
|
|
23607
|
+
const refinedGas = {
|
|
23608
|
+
callGasLimit: orBaseline(estimated.callGasLimit, baselineGas.callGasLimit),
|
|
23609
|
+
verificationGasLimit: orBaseline(estimated.verificationGasLimit, baselineGas.verificationGasLimit),
|
|
23610
|
+
preVerificationGas: orBaseline(estimated.preVerificationGas, baselineGas.preVerificationGas),
|
|
23611
|
+
paymasterVerificationGasLimit: orBaseline(estimated.paymasterVerificationGasLimit, baselineGas.paymasterVerificationGasLimit),
|
|
23612
|
+
paymasterPostOpGasLimit: orBaseline(estimated.paymasterPostOpGasLimit, baselineGas.paymasterPostOpGasLimit)
|
|
23613
|
+
};
|
|
23614
|
+
fee = await quoteFee(computeMinimumViableFee(refinedGas, maxFeePerGas));
|
|
23615
|
+
gas = refinedGas;
|
|
23616
|
+
sponsoringProof = await prove(sponsoringDeposit, senderAddress, relayerAddress, fee);
|
|
23617
|
+
userOperation = await buildOp(gas, fee, buildPaymasterData(sponsoringDeposit.pool, sponsoringProof));
|
|
23618
|
+
} catch {
|
|
23619
|
+
}
|
|
23620
|
+
return [{
|
|
23505
23621
|
mode: "paymaster",
|
|
23506
|
-
proof,
|
|
23507
|
-
poolAddress,
|
|
23622
|
+
proof: sponsoringProof,
|
|
23623
|
+
poolAddress: sponsoringDeposit.pool,
|
|
23508
23624
|
isERC20: poolInfo.isERC20,
|
|
23509
23625
|
paymasterAddress,
|
|
23510
23626
|
entryPointAddress,
|
|
23511
23627
|
bundlerUrl,
|
|
23512
|
-
userOperation
|
|
23513
|
-
}
|
|
23628
|
+
userOperation
|
|
23629
|
+
}];
|
|
23514
23630
|
});
|
|
23515
23631
|
|
|
23516
|
-
// ../provider/dist/index.js
|
|
23517
|
-
var createTx = (address, payload, value = BigInt(0)) => {
|
|
23518
|
-
return {
|
|
23519
|
-
to: address,
|
|
23520
|
-
data: payload,
|
|
23521
|
-
value
|
|
23522
|
-
};
|
|
23523
|
-
};
|
|
23524
|
-
|
|
23525
23632
|
// src/account/tx/shield.ts
|
|
23526
23633
|
init_esm();
|
|
23527
23634
|
init_esm();
|
|
@@ -113,6 +113,24 @@ declare enum DepositStrategy {
|
|
|
113
113
|
MinFee = 1
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* How the batch delegator for a tail-call paymaster withdrawal is produced.
|
|
118
|
+
* Only honored when `tailCalls` are present (see `paymasterWithdrawThunk`).
|
|
119
|
+
*
|
|
120
|
+
* - `deterministic` (default): recoverable. With `path`, the delegator is a
|
|
121
|
+
* classical wallet-path address; without `path`, an ephemeral address keyed by
|
|
122
|
+
* the batch's first deposit.
|
|
123
|
+
* - `random`: a throwaway, unrecoverable EOA — an explicit opt-out of
|
|
124
|
+
* recoverability. Never the default, because in the tail-call path the
|
|
125
|
+
* delegator holds the withdrawn funds.
|
|
126
|
+
*/
|
|
127
|
+
type DelegationConfig = {
|
|
128
|
+
mode: 'deterministic';
|
|
129
|
+
path?: string;
|
|
130
|
+
} | {
|
|
131
|
+
mode: 'random';
|
|
132
|
+
};
|
|
133
|
+
|
|
116
134
|
interface SerializedAuth {
|
|
117
135
|
address: Address$1;
|
|
118
136
|
chainId: Hex;
|
|
@@ -154,12 +172,6 @@ interface IGenericPaymasterWithdrawalPayload {
|
|
|
154
172
|
userOperation: SerializedUserOperation;
|
|
155
173
|
}
|
|
156
174
|
|
|
157
|
-
type DelegationConfig = {
|
|
158
|
-
mode: 'deterministic';
|
|
159
|
-
path?: string;
|
|
160
|
-
} | {
|
|
161
|
-
mode: 'random';
|
|
162
|
-
};
|
|
163
175
|
type StringAddress = `0x${string}`;
|
|
164
176
|
interface IPaymasterConfig {
|
|
165
177
|
paymasterAddress: StringAddress;
|
|
@@ -114,6 +114,24 @@ declare enum DepositStrategy {
|
|
|
114
114
|
MinFee = 1
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* How the batch delegator for a tail-call paymaster withdrawal is produced.
|
|
119
|
+
* Only honored when `tailCalls` are present (see `paymasterWithdrawThunk`).
|
|
120
|
+
*
|
|
121
|
+
* - `deterministic` (default): recoverable. With `path`, the delegator is a
|
|
122
|
+
* classical wallet-path address; without `path`, an ephemeral address keyed by
|
|
123
|
+
* the batch's first deposit.
|
|
124
|
+
* - `random`: a throwaway, unrecoverable EOA — an explicit opt-out of
|
|
125
|
+
* recoverability. Never the default, because in the tail-call path the
|
|
126
|
+
* delegator holds the withdrawn funds.
|
|
127
|
+
*/
|
|
128
|
+
type DelegationConfig = {
|
|
129
|
+
mode: 'deterministic';
|
|
130
|
+
path?: string;
|
|
131
|
+
} | {
|
|
132
|
+
mode: 'random';
|
|
133
|
+
};
|
|
134
|
+
|
|
117
135
|
interface SerializedAuth {
|
|
118
136
|
address: Address$1;
|
|
119
137
|
chainId: Hex;
|
|
@@ -155,12 +173,6 @@ interface IGenericPaymasterWithdrawalPayload {
|
|
|
155
173
|
userOperation: SerializedUserOperation;
|
|
156
174
|
}
|
|
157
175
|
|
|
158
|
-
type DelegationConfig = {
|
|
159
|
-
mode: 'deterministic';
|
|
160
|
-
path?: string;
|
|
161
|
-
} | {
|
|
162
|
-
mode: 'random';
|
|
163
|
-
};
|
|
164
176
|
type StringAddress = `0x${string}`;
|
|
165
177
|
interface IPaymasterConfig {
|
|
166
178
|
paymasterAddress: StringAddress;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kohaku-eth/tornado-cash",
|
|
3
|
-
"version": "0.0.2-alpha.
|
|
3
|
+
"version": "0.0.2-alpha.17",
|
|
4
4
|
"description": "Tornado Cash Shielded Pool Kohaku Plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"micro-zk-proofs": "0.3.1",
|
|
75
75
|
"ox": "^0.12.0",
|
|
76
76
|
"viem": "^2.51.3",
|
|
77
|
+
"@kohaku-eth/plugins": "0.0.1-alpha.11",
|
|
77
78
|
"@kohaku-eth/mimc-tree": "0.0.3",
|
|
78
|
-
"@kohaku-eth/provider": "0.1.0-alpha.8"
|
|
79
|
-
"@kohaku-eth/plugins": "0.0.1-alpha.11"
|
|
79
|
+
"@kohaku-eth/provider": "0.1.0-alpha.8"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@types/node": "^24.12.2",
|