four-flap-meme-sdk 1.6.27 → 1.6.28
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.
|
@@ -147,6 +147,26 @@ export async function buildDisperseFromSingleOwnerOpsWithProfit(params) {
|
|
|
147
147
|
const fnFixed = aaManager.buildUserOpWithFixedGas;
|
|
148
148
|
if (typeof fnFixed !== 'function')
|
|
149
149
|
throw new Error('AA disperse:SDK 不支持 buildUserOpWithFixedGas');
|
|
150
|
+
// ✅ 关键修复:如果有多个 UserOps,需要确保 sender 有足够余额支付所有 prefund
|
|
151
|
+
// 多个 UserOps 在同一个 handleOps 中提交时,prefund 在 validation 阶段同时扣除
|
|
152
|
+
if (chunks.length > 1 && params.kind === 'native') {
|
|
153
|
+
const feeData = await provider.getFeeData();
|
|
154
|
+
const gasPrice = feeData.gasPrice ?? 5000000000n;
|
|
155
|
+
const estimatePrefundPerOp = (listLength, deployed) => {
|
|
156
|
+
const base = 180000n;
|
|
157
|
+
const per = 45000n;
|
|
158
|
+
const callGas = base + per * BigInt(listLength);
|
|
159
|
+
const verifyGas = deployed ? 250000n : 800000n;
|
|
160
|
+
const preVerifyGas = 60000n;
|
|
161
|
+
return (callGas + verifyGas + preVerifyGas) * gasPrice * 120n / 100n;
|
|
162
|
+
};
|
|
163
|
+
let totalPrefundNeeded = 0n;
|
|
164
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
165
|
+
const deployed = i === 0 ? deployed0 : true;
|
|
166
|
+
totalPrefundNeeded += estimatePrefundPerOp(chunks[i].length, deployed);
|
|
167
|
+
}
|
|
168
|
+
console.log(`[AA 分发] 多批次分发:${chunks.length} 批,总 prefund 预估: ${ethers.formatEther(totalPrefundNeeded)} OKB`);
|
|
169
|
+
}
|
|
150
170
|
const ops = [];
|
|
151
171
|
for (let i = 0; i < chunks.length; i++) {
|
|
152
172
|
const list = chunks[i];
|
|
@@ -268,6 +288,19 @@ export async function buildTransfersWithProfit(params) {
|
|
|
268
288
|
initCodeUsed.add(k);
|
|
269
289
|
return aaManager.generateInitCode(ownerAddress);
|
|
270
290
|
};
|
|
291
|
+
// ✅ 关键修复:计算每个 sender 执行 UserOp 需要的 prefund(gas 费用)
|
|
292
|
+
// 在 Native 模式下,需要确保留足够的金额支付 prefund
|
|
293
|
+
const feeData = await provider.getFeeData();
|
|
294
|
+
const gasPrice = feeData.gasPrice ?? feeData.maxFeePerGas ?? 5000000000n;
|
|
295
|
+
const estimateTransferPrefund = (deployed) => {
|
|
296
|
+
// 归集操作的 gas:callGasLimit + verificationGasLimit + preVerificationGas
|
|
297
|
+
const callGas = 120000n; // Native 转账
|
|
298
|
+
const verifyGas = deployed ? 250000n : 800000n;
|
|
299
|
+
const preVerifyGas = 60000n;
|
|
300
|
+
const totalGas = callGas + verifyGas + preVerifyGas;
|
|
301
|
+
// 加 30% buffer 以确保足够(归集操作需要更保守)
|
|
302
|
+
return (totalGas * gasPrice * 130n) / 100n;
|
|
303
|
+
};
|
|
271
304
|
// ✅ 第一步:计算每个钱包的归集金额和总利润
|
|
272
305
|
// 利润从每个钱包的归集金额中扣除,但只由第一个有效钱包统一转账给利润地址
|
|
273
306
|
const transferInfos = [];
|
|
@@ -292,10 +325,18 @@ export async function buildTransfersWithProfit(params) {
|
|
|
292
325
|
if (amountWei <= 0n)
|
|
293
326
|
continue;
|
|
294
327
|
const profitWei = calcProfitWei(amountWei, PROFIT_CONFIG.RATE_BPS);
|
|
295
|
-
const
|
|
328
|
+
const deployed = accountInfos[i]?.deployed ?? false;
|
|
329
|
+
const prefundWei = params.kind === 'native' ? estimateTransferPrefund(deployed) : 0n;
|
|
330
|
+
// ✅ 关键修复:toWei 需要扣除 max(profitWei, prefundWei),确保留足够的 gas
|
|
331
|
+
// 在 Native 模式下,如果 profitWei < prefundWei,需要留更多余额
|
|
332
|
+
const reserveWei = params.kind === 'native'
|
|
333
|
+
? (profitWei > prefundWei ? profitWei : prefundWei)
|
|
334
|
+
: profitWei;
|
|
335
|
+
const toWei = amountWei > reserveWei ? (amountWei - reserveWei) : 0n;
|
|
296
336
|
totalProfitWei += profitWei;
|
|
297
|
-
transferInfos.push({ walletIndex: i, sender, to, amountWei, profitWei, toWei });
|
|
337
|
+
transferInfos.push({ walletIndex: i, sender, to, amountWei, profitWei, toWei, prefundWei });
|
|
298
338
|
}
|
|
339
|
+
console.log(`[AA 归集] 钱包数量: ${transferInfos.length}, 总利润: ${ethers.formatEther(totalProfitWei)} OKB`);
|
|
299
340
|
const unsigned = [];
|
|
300
341
|
const opOwnerIndex = [];
|
|
301
342
|
// ✅ 第二步:构建 UserOps
|
|
@@ -581,8 +581,29 @@ export class AADexSwapExecutor {
|
|
|
581
581
|
if (capitalMode && buyerSenders.length > 0 && totalBuyWei > 0n) {
|
|
582
582
|
if (hopCount <= 0) {
|
|
583
583
|
console.log('[AA DEX 批量换手] 进入直接分发模式 (hopCount <= 0)');
|
|
584
|
-
// ✅
|
|
585
|
-
|
|
584
|
+
// ✅ 关键修复:计算每个买方执行买入 UserOp 需要的 prefund(gas 费用)
|
|
585
|
+
// EntryPoint 在 validation 阶段会扣除 prefund,此时分发还没执行
|
|
586
|
+
// 因此需要为每个买方额外预留 prefund
|
|
587
|
+
const feeData = await this.aaManager.getFeeData();
|
|
588
|
+
const gasPrice = feeData.gasPrice ?? feeData.maxFeePerGas ?? 5000000000n; // 5 gwei fallback
|
|
589
|
+
const estimateBuyerPrefund = (deployed) => {
|
|
590
|
+
// 买入操作的 gas:V3 swap 约 650,000,部署需要额外 verificationGas
|
|
591
|
+
const callGas = 650000n;
|
|
592
|
+
const verifyGas = deployed ? 250000n : 800000n;
|
|
593
|
+
const preVerifyGas = 60000n;
|
|
594
|
+
const totalGas = callGas + verifyGas + preVerifyGas;
|
|
595
|
+
// 加 20% buffer 以确保足够
|
|
596
|
+
return (totalGas * gasPrice * 120n) / 100n;
|
|
597
|
+
};
|
|
598
|
+
// 计算每个买方需要的 prefund
|
|
599
|
+
const buyerPrefunds = buyerAis.map(ai => estimateBuyerPrefund(ai.deployed));
|
|
600
|
+
const totalBuyerPrefund = buyerPrefunds.reduce((a, b) => a + b, 0n);
|
|
601
|
+
console.log(`[AA DEX 直接分发] 买方数量: ${buyerSenders.length}, 总 prefund 预估: ${ethers.formatEther(totalBuyerPrefund)} OKB`);
|
|
602
|
+
// ✅ 直接分发模式:分发金额 = 买入金额 + 买方 prefund
|
|
603
|
+
const items = buyerSenders.map((to, i) => ({
|
|
604
|
+
to,
|
|
605
|
+
value: (buyAmountsWei[i] ?? 0n) + (buyerPrefunds[i] ?? 0n) // ✅ 包含 prefund
|
|
606
|
+
})).filter(x => x.value > 0n);
|
|
586
607
|
// 添加利润接收者到分发列表
|
|
587
608
|
if (extractProfit && profitWei > 0n) {
|
|
588
609
|
items.push({ to: profitRecipient, value: profitWei });
|
|
@@ -390,8 +390,29 @@ export class AAPortalSwapExecutor {
|
|
|
390
390
|
if (capitalMode && buyerSenders.length > 0 && totalBuyWei > 0n) {
|
|
391
391
|
if (hopCount <= 0) {
|
|
392
392
|
console.log('[AA Portal 批量换手] 进入直接分发模式 (hopCount <= 0)');
|
|
393
|
-
// ✅
|
|
394
|
-
|
|
393
|
+
// ✅ 关键修复:计算每个买方执行买入 UserOp 需要的 prefund(gas 费用)
|
|
394
|
+
// EntryPoint 在 validation 阶段会扣除 prefund,此时分发还没执行
|
|
395
|
+
// 因此需要为每个买方额外预留 prefund
|
|
396
|
+
const feeData = await this.aaManager.getFeeData();
|
|
397
|
+
const gasPrice = feeData.gasPrice ?? feeData.maxFeePerGas ?? 5000000000n; // 5 gwei fallback
|
|
398
|
+
const estimateBuyerPrefund = (deployed) => {
|
|
399
|
+
// 买入操作的 gas:Portal 买入约 450,000,部署需要额外 verificationGas
|
|
400
|
+
const callGas = 450000n;
|
|
401
|
+
const verifyGas = deployed ? 250000n : 800000n;
|
|
402
|
+
const preVerifyGas = 60000n;
|
|
403
|
+
const totalGas = callGas + verifyGas + preVerifyGas;
|
|
404
|
+
// 加 20% buffer 以确保足够
|
|
405
|
+
return (totalGas * gasPrice * 120n) / 100n;
|
|
406
|
+
};
|
|
407
|
+
// 计算每个买方需要的 prefund
|
|
408
|
+
const buyerPrefunds = buyerAis.map(ai => estimateBuyerPrefund(ai.deployed));
|
|
409
|
+
const totalBuyerPrefund = buyerPrefunds.reduce((a, b) => a + b, 0n);
|
|
410
|
+
console.log(`[AA Portal 直接分发] 买方数量: ${buyerSenders.length}, 总 prefund 预估: ${ethers.formatEther(totalBuyerPrefund)} OKB`);
|
|
411
|
+
// ✅ 直接分发模式:分发金额 = 买入金额 + 买方 prefund
|
|
412
|
+
const items = buyerSenders.map((to, i) => ({
|
|
413
|
+
to,
|
|
414
|
+
value: (buyAmountsWei[i] ?? 0n) + (buyerPrefunds[i] ?? 0n) // ✅ 包含 prefund
|
|
415
|
+
})).filter(x => x.value > 0n);
|
|
395
416
|
if (extractProfit && profitWei > 0n) {
|
|
396
417
|
items.push({ to: profitRecipient, value: profitWei });
|
|
397
418
|
}
|