@pushchain/core 5.1.17 → 6.0.0
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/package.json +1 -1
- package/src/lib/constants/abi/cea.evm.d.ts +52 -0
- package/src/lib/constants/abi/cea.evm.js +66 -1
- package/src/lib/constants/abi/prc20.evm.d.ts +117 -11
- package/src/lib/constants/abi/prc20.evm.js +38 -11
- package/src/lib/constants/abi/uea.evm.js +41 -0
- package/src/lib/constants/abi/universalGatewayPC.evm.d.ts +117 -1
- package/src/lib/constants/abi/universalGatewayPC.evm.js +40 -1
- package/src/lib/constants/abi/universalGatewayV0.json +1 -1
- package/src/lib/constants/chain.js +14 -14
- package/src/lib/constants/index.d.ts +1 -1
- package/src/lib/constants/index.js +2 -1
- package/src/lib/constants/selectors.d.ts +8 -0
- package/src/lib/constants/selectors.js +9 -1
- package/src/lib/constants/tokens.js +1 -0
- package/src/lib/formatters.d.ts +7 -0
- package/src/lib/formatters.js +46 -0
- package/src/lib/index.d.ts +2 -0
- package/src/lib/index.js +7 -1
- package/src/lib/orchestrator/internals/cascade.d.ts +8 -1
- package/src/lib/orchestrator/internals/cascade.js +593 -192
- package/src/lib/orchestrator/internals/error-decoder.d.ts +2 -6
- package/src/lib/orchestrator/internals/error-decoder.js +10 -10
- package/src/lib/orchestrator/internals/errors.d.ts +1 -1
- package/src/lib/orchestrator/internals/errors.js +8 -5
- package/src/lib/orchestrator/internals/execute-funds-only.js +3 -2
- package/src/lib/orchestrator/internals/execute-funds-payload.js +2 -1
- package/src/lib/orchestrator/internals/execute-standard.js +11 -10
- package/src/lib/orchestrator/internals/gas-calculator.d.ts +1 -0
- package/src/lib/orchestrator/internals/gas-calculator.js +91 -22
- package/src/lib/orchestrator/internals/helpers.d.ts +2 -1
- package/src/lib/orchestrator/internals/helpers.js +14 -11
- package/src/lib/orchestrator/internals/inbound-tracker.js +4 -2
- package/src/lib/orchestrator/internals/outbound-sync.d.ts +1 -0
- package/src/lib/orchestrator/internals/outbound-sync.js +140 -71
- package/src/lib/orchestrator/internals/pc-usd-oracle.d.ts +1 -1
- package/src/lib/orchestrator/internals/pc-usd-oracle.js +4 -3
- package/src/lib/orchestrator/internals/preflight.d.ts +2 -16
- package/src/lib/orchestrator/internals/preflight.js +2 -36
- package/src/lib/orchestrator/internals/push-chain-tx.js +5 -1
- package/src/lib/orchestrator/internals/response-builder.js +23 -7
- package/src/lib/orchestrator/internals/route-handlers.js +182 -227
- package/src/lib/orchestrator/internals/signing.js +7 -2
- package/src/lib/orchestrator/internals/svm-helpers.js +3 -3
- package/src/lib/orchestrator/internals/svm-rent.d.ts +42 -9
- package/src/lib/orchestrator/internals/svm-rent.js +148 -14
- package/src/lib/orchestrator/internals/tx-transformer.js +5 -2
- package/src/lib/orchestrator/max-pc-for-gas.d.ts +60 -0
- package/src/lib/orchestrator/max-pc-for-gas.js +66 -0
- package/src/lib/orchestrator/orchestrator.d.ts +8 -1
- package/src/lib/orchestrator/orchestrator.js +40 -2
- package/src/lib/orchestrator/orchestrator.types.d.ts +35 -23
- package/src/lib/orchestrator/payload-builders.d.ts +7 -6
- package/src/lib/orchestrator/payload-builders.js +18 -6
- package/src/lib/progress-hook/progress-hook.js +39 -38
- package/src/lib/push-chain/push-chain.d.ts +11 -1
- package/src/lib/push-chain/push-chain.js +2 -2
- package/src/lib/universal-tx-detector/cascade.js +14 -4
- package/src/lib/universal-tx-detector/child-inbounds.js +9 -1
- package/src/lib/universal-tx-detector/detector.js +9 -3
- package/src/lib/universal-tx-detector/events.d.ts +3 -1
- package/src/lib/universal-tx-detector/events.js +3 -1
- package/src/lib/universal-tx-detector/normalize.d.ts +42 -0
- package/src/lib/universal-tx-detector/normalize.js +127 -0
- package/src/lib/universal-tx-detector/svm-events.d.ts +1 -1
- package/src/lib/universal-tx-detector/svm-events.js +1 -1
- package/src/lib/utils/external-tx-hash.d.ts +37 -0
- package/src/lib/utils/external-tx-hash.js +62 -0
|
@@ -112,6 +112,37 @@ function resolveR2Prc20TokenSvm(params, targetChain, pushNetwork, hasSvmExecute)
|
|
|
112
112
|
}
|
|
113
113
|
return { prc20Token, burnAmount };
|
|
114
114
|
}
|
|
115
|
+
function resolveR3SvmDrain(params, sourceChain, pushNetwork) {
|
|
116
|
+
var _a;
|
|
117
|
+
let drainAmount = BigInt(0);
|
|
118
|
+
let tokenMintHex;
|
|
119
|
+
let prc20Token = (0, helpers_1.getNativePRC20ForChain)(sourceChain, pushNetwork);
|
|
120
|
+
if (((_a = params.funds) === null || _a === void 0 ? void 0 : _a.amount) && params.funds.amount > BigInt(0)) {
|
|
121
|
+
drainAmount = params.funds.amount;
|
|
122
|
+
const token = params.funds.token;
|
|
123
|
+
if ((token === null || token === void 0 ? void 0 : token.mechanism) === 'approve') {
|
|
124
|
+
const mintPk = new web3_js_1.PublicKey(token.address);
|
|
125
|
+
tokenMintHex = ('0x' + Buffer.from(mintPk.toBytes()).toString('hex'));
|
|
126
|
+
prc20Token = push_chain_1.PushChain.utils.tokens.getPRC20Address(token).address;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else if (params.value && params.value > BigInt(0)) {
|
|
130
|
+
drainAmount = params.value;
|
|
131
|
+
}
|
|
132
|
+
return { prc20Token, drainAmount, tokenMintHex };
|
|
133
|
+
}
|
|
134
|
+
function buildR3SvmExtraPayload(ctx, params, ueaAddress, sourceChain, inboundNonce) {
|
|
135
|
+
if (!params.data) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
const executeParams = (0, helpers_1.toExecuteParams)(params);
|
|
139
|
+
const multicallCtx = Object.assign(Object.assign({}, ctx), { universalSigner: Object.assign(Object.assign({}, ctx.universalSigner), { account: Object.assign(Object.assign({}, ctx.universalSigner.account), { chain: sourceChain }) }) });
|
|
140
|
+
const multicallPayload = (0, payload_builder_1.buildMulticallPayloadData)(multicallCtx, executeParams.to, (0, payload_builders_1.buildExecuteMulticall)({ execute: executeParams, ueaAddress }));
|
|
141
|
+
const inboundPayload = (0, payload_builders_1.buildInboundUniversalPayload)(multicallPayload, {
|
|
142
|
+
nonce: inboundNonce !== null && inboundNonce !== void 0 ? inboundNonce : BigInt(0),
|
|
143
|
+
});
|
|
144
|
+
return (0, viem_1.hexToBytes)(inboundPayload);
|
|
145
|
+
}
|
|
115
146
|
/**
|
|
116
147
|
* Build the CEA-side multicall payload for a Route 2 EVM outbound. Needs the
|
|
117
148
|
* resolved `ceaAddress` because the native-value self-call branch skips the
|
|
@@ -337,6 +368,7 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
337
368
|
// --- 202: Gas estimation (spec-ordered before 203) ---
|
|
338
369
|
let gasFee = BigInt(0);
|
|
339
370
|
let protocolFee = BigInt(0);
|
|
371
|
+
let outboundGasPrice = BigInt(0);
|
|
340
372
|
let gasToken = selectors_1.ZERO_ADDRESS;
|
|
341
373
|
let universalCoreAddress;
|
|
342
374
|
if (prc20Token !== selectors_1.ZERO_ADDRESS) {
|
|
@@ -345,6 +377,7 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
345
377
|
const result = yield (0, gas_calculator_1.queryOutboundGasFee)(ctx, prc20Token, gasLimitForQuery, targetChain);
|
|
346
378
|
gasFee = result.gasFee;
|
|
347
379
|
protocolFee = result.protocolFee;
|
|
380
|
+
outboundGasPrice = result.gasPrice;
|
|
348
381
|
gasToken = result.gasToken;
|
|
349
382
|
universalCoreAddress = result.universalCoreAddress;
|
|
350
383
|
(0, context_1.printLog)(ctx, `executeUoaToCea — queried gas fee: ${gasFee.toString()}, gasToken: ${gasToken}`);
|
|
@@ -376,19 +409,20 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
376
409
|
(0, context_1.printLog)(ctx, `executeUoaToCea — MIGRATION: using raw MIGRATION_SELECTOR payload (${ceaPayload}), native PRC-20 ${prc20Token}`);
|
|
377
410
|
}
|
|
378
411
|
// Build outbound request struct for the gateway
|
|
379
|
-
//
|
|
380
|
-
//
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, gasLimitForQuery, ceaPayload, ueaAddress // revert recipient is the UEA
|
|
386
|
-
);
|
|
412
|
+
// Empty CEA payloads intentionally use zero recipient to park funds in the
|
|
413
|
+
// CEA under the post-audit single-call guard.
|
|
414
|
+
const targetBytes = ceaPayload === '0x'
|
|
415
|
+
? selectors_1.ZERO_ADDRESS
|
|
416
|
+
: ceaAddress;
|
|
417
|
+
(0, payload_builders_1.assertCeaFundsParkingInvariant)(targetBytes, ceaPayload);
|
|
418
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, gasLimitForQuery, ceaPayload, ueaAddress, // revert recipient is the UEA
|
|
419
|
+
(_d = params.maxPCForGas) !== null && _d !== void 0 ? _d : BigInt(0), outboundGasPrice);
|
|
387
420
|
(0, context_1.printLog)(ctx, `executeUoaToCea — outbound request: ${JSON.stringify({
|
|
388
421
|
target: outboundReq.target,
|
|
389
422
|
token: outboundReq.token,
|
|
390
423
|
amount: outboundReq.amount.toString(),
|
|
391
424
|
gasLimit: outboundReq.gasLimit.toString(),
|
|
425
|
+
maxPCForGas: outboundReq.maxPCForGas.toString(),
|
|
392
426
|
payloadLength: outboundReq.payload.length,
|
|
393
427
|
revertRecipient: outboundReq.revertRecipient,
|
|
394
428
|
}, null, 2)}`);
|
|
@@ -430,12 +464,16 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
430
464
|
}
|
|
431
465
|
}
|
|
432
466
|
}
|
|
433
|
-
//
|
|
467
|
+
// estimateNativeValueForSwap applies the full 2.2x safety buffer
|
|
468
|
+
// internally (pool-slippage cushion + the 10% headroom that used to be
|
|
469
|
+
// multiplied here). Folded into one place so the function's cap branch
|
|
470
|
+
// bounds the final value — the previous outer ×110/100 on top of the
|
|
471
|
+
// inner cap broke preflight whenever the cap fired. Over-send is refunded
|
|
472
|
+
// by the contract.
|
|
434
473
|
let nativeValueForGas = BigInt(0);
|
|
435
474
|
if (universalCoreAddress && gasFee > BigInt(0)) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
(0, context_1.printLog)(ctx, `executeUoaToCea — nativeValueForGas: pool-quote=${estimated.toString()}, with 10% buffer=${nativeValueForGas.toString()}`);
|
|
475
|
+
nativeValueForGas = yield (0, gas_calculator_1.estimateNativeValueForSwap)(ctx, universalCoreAddress, gasToken, gasFee, effectiveBalance);
|
|
476
|
+
(0, context_1.printLog)(ctx, `executeUoaToCea — nativeValueForGas=${nativeValueForGas.toString()} (includes 2.2x buffer)`);
|
|
439
477
|
}
|
|
440
478
|
// Hard safety cap so a broken pool price can't drain the UEA.
|
|
441
479
|
if (nativeValueForGas > EVM_NATIVE_VALUE_SAFETY_CAP) {
|
|
@@ -457,8 +495,7 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
457
495
|
args: [ueaAddress],
|
|
458
496
|
});
|
|
459
497
|
}
|
|
460
|
-
|
|
461
|
-
const preflightR2Evm = (0, preflight_1.runPreflight)({
|
|
498
|
+
(0, preflight_1.runPreflight)({
|
|
462
499
|
ctx,
|
|
463
500
|
ueaAddress,
|
|
464
501
|
ueaBalance: effectiveBalance,
|
|
@@ -468,13 +505,8 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
468
505
|
burnToken: prc20Token,
|
|
469
506
|
burnAmount,
|
|
470
507
|
prc20Balance: prc20BalanceR2Evm,
|
|
471
|
-
allowUnderfundedSwap: allowUnderfundedR2Evm,
|
|
472
508
|
});
|
|
473
|
-
|
|
474
|
-
nativeValueForGas = preflightR2Evm.legacyClampedValue;
|
|
475
|
-
(0, context_1.printLog)(ctx, `executeUoaToCea — allowUnderfundedSwap=true; using legacy clamped value ${nativeValueForGas.toString()}`);
|
|
476
|
-
}
|
|
477
|
-
// ok=true → nativeValueForGas already covers required + reserve; no adjust needed.
|
|
509
|
+
// Preflight success means nativeValueForGas already covers required + reserve; no adjust needed.
|
|
478
510
|
// Build outbound multicalls (approve burn + sendUniversalTxOutbound with native value)
|
|
479
511
|
const outboundMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
|
|
480
512
|
prc20Token,
|
|
@@ -536,7 +568,7 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
536
568
|
*/
|
|
537
569
|
function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
538
570
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
539
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
571
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
540
572
|
const targetChain = target.chain;
|
|
541
573
|
const targetAddress = target.address; // 0x-prefixed, 32 bytes
|
|
542
574
|
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
@@ -563,44 +595,49 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
563
595
|
// --- 202: Gas estimation (spec-ordered before 203) ---
|
|
564
596
|
let gasFee = BigInt(0);
|
|
565
597
|
let protocolFeeSvm = BigInt(0);
|
|
598
|
+
let outboundGasPriceSvm = BigInt(0);
|
|
566
599
|
let gasToken = selectors_1.ZERO_ADDRESS;
|
|
567
600
|
let universalCoreAddress;
|
|
568
601
|
// Effective gas limit seeded from the user param. When the user omits
|
|
569
|
-
// gasLimit, it'll be derived from the
|
|
570
|
-
//
|
|
602
|
+
// gasLimit, it'll be derived from the gas quote so the on-chain record
|
|
603
|
+
// carries a non-zero compute budget the relay can use.
|
|
571
604
|
let effectiveGasLimit = (_d = params.gasLimit) !== null && _d !== void 0 ? _d : BigInt(0);
|
|
572
|
-
//
|
|
573
|
-
//
|
|
574
|
-
//
|
|
575
|
-
//
|
|
576
|
-
//
|
|
577
|
-
const
|
|
578
|
-
? (
|
|
605
|
+
// SVM finalize budget: the Solana gateway requires gas_fee to cover the
|
|
606
|
+
// relayer signature fee, ExecutedSubTx rent, a compute buffer, and
|
|
607
|
+
// conditionally CEA ATA rent for SPL outbounds. The on-chain quote can be
|
|
608
|
+
// below that floor, so we compare the quoted fee in lamports and re-query
|
|
609
|
+
// with a bumped gasLimit when required.
|
|
610
|
+
const svmFundsToken = burnAmount > BigInt(0)
|
|
611
|
+
? (_e = params.funds) === null || _e === void 0 ? void 0 : _e.token
|
|
579
612
|
: undefined;
|
|
580
|
-
|
|
581
|
-
ctx,
|
|
582
|
-
ueaAddress,
|
|
583
|
-
targetChain,
|
|
584
|
-
splMintBase58,
|
|
585
|
-
burnAmount,
|
|
586
|
-
effectiveGasLimit,
|
|
587
|
-
});
|
|
613
|
+
const splMintBase58 = (svmFundsToken === null || svmFundsToken === void 0 ? void 0 : svmFundsToken.mechanism) === 'approve' ? svmFundsToken.address : undefined;
|
|
588
614
|
if (prc20Token !== selectors_1.ZERO_ADDRESS) {
|
|
589
615
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_202_01, targetChain);
|
|
590
616
|
try {
|
|
591
|
-
|
|
617
|
+
let result = yield (0, gas_calculator_1.queryOutboundGasFee)(ctx, prc20Token, effectiveGasLimit, targetChain);
|
|
618
|
+
result = yield (0, svm_rent_1.ensureSvmFinalizeGasBudgetQuote)({
|
|
619
|
+
ctx,
|
|
620
|
+
ueaAddress,
|
|
621
|
+
targetChain,
|
|
622
|
+
prc20Token,
|
|
623
|
+
quote: result,
|
|
624
|
+
splMintBase58,
|
|
625
|
+
burnAmount,
|
|
626
|
+
pathTag: 'executeUoaToCeaSvm',
|
|
627
|
+
});
|
|
592
628
|
gasFee = result.gasFee;
|
|
593
629
|
protocolFeeSvm = result.protocolFee;
|
|
630
|
+
outboundGasPriceSvm = result.gasPrice;
|
|
594
631
|
gasToken = result.gasToken;
|
|
595
632
|
universalCoreAddress = result.universalCoreAddress;
|
|
596
|
-
// When user omits gasLimit (sent as 0), the contract computes fees using
|
|
597
|
-
// baseGasLimitByChainNamespace. But the relay reads the
|
|
598
|
-
//
|
|
599
|
-
//
|
|
600
|
-
|
|
601
|
-
if (!params.gasLimit
|
|
602
|
-
effectiveGasLimit
|
|
603
|
-
|
|
633
|
+
// When user omits gasLimit (sent as 0), the contract computes fees using
|
|
634
|
+
// its internal baseGasLimitByChainNamespace. But the relay reads the
|
|
635
|
+
// stored gasLimit from the outbound record. Store the resolved value from
|
|
636
|
+
// UniversalCore so the relayer has a non-zero SVM budget.
|
|
637
|
+
effectiveGasLimit = result.gasLimitUsed;
|
|
638
|
+
if (!params.gasLimit) {
|
|
639
|
+
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — resolved effectiveGasLimit: ${effectiveGasLimit} ` +
|
|
640
|
+
`(gasFee=${result.gasFee}, gasPrice=${result.gasPrice})`);
|
|
604
641
|
}
|
|
605
642
|
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — queried gas fee: ${gasFee.toString()}, gasToken: ${gasToken}`);
|
|
606
643
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_202_02, targetChain, protocolFeeSvm, gasFee);
|
|
@@ -616,13 +653,14 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
616
653
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_203_02, ueaAddress, targetAddress, targetChain, true);
|
|
617
654
|
// --- Build outbound request ---
|
|
618
655
|
// targetBytes: for execute = program id (resolver output); for withdraw = to.address
|
|
619
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, effectiveGasLimit, svmPayload, ueaAddress // revert recipient is the UEA
|
|
620
|
-
);
|
|
656
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, effectiveGasLimit, svmPayload, ueaAddress, // revert recipient is the UEA
|
|
657
|
+
(_f = params.maxPCForGas) !== null && _f !== void 0 ? _f : BigInt(0), outboundGasPriceSvm);
|
|
621
658
|
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — outbound request: ${JSON.stringify({
|
|
622
659
|
target: outboundReq.target,
|
|
623
660
|
token: outboundReq.token,
|
|
624
661
|
amount: outboundReq.amount.toString(),
|
|
625
662
|
gasLimit: outboundReq.gasLimit.toString(),
|
|
663
|
+
maxPCForGas: outboundReq.maxPCForGas.toString(),
|
|
626
664
|
payloadLength: (outboundReq.payload.length - 2) / 2,
|
|
627
665
|
revertRecipient: outboundReq.revertRecipient,
|
|
628
666
|
}, null, 2)}`);
|
|
@@ -648,8 +686,10 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
648
686
|
}
|
|
649
687
|
const ueaNonce = (!isUEADeployed || isNativePushEOASvm) ? BigInt(0) : yield (0, uea_manager_1.getUEANonce)(ctx, ueaAddress);
|
|
650
688
|
// R2 does NOT use Case A/B/C gas abstraction (scoped to R1 + R3 only).
|
|
651
|
-
// Size msg.value from the live WPC/gasToken Uniswap V3 pool quote
|
|
652
|
-
//
|
|
689
|
+
// Size msg.value from the live WPC/gasToken Uniswap V3 pool quote. The
|
|
690
|
+
// 2.2x safety buffer is applied inside estimateNativeValueForSwap (was
|
|
691
|
+
// split as inner 2x + outer 10% — combined to keep the cap branch
|
|
692
|
+
// mathematically correct). swapAndBurnGas refunds the excess as PC via
|
|
653
693
|
// refundUnusedGas.
|
|
654
694
|
//
|
|
655
695
|
// SVM pools (WPC/pSOL) are thinner than EVM pools so the pool-quote can
|
|
@@ -664,9 +704,10 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
664
704
|
const SVM_GAS_RESERVE = BigInt(3e18); // 3 UPC for outer-tx gas
|
|
665
705
|
let nativeValueForGas = BigInt(0);
|
|
666
706
|
if (universalCoreAddress && gasFee > BigInt(0)) {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
(0,
|
|
707
|
+
// 2.2x safety buffer is applied inside estimateNativeValueForSwap so
|
|
708
|
+
// the function's balance-cap branch bounds the final value correctly.
|
|
709
|
+
nativeValueForGas = yield (0, gas_calculator_1.estimateNativeValueForSwap)(ctx, universalCoreAddress, gasToken, gasFee, ueaBalance);
|
|
710
|
+
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — nativeValueForGas=${nativeValueForGas.toString()} (includes 2.2x buffer)`);
|
|
670
711
|
(0, preflight_1.maybeFireSvmWarnThreshold)(ctx, nativeValueForGas, gasToken, 'R2_SVM');
|
|
671
712
|
}
|
|
672
713
|
// Pre-flight: throws InsufficientUEABalanceError when UEA cannot cover
|
|
@@ -688,8 +729,7 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
688
729
|
args: [ueaAddress],
|
|
689
730
|
});
|
|
690
731
|
}
|
|
691
|
-
|
|
692
|
-
const preflightR2Svm = (0, preflight_1.runPreflight)({
|
|
732
|
+
(0, preflight_1.runPreflight)({
|
|
693
733
|
ctx,
|
|
694
734
|
ueaAddress,
|
|
695
735
|
ueaBalance,
|
|
@@ -699,12 +739,7 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
699
739
|
burnToken: prc20Token,
|
|
700
740
|
burnAmount,
|
|
701
741
|
prc20Balance: prc20BalanceR2Svm,
|
|
702
|
-
allowUnderfundedSwap: allowUnderfundedR2Svm,
|
|
703
742
|
});
|
|
704
|
-
if (!preflightR2Svm.ok) {
|
|
705
|
-
nativeValueForGas = preflightR2Svm.legacyClampedValue;
|
|
706
|
-
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — allowUnderfundedSwap=true; using legacy clamped value ${nativeValueForGas.toString()}`);
|
|
707
|
-
}
|
|
708
743
|
// --- Build Push Chain multicalls (approve + sendUniversalTxOutbound) ---
|
|
709
744
|
// Reuse the same builder as EVM — this part is identical
|
|
710
745
|
const pushChainMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
|
|
@@ -769,7 +804,7 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
769
804
|
*/
|
|
770
805
|
function executeCeaToPush(ctx, params, executeFn) {
|
|
771
806
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
772
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
807
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
773
808
|
// 1. Validate and extract source chain
|
|
774
809
|
if (!((_a = params.from) === null || _a === void 0 ? void 0 : _a.chain)) {
|
|
775
810
|
throw new Error('Route 3 (CEA -> Push) requires from.chain to specify the source CEA chain');
|
|
@@ -806,11 +841,6 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
806
841
|
(0, context_1.printLog)(ctx, `executeCeaToPush — sourceChain: ${sourceChain}, CEA: ${ceaAddress}, deployed: ${ceaDeployed}`);
|
|
807
842
|
// CEA auto-deploys on-chain: Vault.finalizeUniversalTx calls CEAFactory.deployCEA()
|
|
808
843
|
// if CEA doesn't exist yet. No SDK-side blocking needed.
|
|
809
|
-
// 5. Get UniversalGateway address on source chain
|
|
810
|
-
const gatewayAddress = chain_1.UNIVERSAL_GATEWAY_ADDRESSES[sourceChain];
|
|
811
|
-
if (!gatewayAddress) {
|
|
812
|
-
throw new Error(`No UniversalGateway address configured for chain ${sourceChain}`);
|
|
813
|
-
}
|
|
814
844
|
// 6. Build multicall for CEA to execute on source chain (self-calls via sendUniversalTxToUEA)
|
|
815
845
|
const ceaMulticalls = [];
|
|
816
846
|
// Determine token and amount for sendUniversalTxToUEA
|
|
@@ -826,7 +856,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
826
856
|
amount = params.funds.amount;
|
|
827
857
|
}
|
|
828
858
|
else {
|
|
829
|
-
// ERC20 token
|
|
859
|
+
// ERC20 token. CEA handles gateway approval internally around sendUniversalTxToUEA.
|
|
830
860
|
tokenAddress = token.address;
|
|
831
861
|
amount = params.funds.amount;
|
|
832
862
|
}
|
|
@@ -843,33 +873,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
843
873
|
// query and relay execution, causing sendUniversalTxToUEA to revert with
|
|
844
874
|
// InsufficientBalance. Pre-existing CEA funds remain parked and can be swept separately.
|
|
845
875
|
const bridgeAmount = amount;
|
|
846
|
-
//
|
|
847
|
-
// Keeping bridgeAmount as-is (0) for payload-only to test precompile behavior.
|
|
848
|
-
// For ERC20 tokens, add approve call for the bridge amount
|
|
849
|
-
// (CEA approves gateway to spend the Vault-deposited amount)
|
|
850
|
-
// Reset to 0 first for USDT-style tokens that revert on non-zero to non-zero approve.
|
|
851
|
-
if (tokenAddress !== selectors_1.ZERO_ADDRESS && bridgeAmount > BigInt(0)) {
|
|
852
|
-
const approveZeroData = (0, viem_1.encodeFunctionData)({
|
|
853
|
-
abi: erc20_evm_1.ERC20_EVM,
|
|
854
|
-
functionName: 'approve',
|
|
855
|
-
args: [gatewayAddress, BigInt(0)],
|
|
856
|
-
});
|
|
857
|
-
ceaMulticalls.push({
|
|
858
|
-
to: tokenAddress,
|
|
859
|
-
value: BigInt(0),
|
|
860
|
-
data: approveZeroData,
|
|
861
|
-
});
|
|
862
|
-
const approveData = (0, viem_1.encodeFunctionData)({
|
|
863
|
-
abi: erc20_evm_1.ERC20_EVM,
|
|
864
|
-
functionName: 'approve',
|
|
865
|
-
args: [gatewayAddress, bridgeAmount],
|
|
866
|
-
});
|
|
867
|
-
ceaMulticalls.push({
|
|
868
|
-
to: tokenAddress,
|
|
869
|
-
value: BigInt(0),
|
|
870
|
-
data: approveData,
|
|
871
|
-
});
|
|
872
|
-
}
|
|
876
|
+
// The post-audit CEA allows amount=0 for payload-only sendUniversalTxToUEA.
|
|
873
877
|
// Pre-fetch UEA nonce — needed for the inbound UniversalPayload struct
|
|
874
878
|
// Skip getCode if accountStatusCache already confirmed deployment
|
|
875
879
|
let isUEADeployed;
|
|
@@ -903,8 +907,8 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
903
907
|
// so the inbound will arrive when the UEA nonce is already incremented.
|
|
904
908
|
pushPayload = (0, payload_builders_1.buildInboundUniversalPayload)(multicallPayload, { nonce: ueaNonce + BigInt(1) });
|
|
905
909
|
}
|
|
906
|
-
// Build sendUniversalTxToUEA self-call on CEA
|
|
907
|
-
//
|
|
910
|
+
// Build sendUniversalTxToUEA self-call on CEA. CEA self-calls must always
|
|
911
|
+
// use value=0; native sends spend from the CEA's existing balance.
|
|
908
912
|
// CEA internally calls gateway.sendUniversalTxFromCEA(...)
|
|
909
913
|
// Uses bridgeAmount (= burn amount deposited by Vault)
|
|
910
914
|
const sendUniversalTxCall = (0, payload_builders_1.buildSendUniversalTxToUEA)(ceaAddress, // to: CEA address (self-call)
|
|
@@ -929,20 +933,22 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
929
933
|
// tokens FROM the CEA back to Push Chain, not to round-trip them.
|
|
930
934
|
const prc20Token = (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork);
|
|
931
935
|
const burnAmount = BigInt(0);
|
|
936
|
+
const outboundGasLimit = (_f = params.gasLimit) !== null && _f !== void 0 ? _f : selectors_1.DEFAULT_CEA_TO_PUSH_GAS_LIMIT;
|
|
932
937
|
(0, context_1.printLog)(ctx, `executeCeaToPush — prc20Token: ${prc20Token}, burnAmount: ${burnAmount.toString()}`);
|
|
933
938
|
// 9. Build outbound request (same structure as Route 2)
|
|
934
939
|
// target = CEA address (for self-execution), value = 0 in payload
|
|
935
|
-
|
|
940
|
+
let outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, // target: CEA address (to=CEA for self-execution)
|
|
936
941
|
prc20Token, // token: native PRC-20 for source chain (for namespace lookup)
|
|
937
942
|
burnAmount, // amount: 0 (payload-only, CEA uses its own balance)
|
|
938
|
-
|
|
939
|
-
ueaAddress // revertRecipient: UEA
|
|
940
|
-
);
|
|
943
|
+
outboundGasLimit, ceaPayload, // payload: ABI-encoded CEA multicall
|
|
944
|
+
ueaAddress, // revertRecipient: UEA
|
|
945
|
+
(_g = params.maxPCForGas) !== null && _g !== void 0 ? _g : BigInt(0));
|
|
941
946
|
(0, context_1.printLog)(ctx, `executeCeaToPush — outbound request: ${JSON.stringify({
|
|
942
947
|
target: outboundReq.target,
|
|
943
948
|
token: outboundReq.token,
|
|
944
949
|
amount: outboundReq.amount.toString(),
|
|
945
950
|
gasLimit: outboundReq.gasLimit.toString(),
|
|
951
|
+
maxPCForGas: outboundReq.maxPCForGas.toString(),
|
|
946
952
|
payloadLength: outboundReq.payload.length,
|
|
947
953
|
revertRecipient: outboundReq.revertRecipient,
|
|
948
954
|
}, null, 2)}`);
|
|
@@ -953,20 +959,22 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
953
959
|
// 11. Query gas fees from UniversalCore
|
|
954
960
|
let gasFee = BigInt(0);
|
|
955
961
|
let protocolFeeR3 = BigInt(0);
|
|
962
|
+
let outboundGasPriceR3 = BigInt(0);
|
|
956
963
|
let nativeValueForGas = BigInt(0);
|
|
957
964
|
let gasToken = selectors_1.ZERO_ADDRESS;
|
|
958
965
|
let sizingDecisionR3;
|
|
959
966
|
if (prc20Token !== selectors_1.ZERO_ADDRESS) {
|
|
960
|
-
const gasLimit = outboundReq.gasLimit;
|
|
961
967
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_302_01, sourceChain);
|
|
962
968
|
try {
|
|
963
|
-
const result = yield (0, gas_calculator_1.queryOutboundGasFee)(ctx, prc20Token,
|
|
969
|
+
const result = yield (0, gas_calculator_1.queryOutboundGasFee)(ctx, prc20Token, outboundGasLimit, sourceChain);
|
|
964
970
|
gasToken = result.gasToken;
|
|
965
971
|
gasFee = result.gasFee;
|
|
972
|
+
outboundGasPriceR3 = result.gasPrice;
|
|
966
973
|
protocolFeeR3 = result.protocolFee;
|
|
967
974
|
nativeValueForGas = result.nativeValueForGas;
|
|
968
975
|
sizingDecisionR3 = result.sizing;
|
|
969
|
-
(0,
|
|
976
|
+
outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, outboundGasLimit, ceaPayload, ueaAddress, (_h = params.maxPCForGas) !== null && _h !== void 0 ? _h : BigInt(0), outboundGasPriceR3);
|
|
977
|
+
(0, context_1.printLog)(ctx, `executeCeaToPush — queried gas fee: ${gasFee.toString()}, gasToken: ${gasToken}, nativeValueForGas: ${nativeValueForGas.toString()}, sizing=${(_k = (_j = result.sizing) === null || _j === void 0 ? void 0 : _j.category) !== null && _k !== void 0 ? _k : 'legacy'}`);
|
|
970
978
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_302_02, sourceChain, protocolFeeR3, gasFee);
|
|
971
979
|
}
|
|
972
980
|
catch (err) {
|
|
@@ -1040,20 +1048,14 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
1040
1048
|
// Pre-flight (R3 EVM): no PRC-20 burn check — `burnAmount = 0` makes this
|
|
1041
1049
|
// payload-only (UEA never holds the source-chain PRC-20; see plan §9 #4).
|
|
1042
1050
|
// Native UPC check still applies for the gas swap.
|
|
1043
|
-
|
|
1044
|
-
const preflightR3Evm = (0, preflight_1.runPreflight)({
|
|
1051
|
+
(0, preflight_1.runPreflight)({
|
|
1045
1052
|
ctx,
|
|
1046
1053
|
ueaAddress,
|
|
1047
1054
|
ueaBalance: effectiveBalance,
|
|
1048
1055
|
requiredValue: nativeValueForGas,
|
|
1049
1056
|
gasReserve: OUTBOUND_GAS_RESERVE_R3,
|
|
1050
1057
|
pathTag: 'R3_EVM',
|
|
1051
|
-
allowUnderfundedSwap: allowUnderfundedR3Evm,
|
|
1052
1058
|
});
|
|
1053
|
-
if (!preflightR3Evm.ok) {
|
|
1054
|
-
nativeValueForGas = preflightR3Evm.legacyClampedValue;
|
|
1055
|
-
(0, context_1.printLog)(ctx, `executeCeaToPush — allowUnderfundedSwap=true; using legacy clamped value ${nativeValueForGas.toString()}`);
|
|
1056
|
-
}
|
|
1057
1059
|
// 12. Build Push Chain multicalls (approvals + sendUniversalTxOutbound)
|
|
1058
1060
|
const pushChainMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
|
|
1059
1061
|
prc20Token,
|
|
@@ -1132,41 +1134,31 @@ function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
|
1132
1134
|
const gatewayProgramHex = ('0x' + Buffer.from(programPk.toBytes()).toString('hex'));
|
|
1133
1135
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_301, sourceChain, lockerContract);
|
|
1134
1136
|
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — sourceChain: ${sourceChain}, gateway: ${lockerContract}`);
|
|
1135
|
-
//
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
drainAmount = params.funds.amount;
|
|
1141
|
-
const token = params.funds.token;
|
|
1142
|
-
if (token && token.address) {
|
|
1143
|
-
// Convert SPL mint address to 32-byte hex
|
|
1144
|
-
const mintPk = new web3_js_1.PublicKey(token.address);
|
|
1145
|
-
tokenMintHex = ('0x' + Buffer.from(mintPk.toBytes()).toString('hex'));
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
else if (params.value && params.value > BigInt(0)) {
|
|
1149
|
-
// Native SOL drain
|
|
1150
|
-
drainAmount = params.value;
|
|
1151
|
-
}
|
|
1152
|
-
// Route 3 SVM: ALWAYS use native PRC-20 for chain namespace lookup + gas fees.
|
|
1153
|
-
// CEA uses its own pre-existing balance — no PRC-20 burn needed on Push Chain.
|
|
1154
|
-
const prc20Token = (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork);
|
|
1155
|
-
// Build the SVM CPI payload (send_universal_tx_to_uea wrapped in execute)
|
|
1156
|
-
// If params.data is provided, pass it as extraPayload for Push Chain execution
|
|
1157
|
-
let extraPayload;
|
|
1158
|
-
if (params.data && typeof params.data === 'string') {
|
|
1159
|
-
extraPayload = (0, viem_1.hexToBytes)(params.data);
|
|
1160
|
-
}
|
|
1137
|
+
// Route 3 SVM: CEA uses its own pre-existing balance — no PRC-20 burn
|
|
1138
|
+
// needed on Push Chain. The outer request token must still match the source
|
|
1139
|
+
// asset so the relayer supplies the same Solana mint that the payload
|
|
1140
|
+
// encodes; otherwise the gateway rejects with InvalidMint.
|
|
1141
|
+
const { prc20Token, drainAmount, tokenMintHex } = resolveR3SvmDrain(params, sourceChain, ctx.pushNetwork);
|
|
1161
1142
|
// Derive CEA PDA as revert recipient: ["push_identity", ueaAddress_20_bytes]
|
|
1162
1143
|
const ueaBytes = Buffer.from(ueaAddress.slice(2), 'hex'); // 20 bytes
|
|
1163
1144
|
const [ceaPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('push_identity'), ueaBytes], programPk);
|
|
1164
1145
|
const ceaPdaHex = ('0x' + Buffer.from(ceaPda.toBytes()).toString('hex'));
|
|
1146
|
+
// Pre-fetch UEA status before payload construction. The inbound
|
|
1147
|
+
// UniversalPayload must use the nonce after this outbound execution, because
|
|
1148
|
+
// the Push-side execute() below consumes one UEA nonce before the Solana
|
|
1149
|
+
// round-trip payload returns.
|
|
1150
|
+
const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
|
|
1151
|
+
const [ueaCode, ueaBalance] = yield Promise.all([
|
|
1152
|
+
ctx.pushClient.publicClient.getCode({ address: ueaAddress }),
|
|
1153
|
+
ctx.pushClient.getBalance(ueaAddress),
|
|
1154
|
+
]);
|
|
1155
|
+
const isUEADeployed = ueaCode !== undefined;
|
|
1156
|
+
const ueaNonce = isUEADeployed ? yield (0, uea_manager_1.getUEANonce)(ctx, ueaAddress) : BigInt(0);
|
|
1165
1157
|
const svmPayload = (0, payload_builders_1.encodeSvmCeaToUeaPayload)({
|
|
1166
1158
|
gatewayProgramHex,
|
|
1167
1159
|
drainAmount,
|
|
1168
1160
|
tokenMintHex,
|
|
1169
|
-
extraPayload,
|
|
1161
|
+
extraPayload: buildR3SvmExtraPayload(ctx, params, ueaAddress, sourceChain, ueaNonce + BigInt(1)),
|
|
1170
1162
|
revertRecipientHex: ceaPdaHex,
|
|
1171
1163
|
});
|
|
1172
1164
|
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — drainAmount: ${drainAmount.toString()}, payload length: ${(svmPayload.length - 2) / 2} bytes`);
|
|
@@ -1177,33 +1169,42 @@ function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
|
1177
1169
|
// (e.g. pSOL). The UGPC upgrade post-2026-03-19 already accepts amount = 0
|
|
1178
1170
|
// on the cascade path, and the same precompile is used here.
|
|
1179
1171
|
const burnAmount = BigInt(0);
|
|
1172
|
+
let effectiveGasLimit = (_a = params.gasLimit) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
1180
1173
|
// Build outbound request: target = gateway program (self-call)
|
|
1181
|
-
|
|
1182
|
-
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — outbound request: target=${outboundReq.target.slice(0, 20)}..., token=${outboundReq.token}`);
|
|
1183
|
-
// Pre-fetch UEA status early — balance is needed for gas value calculation
|
|
1184
|
-
const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
|
|
1185
|
-
const [ueaCode, ueaBalance] = yield Promise.all([
|
|
1186
|
-
ctx.pushClient.publicClient.getCode({ address: ueaAddress }),
|
|
1187
|
-
ctx.pushClient.getBalance(ueaAddress),
|
|
1188
|
-
]);
|
|
1189
|
-
const isUEADeployed = ueaCode !== undefined;
|
|
1190
|
-
const ueaNonce = isUEADeployed ? yield (0, uea_manager_1.getUEANonce)(ctx, ueaAddress) : BigInt(0);
|
|
1174
|
+
let outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, prc20Token, burnAmount, effectiveGasLimit, svmPayload, ueaAddress, (_b = params.maxPCForGas) !== null && _b !== void 0 ? _b : BigInt(0));
|
|
1175
|
+
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — outbound request: target=${outboundReq.target.slice(0, 20)}..., token=${outboundReq.token}, maxPCForGas=${outboundReq.maxPCForGas}`);
|
|
1191
1176
|
// Query gas fees
|
|
1192
1177
|
let gasFee = BigInt(0);
|
|
1193
1178
|
let protocolFeeR3Svm = BigInt(0);
|
|
1179
|
+
let outboundGasPriceR3Svm = BigInt(0);
|
|
1194
1180
|
let nativeValueForGas = BigInt(0);
|
|
1195
1181
|
let gasToken = selectors_1.ZERO_ADDRESS;
|
|
1196
1182
|
let sizingDecisionR3Svm;
|
|
1197
1183
|
if (prc20Token !== selectors_1.ZERO_ADDRESS) {
|
|
1198
1184
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_302_01, sourceChain);
|
|
1199
1185
|
try {
|
|
1200
|
-
|
|
1186
|
+
let result = yield (0, gas_calculator_1.queryOutboundGasFee)(ctx, prc20Token, outboundReq.gasLimit, sourceChain);
|
|
1187
|
+
result = yield (0, svm_rent_1.ensureSvmFinalizeGasBudgetQuote)({
|
|
1188
|
+
ctx,
|
|
1189
|
+
ueaAddress,
|
|
1190
|
+
targetChain: sourceChain,
|
|
1191
|
+
prc20Token,
|
|
1192
|
+
quote: result,
|
|
1193
|
+
splMintBase58: undefined,
|
|
1194
|
+
burnAmount: BigInt(0),
|
|
1195
|
+
pathTag: 'executeCeaToPushSvm',
|
|
1196
|
+
});
|
|
1201
1197
|
gasToken = result.gasToken;
|
|
1202
1198
|
gasFee = result.gasFee;
|
|
1199
|
+
outboundGasPriceR3Svm = result.gasPrice;
|
|
1203
1200
|
protocolFeeR3Svm = result.protocolFee;
|
|
1204
1201
|
nativeValueForGas = result.nativeValueForGas;
|
|
1205
1202
|
sizingDecisionR3Svm = result.sizing;
|
|
1206
|
-
|
|
1203
|
+
effectiveGasLimit = result.gasLimitUsed;
|
|
1204
|
+
outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, prc20Token, burnAmount, effectiveGasLimit, svmPayload, ueaAddress, (_c = params.maxPCForGas) !== null && _c !== void 0 ? _c : BigInt(0), outboundGasPriceR3Svm);
|
|
1205
|
+
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — resolved effectiveGasLimit: ${effectiveGasLimit} ` +
|
|
1206
|
+
`(gasFee=${result.gasFee}, gasPrice=${result.gasPrice})`);
|
|
1207
|
+
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — gasFee: ${gasFee.toString()}, gasToken: ${gasToken}, nativeValueForGas: ${nativeValueForGas.toString()}, sizing=${(_e = (_d = result.sizing) === null || _d === void 0 ? void 0 : _d.category) !== null && _e !== void 0 ? _e : 'legacy'}`);
|
|
1207
1208
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_302_02, sourceChain, protocolFeeR3Svm, gasFee);
|
|
1208
1209
|
}
|
|
1209
1210
|
catch (err) {
|
|
@@ -1263,23 +1264,16 @@ function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
|
1263
1264
|
}
|
|
1264
1265
|
// SVM warn-threshold telemetry (no truncation — pre-flight handles drain protection).
|
|
1265
1266
|
(0, preflight_1.maybeFireSvmWarnThreshold)(ctx, nativeValueForGas, gasToken, 'R3_SVM');
|
|
1266
|
-
// Pre-flight (R3 SVM): no PRC-20 burn check
|
|
1267
|
-
//
|
|
1268
|
-
|
|
1269
|
-
const allowUnderfundedR3Svm = ((_e = params.options) === null || _e === void 0 ? void 0 : _e.allowUnderfundedSwap) === true;
|
|
1270
|
-
const preflightR3Svm = (0, preflight_1.runPreflight)({
|
|
1267
|
+
// Pre-flight (R3 SVM): no PRC-20 burn check. R3 SVM uses burnAmount=0
|
|
1268
|
+
// because the drain amount lives inside the SVM instruction data.
|
|
1269
|
+
(0, preflight_1.runPreflight)({
|
|
1271
1270
|
ctx,
|
|
1272
1271
|
ueaAddress,
|
|
1273
1272
|
ueaBalance: currentBalance,
|
|
1274
1273
|
requiredValue: nativeValueForGas,
|
|
1275
1274
|
gasReserve: OUTBOUND_GAS_RESERVE_R3_SVM,
|
|
1276
1275
|
pathTag: 'R3_SVM',
|
|
1277
|
-
allowUnderfundedSwap: allowUnderfundedR3Svm,
|
|
1278
1276
|
});
|
|
1279
|
-
if (!preflightR3Svm.ok) {
|
|
1280
|
-
nativeValueForGas = preflightR3Svm.legacyClampedValue;
|
|
1281
|
-
(0, context_1.printLog)(ctx, `executeCeaToPushSvm — allowUnderfundedSwap=true; using legacy clamped value ${nativeValueForGas.toString()}`);
|
|
1282
|
-
}
|
|
1283
1277
|
// Build Push Chain multicalls (approvals + sendUniversalTxOutbound)
|
|
1284
1278
|
const pushChainMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
|
|
1285
1279
|
prc20Token,
|
|
@@ -1316,17 +1310,11 @@ function executeCeaToPushSvm(ctx, params, sourceChain, executeFn) {
|
|
|
1316
1310
|
response.chain = sourceChain;
|
|
1317
1311
|
const chainInfo = chain_1.CHAIN_INFO[sourceChain];
|
|
1318
1312
|
response.chainNamespace = `${chain_1.VM_NAMESPACE[chainInfo.vm]}:${chainInfo.chainId}`;
|
|
1319
|
-
// R3 SVM
|
|
1320
|
-
//
|
|
1321
|
-
//
|
|
1322
|
-
//
|
|
1323
|
-
|
|
1324
|
-
// log — the parent utxId's `outboundStatus=OBSERVED` is the terminal state.
|
|
1325
|
-
// Polling for a deterministically-derived child id therefore never
|
|
1326
|
-
// resolves, and the cosmos `inbound_tx_hash` text-search fallback also
|
|
1327
|
-
// returns 0 hits. Receipts now resolve as soon as the Solana outbound is
|
|
1328
|
-
// observed instead of timing out at 300s.
|
|
1329
|
-
response._expectsInboundRoundTrip = false;
|
|
1313
|
+
// R3 SVM mirrors EVM R3: when funds drain back to Push, the Solana-side
|
|
1314
|
+
// send_universal_tx_to_uea emits an inbound leg whose payload can execute on
|
|
1315
|
+
// Push. Payload-only R3 has no child inbound UTX, so skip round-trip tracking
|
|
1316
|
+
// when no amount is being drained.
|
|
1317
|
+
response._expectsInboundRoundTrip = drainAmount > BigInt(0);
|
|
1330
1318
|
return response;
|
|
1331
1319
|
});
|
|
1332
1320
|
}
|
|
@@ -1352,7 +1340,7 @@ function executeCeaToCea(ctx, params, executeFn) {
|
|
|
1352
1340
|
*/
|
|
1353
1341
|
function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
1354
1342
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
1355
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
1343
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
1356
1344
|
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
1357
1345
|
switch (route) {
|
|
1358
1346
|
case route_detector_1.TransactionRoute.UOA_TO_PUSH: {
|
|
@@ -1396,13 +1384,13 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1396
1384
|
}
|
|
1397
1385
|
else if (hasExecute) {
|
|
1398
1386
|
prc20Token = (0, helpers_1.getNativePRC20ForChain)(target.chain, ctx.pushNetwork);
|
|
1399
|
-
burnAmount = BigInt(
|
|
1387
|
+
burnAmount = BigInt(0);
|
|
1400
1388
|
}
|
|
1401
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (_b = params.gasLimit) !== null && _b !== void 0 ? _b : BigInt(0), payload, ueaAddress);
|
|
1389
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (_b = params.gasLimit) !== null && _b !== void 0 ? _b : BigInt(0), payload, ueaAddress, (_c = params.maxPCForGas) !== null && _c !== void 0 ? _c : BigInt(0));
|
|
1402
1390
|
return { payload, gatewayRequest: outboundReq };
|
|
1403
1391
|
}
|
|
1404
1392
|
// EVM path: Resolve CEA address first (needed for self-transfer check)
|
|
1405
|
-
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, target.chain, (
|
|
1393
|
+
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, target.chain, (_d = ctx.rpcUrls[target.chain]) === null || _d === void 0 ? void 0 : _d[0]);
|
|
1406
1394
|
// Build CEA outbound payload
|
|
1407
1395
|
const multicalls = [];
|
|
1408
1396
|
if (params.data) {
|
|
@@ -1435,21 +1423,24 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1435
1423
|
const payload = (0, payload_builders_1.buildCeaMulticallPayload)(multicalls);
|
|
1436
1424
|
let prc20Token = selectors_1.ZERO_ADDRESS;
|
|
1437
1425
|
let burnAmount = BigInt(0);
|
|
1438
|
-
if ((
|
|
1426
|
+
if ((_e = params.funds) === null || _e === void 0 ? void 0 : _e.amount) {
|
|
1439
1427
|
const token = params.funds.token;
|
|
1440
1428
|
if (token) {
|
|
1441
1429
|
prc20Token = push_chain_1.PushChain.utils.tokens.getPRC20Address(token).address;
|
|
1442
1430
|
burnAmount = params.funds.amount;
|
|
1443
1431
|
}
|
|
1444
1432
|
}
|
|
1445
|
-
const targetBytes =
|
|
1446
|
-
|
|
1433
|
+
const targetBytes = payload === '0x'
|
|
1434
|
+
? selectors_1.ZERO_ADDRESS
|
|
1435
|
+
: ceaAddress;
|
|
1436
|
+
(0, payload_builders_1.assertCeaFundsParkingInvariant)(targetBytes, payload);
|
|
1437
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (_f = params.gasLimit) !== null && _f !== void 0 ? _f : BigInt(0), payload, ueaAddress, (_g = params.maxPCForGas) !== null && _g !== void 0 ? _g : BigInt(0));
|
|
1447
1438
|
return { payload, gatewayRequest: outboundReq };
|
|
1448
1439
|
}
|
|
1449
1440
|
case route_detector_1.TransactionRoute.CEA_TO_PUSH: {
|
|
1450
1441
|
// Route 3: CEA -> Push Chain
|
|
1451
|
-
// Build CEA multicall (
|
|
1452
|
-
if (!((
|
|
1442
|
+
// Build CEA multicall (sendUniversalTxToUEA self-call) and wrap in outbound
|
|
1443
|
+
if (!((_h = params.from) === null || _h === void 0 ? void 0 : _h.chain)) {
|
|
1453
1444
|
throw new Error('Route 3 (CEA -> Push) requires from.chain');
|
|
1454
1445
|
}
|
|
1455
1446
|
const sourceChain = params.from.chain;
|
|
@@ -1462,21 +1453,7 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1462
1453
|
}
|
|
1463
1454
|
const programPk = new web3_js_1.PublicKey(lockerContract);
|
|
1464
1455
|
const gatewayProgramHex = ('0x' + Buffer.from(programPk.toBytes()).toString('hex'));
|
|
1465
|
-
|
|
1466
|
-
let tokenMintHex;
|
|
1467
|
-
if (((_g = params.funds) === null || _g === void 0 ? void 0 : _g.amount) && params.funds.amount > BigInt(0)) {
|
|
1468
|
-
drainAmount = params.funds.amount;
|
|
1469
|
-
const token = params.funds.token;
|
|
1470
|
-
if (token && token.address) {
|
|
1471
|
-
const mintPk = new web3_js_1.PublicKey(token.address);
|
|
1472
|
-
tokenMintHex = ('0x' + Buffer.from(mintPk.toBytes()).toString('hex'));
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
else if (params.value && params.value > BigInt(0)) {
|
|
1476
|
-
drainAmount = params.value;
|
|
1477
|
-
}
|
|
1478
|
-
// Route 3 SVM: ALWAYS use native PRC-20, CEA uses its own balance.
|
|
1479
|
-
const prc20Token = (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork);
|
|
1456
|
+
const { prc20Token, drainAmount, tokenMintHex } = resolveR3SvmDrain(params, sourceChain, ctx.pushNetwork);
|
|
1480
1457
|
// Derive CEA PDA as revert recipient
|
|
1481
1458
|
const ueaBytes2 = Buffer.from(ueaAddress.slice(2), 'hex');
|
|
1482
1459
|
const [ceaPda2] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('push_identity'), ueaBytes2], programPk);
|
|
@@ -1485,25 +1462,22 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1485
1462
|
gatewayProgramHex,
|
|
1486
1463
|
drainAmount,
|
|
1487
1464
|
tokenMintHex,
|
|
1465
|
+
extraPayload: buildR3SvmExtraPayload(ctx, params, ueaAddress, sourceChain, nonce + BigInt(1)),
|
|
1488
1466
|
revertRecipientHex: ceaPdaHex2,
|
|
1489
1467
|
});
|
|
1490
|
-
//
|
|
1491
|
-
const burnAmount = BigInt(
|
|
1492
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, prc20Token, burnAmount, (
|
|
1468
|
+
// Payload-only outbound: drain amount lives inside ixData.
|
|
1469
|
+
const burnAmount = BigInt(0);
|
|
1470
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, prc20Token, burnAmount, (_j = params.gasLimit) !== null && _j !== void 0 ? _j : BigInt(0), svmPayload, ueaAddress, (_k = params.maxPCForGas) !== null && _k !== void 0 ? _k : BigInt(0));
|
|
1493
1471
|
return { payload: svmPayload, gatewayRequest: outboundReq };
|
|
1494
1472
|
}
|
|
1495
|
-
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (
|
|
1473
|
+
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_l = ctx.rpcUrls[sourceChain]) === null || _l === void 0 ? void 0 : _l[0]);
|
|
1496
1474
|
// CEA auto-deploys on-chain: Vault.finalizeUniversalTx calls CEAFactory.deployCEA()
|
|
1497
1475
|
// if CEA doesn't exist yet. No SDK-side blocking needed.
|
|
1498
|
-
const gatewayAddr = chain_1.UNIVERSAL_GATEWAY_ADDRESSES[sourceChain];
|
|
1499
|
-
if (!gatewayAddr) {
|
|
1500
|
-
throw new Error(`No UniversalGateway address configured for chain ${sourceChain}`);
|
|
1501
|
-
}
|
|
1502
1476
|
// Build CEA multicalls (self-calls via sendUniversalTxToUEA)
|
|
1503
1477
|
const ceaMulticalls = [];
|
|
1504
1478
|
let tokenAddress = selectors_1.ZERO_ADDRESS;
|
|
1505
1479
|
let amount = BigInt(0);
|
|
1506
|
-
if ((
|
|
1480
|
+
if ((_m = params.funds) === null || _m === void 0 ? void 0 : _m.amount) {
|
|
1507
1481
|
const token = params.funds.token;
|
|
1508
1482
|
if (token) {
|
|
1509
1483
|
if (token.mechanism === 'native') {
|
|
@@ -1513,27 +1487,6 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1513
1487
|
else {
|
|
1514
1488
|
tokenAddress = token.address;
|
|
1515
1489
|
amount = params.funds.amount;
|
|
1516
|
-
// Reset allowance to 0 first for USDT-style tokens, then approve
|
|
1517
|
-
const approveZeroData = (0, viem_1.encodeFunctionData)({
|
|
1518
|
-
abi: erc20_evm_1.ERC20_EVM,
|
|
1519
|
-
functionName: 'approve',
|
|
1520
|
-
args: [gatewayAddr, BigInt(0)],
|
|
1521
|
-
});
|
|
1522
|
-
ceaMulticalls.push({
|
|
1523
|
-
to: tokenAddress,
|
|
1524
|
-
value: BigInt(0),
|
|
1525
|
-
data: approveZeroData,
|
|
1526
|
-
});
|
|
1527
|
-
const approveData = (0, viem_1.encodeFunctionData)({
|
|
1528
|
-
abi: erc20_evm_1.ERC20_EVM,
|
|
1529
|
-
functionName: 'approve',
|
|
1530
|
-
args: [gatewayAddr, amount],
|
|
1531
|
-
});
|
|
1532
|
-
ceaMulticalls.push({
|
|
1533
|
-
to: tokenAddress,
|
|
1534
|
-
value: BigInt(0),
|
|
1535
|
-
data: approveData,
|
|
1536
|
-
});
|
|
1537
1490
|
}
|
|
1538
1491
|
}
|
|
1539
1492
|
}
|
|
@@ -1559,7 +1512,8 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1559
1512
|
const multicallPayload = (0, payload_builder_1.buildMulticallPayloadData)(ctx, pushDestination, multicallData);
|
|
1560
1513
|
pushPayload = (0, payload_builders_1.buildInboundUniversalPayload)(multicallPayload, { nonce: ueaNonceHop + BigInt(1) });
|
|
1561
1514
|
}
|
|
1562
|
-
// Build sendUniversalTxToUEA self-call on CEA
|
|
1515
|
+
// Build sendUniversalTxToUEA self-call on CEA. CEA self-calls must
|
|
1516
|
+
// always use value=0; native sends spend from the CEA balance.
|
|
1563
1517
|
const sendCall = (0, payload_builders_1.buildSendUniversalTxToUEA)(ceaAddress, tokenAddress, amount, pushPayload, ceaAddress);
|
|
1564
1518
|
ceaMulticalls.push(sendCall);
|
|
1565
1519
|
const ceaPayload = (0, payload_builders_1.buildCeaMulticallPayload)(ceaMulticalls);
|
|
@@ -1567,7 +1521,8 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1567
1521
|
// Route 3: CEA uses its own pre-existing balance — no PRC-20 burn needed.
|
|
1568
1522
|
// burnAmount = 0 makes this a payload-only outbound relay.
|
|
1569
1523
|
const burnAmount = BigInt(0);
|
|
1570
|
-
const
|
|
1524
|
+
const outboundGasLimit = (_o = params.gasLimit) !== null && _o !== void 0 ? _o : selectors_1.DEFAULT_CEA_TO_PUSH_GAS_LIMIT;
|
|
1525
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, outboundGasLimit, ceaPayload, ueaAddress, (_p = params.maxPCForGas) !== null && _p !== void 0 ? _p : BigInt(0));
|
|
1571
1526
|
return { payload: ceaPayload, gatewayRequest: outboundReq };
|
|
1572
1527
|
}
|
|
1573
1528
|
default:
|