@@ -164,14 +164,32 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
164164
165165 const { inputs, amount, credentials } = this . createInputs ( ) ;
166166
167- // Calculate fee
167+ // Calculate import cost units (matching AVAXP's costImportTx approach)
168+ // Create a temporary transaction to calculate the actual cost units
169+ const tempOutput = new evmSerial . Output (
170+ new Address ( this . transaction . _to [ 0 ] ) ,
171+ new BigIntPr ( amount ) ,
172+ new Id ( new Uint8Array ( Buffer . from ( this . transaction . _assetId , 'hex' ) ) )
173+ ) ;
174+ const tempImportTx = new evmSerial . ImportTx (
175+ new Int ( this . transaction . _networkID ) ,
176+ new Id ( new Uint8Array ( Buffer . from ( this . transaction . _blockchainID , 'hex' ) ) ) ,
177+ new Id ( new Uint8Array ( this . _externalChainId ) ) ,
178+ inputs ,
179+ [ tempOutput ]
180+ ) ;
181+
182+ // Calculate the import cost units (matches AVAXP's feeSize from costImportTx)
183+ const feeSize = this . calculateImportCost ( tempImportTx ) ;
184+
185+ // Multiply feeRate by cost units (matching AVAXP: fee = feeRate.muln(feeSize))
168186 const feeRate = BigInt ( this . transaction . _fee . feeRate ) ;
169- const feeSize = this . calculateFeeSize ( ) ;
170187 const fee = feeRate * BigInt ( feeSize ) ;
188+
171189 this . transaction . _fee . fee = fee . toString ( ) ;
172190 this . transaction . _fee . size = feeSize ;
173191
174- // Create EVM output using proper FlareJS class
192+ // Create EVM output using proper FlareJS class with amount minus fee
175193 const output = new evmSerial . Output (
176194 new Address ( this . transaction . _to [ 0 ] ) ,
177195 new BigIntPr ( amount - fee ) ,
@@ -274,7 +292,43 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
274292 }
275293
276294 /**
277- * Calculate the fee size for the transaction
295+ * Calculate the import cost for C-chain import transactions
296+ * Matches AVAXP's costImportTx formula:
297+ * - Base byte cost: transactionSize * txBytesGas (1 gas per byte)
298+ * - Per-input cost: numInputs * costPerSignature (1000 per signature) * threshold
299+ * - Fixed fee: 10000
300+ *
301+ * This returns cost "units" to be multiplied by feeRate, matching AVAXP's approach:
302+ * AVAXP: fee = feeRate.muln(costImportTx(tx))
303+ * FLRP: fee = feeRate * calculateImportCost(tx)
304+ *
305+ * @param tx The ImportTx to calculate the cost for
306+ * @returns The total cost units
307+ */
308+ private calculateImportCost ( tx : evmSerial . ImportTx ) : number {
309+ const codec = avmSerial . getAVMManager ( ) . getDefaultCodec ( ) ;
310+ const txBytes = tx . toBytes ( codec ) ;
311+
312+ // Base byte cost: 1 gas per byte (matching AVAX txBytesGas)
313+ const txBytesGas = 1 ;
314+ let bytesCost = txBytes . length * txBytesGas ;
315+
316+ // Per-input cost: costPerSignature (1000) per signature
317+ const costPerSignature = 1000 ;
318+ const numInputs = tx . importedInputs . length ;
319+ const numSignatures = this . transaction . _threshold ; // Each input requires threshold signatures
320+ const inputCost = numInputs * costPerSignature * numSignatures ;
321+ bytesCost += inputCost ;
322+
323+ // Fixed fee component
324+ const fixedFee = 10000 ;
325+ const totalCost = bytesCost + fixedFee ;
326+
327+ return totalCost ;
328+ }
329+
330+ /**
331+ * Calculate the fee size for the transaction (for backwards compatibility)
278332 * For C-chain imports, the feeRate is treated as an absolute fee value
279333 */
280334 private calculateFeeSize ( tx ?: evmSerial . ImportTx ) : number {
0 commit comments