Skip to content

Commit fb69c69

Browse files
fix(sdk-coin-flrp): subtract minImportToCFee from ExportInP outputAmount
For P→C exports (ExportInP), the exported UTXO amount includes the C-chain import fee that is added by the platform during transaction building (amount = userAmount + importToCFee). Without adjusting the outputAmount, the confirmation UI reads the gross UTXO amount as the displayed send amount. When the platform additionally applies its own import-fee subtraction from the same gross value, the resulting spendAmount can appear as 0 or be misinterpreted, causing the export confirmation UI to display "- TFLR" instead of the correct amount. Fix: in Flrp.explainTransaction, when the transaction is a P-chain export (ExportInP, !isTransactionForCChain), subtract minImportToCFee from outputAmount and each output's amount. This yields the minimum expected net C-chain receipt, aligning the confirmation display with the amount the user will actually receive after ImportInC, consistent with how ExportInC subtracts minImportToPFee (CECHO-1450). Add minImportToCFee to the FlareNetwork interface and set it to 2850000 nFLR (250 nFLR/gas × ~11400 gas, the minimum EVM import fee). Add test coverage verifying ExportInP outputAmount is adjusted. Ticket: CECHO-1518 Session-Id: 6f2ea6bd-01d6-4a82-a82f-0af0974e5165 Task-Id: 65e37cf1-5c7c-4605-8126-070b8d699a02
1 parent ad4998b commit fb69c69

3 files changed

Lines changed: 47 additions & 2 deletions

File tree

modules/sdk-coin-flrp/src/flrp.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,24 @@ export class Flrp extends BaseCoin {
451451
};
452452
}
453453

454+
// For a P→C export (ExportInP), the exported UTXO amount includes the C-chain
455+
// import fee that will be deducted when ImportInC is confirmed. Subtract the
456+
// minimum import-to-C fee so the displayed amount reflects the expected net
457+
// C-chain receipt, consistent with how ExportInC subtracts minImportToPFee.
458+
if (!tx.isTransactionForCChain && explanation.type === TransactionType.Export) {
459+
const minImportToCFee = BigInt((this._staticsCoin.network as FlareNetwork).minImportToCFee);
460+
const adjustedOutputs = explanation.outputs.map((o) => ({
461+
...o,
462+
amount: (BigInt(o.amount) - minImportToCFee).toString(),
463+
}));
464+
const adjustedOutputAmount = (BigInt(explanation.outputAmount) - minImportToCFee).toString();
465+
return {
466+
...explanation,
467+
outputs: adjustedOutputs,
468+
outputAmount: adjustedOutputAmount,
469+
};
470+
}
471+
454472
return explanation;
455473
} catch (e) {
456474
throw new Error(`Invalid transaction: ${e.message}`);

modules/sdk-coin-flrp/test/unit/flrp.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,30 @@ describe('Flrp test cases', function () {
313313
signedExplain.outputs[0].amount.should.equal(expectedAdjustedAmount);
314314
});
315315

316+
it('should subtract minImportToCFee from ExportInP outputAmount to show expected net C-chain receipt', async () => {
317+
// The ExportInP UTXO amount is the gross amount going to C-chain, which includes
318+
// the C-chain import fee that will be deducted when ImportInC is confirmed. We
319+
// subtract minImportToCFee to show the minimum net amount the user will receive
320+
// on C-chain, preventing the confirmation UI from showing a higher-than-actual
321+
// amount and causing the display to appear as "- TFLR" instead of the correct amount.
322+
const minImportToCFee = BigInt('2850000'); // from FlarePTestnet.minImportToCFee
323+
const grossOutputAmount = BigInt(EXPORT_IN_P.amount); // 55000000 (includes import fee)
324+
const expectedAdjustedAmount = (grossOutputAmount - minImportToCFee).toString();
325+
326+
// Should work for both half-signed and fully-signed ExportInP hex
327+
const halfSignedExplain = await basecoin.explainTransaction({
328+
halfSigned: { txHex: EXPORT_IN_P.halfSigntxHex },
329+
});
330+
halfSignedExplain.outputAmount.should.equal(expectedAdjustedAmount);
331+
halfSignedExplain.outputs.should.be.an.Array();
332+
halfSignedExplain.outputs.length.should.equal(1);
333+
halfSignedExplain.outputs[0].amount.should.equal(expectedAdjustedAmount);
334+
335+
const signedExplain = await basecoin.explainTransaction({ txHex: EXPORT_IN_P.fullSigntxHex });
336+
signedExplain.outputAmount.should.equal(expectedAdjustedAmount);
337+
signedExplain.outputs[0].amount.should.equal(expectedAdjustedAmount);
338+
});
339+
316340
it('should fail when transaction hex is not provided', async () => {
317341
await basecoin.explainTransaction({}).should.be.rejectedWith('missing transaction hex');
318342
});

modules/statics/src/networks.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface FlareNetwork extends BaseNetwork {
1818
vm?: string;
1919
txFee: string;
2020
minImportToPFee: string;
21+
minImportToCFee: string;
2122
maxImportFee: string;
2223
createSubnetTx?: string;
2324
createChainTx?: string;
@@ -2318,7 +2319,8 @@ export class FlareP extends Mainnet implements FlareNetwork {
23182319
hrp = 'flare';
23192320
alias = 'P';
23202321
vm = 'platformvm';
2321-
minImportToPFee = '1261000'; // 0.1261 FLR
2322+
minImportToPFee = '1261000'; // minimum PVM import-to-P fee in nFLR
2323+
minImportToCFee = '2850000'; // minimum EVM import-to-C fee in nFLR (250 nFLR/gas * ~11400 gas)
23222324
txFee = '200000'; // FLR P-chain import requires higher fee than base txFee
23232325
baseTxFee = '1000000';
23242326
maxImportFee = '10000000'; // defaults
@@ -2354,7 +2356,8 @@ export class FlarePTestnet extends Testnet implements FlareNetwork {
23542356
alias = 'P';
23552357
assetId = 'fxMAKpBQQpFedrUhWMsDYfCUJxdUw4mneTczKBzNg3rc2JUub';
23562358
vm = 'platformvm';
2357-
minImportToPFee = '1261000'; // 0.1261 FLR
2359+
minImportToPFee = '1261000'; // minimum PVM import-to-P fee in nFLR
2360+
minImportToCFee = '2850000'; // minimum EVM import-to-C fee in nFLR (250 nFLR/gas * ~11400 gas)
23582361
txFee = '200000'; // FLR P-chain import requires higher fee than base txFee
23592362
baseTxFee = '1000000';
23602363
maxImportFee = '10000000'; // defaults

0 commit comments

Comments
 (0)