diff --git a/node/external/transactionAPI/gasUsedAndFeeProcessor.go b/node/external/transactionAPI/gasUsedAndFeeProcessor.go index 8951149c983..5f4e2626fca 100644 --- a/node/external/transactionAPI/gasUsedAndFeeProcessor.go +++ b/node/external/transactionAPI/gasUsedAndFeeProcessor.go @@ -49,27 +49,28 @@ func (gfp *gasUsedAndFeeProcessor) computeAndAttachGasUsedAndFee(tx *transaction tx.Fee = tx.InitiallyPaidFee } - if tx.IsRelayed && isFeeFixActive { - totalFee, isRelayed := gfp.getFeeOfRelayed(tx) - if isRelayed { - tx.Fee = totalFee.String() - tx.InitiallyPaidFee = totalFee.String() - tx.GasUsed = big.NewInt(0).Div(totalFee, big.NewInt(0).SetUint64(tx.GasPrice)).Uint64() - } + initialTotalFee, isRelayed := gfp.getFeeOfRelayed(tx) + if isRelayed && isFeeFixActive { + tx.InitiallyPaidFee = initialTotalFee.String() + tx.Fee = initialTotalFee.String() + tx.GasUsed = big.NewInt(0).Div(initialTotalFee, big.NewInt(0).SetUint64(tx.GasPrice)).Uint64() } hasRefundForSender := false + totalRefunds := big.NewInt(0) for _, scr := range tx.SmartContractResults { if !scr.IsRefund || scr.RcvAddr != tx.Sender { continue } - if scr.RcvAddr != tx.Sender { - continue - } - gfp.setGasUsedAndFeeBaseOnRefundValue(tx, scr.Value) hasRefundForSender = true - break + totalRefunds.Add(totalRefunds, scr.Value) + } + + if totalRefunds.Cmp(big.NewInt(0)) > 0 { + gasUsed, fee = gfp.feeComputer.ComputeGasUsedAndFeeBasedOnRefundValue(tx, totalRefunds) + tx.GasUsed = gasUsed + tx.Fee = fee.String() } gfp.prepareTxWithResultsBasedOnLogs(tx, hasRefundForSender) @@ -172,12 +173,6 @@ func (gfp *gasUsedAndFeeProcessor) setGasUsedAndFeeBaseOnLogEvent(tx *transactio } } -func (gfp *gasUsedAndFeeProcessor) setGasUsedAndFeeBaseOnRefundValue(tx *transaction.ApiTransactionResult, refund *big.Int) { - gasUsed, fee := gfp.feeComputer.ComputeGasUsedAndFeeBasedOnRefundValue(tx, refund) - tx.GasUsed = gasUsed - tx.Fee = fee.String() -} - func (gfp *gasUsedAndFeeProcessor) isESDTOperationWithSCCall(tx *transaction.ApiTransactionResult) bool { isESDTTransferOperation := tx.Operation == core.BuiltInFunctionESDTTransfer || tx.Operation == core.BuiltInFunctionESDTNFTTransfer || tx.Operation == core.BuiltInFunctionMultiESDTNFTTransfer diff --git a/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go b/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go index d5340e7903c..3c8bb6d05cd 100644 --- a/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go +++ b/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go @@ -251,3 +251,111 @@ func TestNFTTransferWithScCall(t *testing.T) { req.Equal(uint64(55_000_000), tx.GasUsed) req.Equal("822250000000000", tx.Fee) } + +func TestComputeAndAttachGasUsedAndFeeTransactionWithMultipleScrWithRefund(t *testing.T) { + t.Parallel() + + feeComp, _ := fee.NewFeeComputer(createEconomicsData(&enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.GasPriceModifierFlag || + flag == common.PenalizedTooMuchGasFlag || + flag == common.FixRelayedBaseCostFlag + }, + })) + computer := fee.NewTestFeeComputer(feeComp) + + gasUsedAndFeeProc := newGasUsedAndFeeProcessor( + computer, + pubKeyConverter, + &testscommon.ArgumentParserMock{}, + &testscommon.MarshallerStub{}, + enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), + ) + + txWithSRefundSCR := &transaction.ApiTransactionResult{} + err := core.LoadJsonFile(txWithSRefundSCR, "testData/scInvokingWithMultipleRefunds.json") + require.NoError(t, err) + + txWithSRefundSCR.Fee = "" + txWithSRefundSCR.GasUsed = 0 + + snd, _ := pubKeyConverter.Decode(txWithSRefundSCR.Sender) + rcv, _ := pubKeyConverter.Decode(txWithSRefundSCR.Receiver) + val, _ := big.NewInt(0).SetString(txWithSRefundSCR.Value, 10) + txWithSRefundSCR.Tx = &transaction.Transaction{ + Nonce: txWithSRefundSCR.Nonce, + Value: val, + RcvAddr: rcv, + SndAddr: snd, + GasPrice: txWithSRefundSCR.GasPrice, + GasLimit: txWithSRefundSCR.GasLimit, + Data: txWithSRefundSCR.Data, + } + + gasUsedAndFeeProc.computeAndAttachGasUsedAndFee(txWithSRefundSCR) + require.Equal(t, uint64(20313408), txWithSRefundSCR.GasUsed) + require.Equal(t, "319459080000000", txWithSRefundSCR.Fee) +} + +func TestComputeAndAttachGasUsedAndFeeRelayedV3WithRefund(t *testing.T) { + t.Parallel() + + feeComp, _ := fee.NewFeeComputer(createEconomicsData(&enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.GasPriceModifierFlag || + flag == common.PenalizedTooMuchGasFlag || + flag == common.FixRelayedBaseCostFlag + }, + })) + computer := fee.NewTestFeeComputer(feeComp) + + gasUsedAndFeeProc := newGasUsedAndFeeProcessor( + computer, + pubKeyConverter, + &testscommon.ArgumentParserMock{}, + &testscommon.MarshallerStub{}, + enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), + ) + + txWithSRefundSCR := &transaction.ApiTransactionResult{} + err := core.LoadJsonFile(txWithSRefundSCR, "testData/relayedV3WithOneRefund.json") + require.NoError(t, err) + + txWithSRefundSCR.Fee = "" + txWithSRefundSCR.GasUsed = 0 + + innerTxs := make([]*transaction.Transaction, 0, len(txWithSRefundSCR.InnerTransactions)) + for _, innerTx := range txWithSRefundSCR.InnerTransactions { + snd, _ := pubKeyConverter.Decode(innerTx.Sender) + rcv, _ := pubKeyConverter.Decode(innerTx.Receiver) + val, _ := big.NewInt(0).SetString(innerTx.Value, 10) + + innerTxs = append(innerTxs, &transaction.Transaction{ + Nonce: innerTx.Nonce, + Value: val, + RcvAddr: rcv, + SndAddr: snd, + GasPrice: innerTx.GasPrice, + GasLimit: innerTx.GasLimit, + Data: innerTx.Data, + }) + } + + snd, _ := pubKeyConverter.Decode(txWithSRefundSCR.Sender) + rcv, _ := pubKeyConverter.Decode(txWithSRefundSCR.Receiver) + val, _ := big.NewInt(0).SetString(txWithSRefundSCR.Value, 10) + txWithSRefundSCR.Tx = &transaction.Transaction{ + Nonce: txWithSRefundSCR.Nonce, + Value: val, + RcvAddr: rcv, + SndAddr: snd, + GasPrice: txWithSRefundSCR.GasPrice, + GasLimit: txWithSRefundSCR.GasLimit, + Data: txWithSRefundSCR.Data, + InnerTransactions: innerTxs, + } + + gasUsedAndFeeProc.computeAndAttachGasUsedAndFee(txWithSRefundSCR) + require.Equal(t, uint64(55149500), txWithSRefundSCR.GasUsed) + require.Equal(t, "699500000000000", txWithSRefundSCR.Fee) +} diff --git a/node/external/transactionAPI/testData/relayedV3WithOneRefund.json b/node/external/transactionAPI/testData/relayedV3WithOneRefund.json new file mode 100644 index 00000000000..c2b0484f877 --- /dev/null +++ b/node/external/transactionAPI/testData/relayedV3WithOneRefund.json @@ -0,0 +1,56 @@ +{ + "type": "normal", + "processingTypeOnSource": "RelayedTxV3", + "processingTypeOnDestination": "RelayedTxV3", + "hash": "af1581562830e36b0bfb12c618a4ee92d6b7f2e0aa84935432a44c9b63cc8daa", + "nonce": 0, + "value": "0", + "receiver": "erd1tp66n2lkhs2fm7elvh9lmzfajpg480v55sd8lf2lvu4fw92zsrasvn2wze", + "sender": "erd1tp66n2lkhs2fm7elvh9lmzfajpg480v55sd8lf2lvu4fw92zsrasvn2wze", + "gasPrice": 1000000000, + "gasLimit": 99000000, + "gasUsed": 998505, + "smartContractResults": [ + { + "hash": "4c58801e77c57e88294f21018145662e2fb1698fd5f1a1cf7b6f81f073f5cd6c", + "nonce": 0, + "value": 2501000000000000000000, + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6", + "sender": "erd1s89rm6mv6xyct38r3vqadj74rmqunamhwyz7c84a6u9thedj2wus5nlchg", + "data": "createNewDelegationContract@00@00", + "prevTxHash": "af1581562830e36b0bfb12c618a4ee92d6b7f2e0aa84935432a44c9b63cc8daa", + "originalTxHash": "af1581562830e36b0bfb12c618a4ee92d6b7f2e0aa84935432a44c9b63cc8daa", + "gasLimit": 84900500, + "gasPrice": 1000000000 + }, + { + "hash": "94e678f400192eeae3c84b3125c9d45301db619a3ecbf9e7f46266a81a85ef51", + "nonce": 1, + "value": 299005000000000, + "receiver": "erd1tp66n2lkhs2fm7elvh9lmzfajpg480v55sd8lf2lvu4fw92zsrasvn2wze", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6", + "prevTxHash": "4c58801e77c57e88294f21018145662e2fb1698fd5f1a1cf7b6f81f073f5cd6c", + "originalTxHash": "af1581562830e36b0bfb12c618a4ee92d6b7f2e0aa84935432a44c9b63cc8daa", + "gasLimit": 0, + "gasPrice": 1000000000, + "returnMessage": "gas refund for relayer", + "operation": "transfer", + "isRefund": true + } + ], + "innerTransactions": [ + { + "nonce": 0, + "value": "2501000000000000000000", + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6", + "sender": "erd1s89rm6mv6xyct38r3vqadj74rmqunamhwyz7c84a6u9thedj2wus5nlchg", + "gasPrice": 1000000000, + "gasLimit": 85000000, + "data": "Y3JlYXRlTmV3RGVsZWdhdGlvbkNvbnRyYWN0QDAwQDAw", + "signature": "610493074d4e3ce0d8dcc5434cc67032f7e4acf3fd9f97525dba4865ba42408df8315824bf7b6268e2fa0d97fc51efe1a32f7928a799064a69d54bf063a19607", + "chainID": "chain", + "version": 2, + "relayer": "erd1tp66n2lkhs2fm7elvh9lmzfajpg480v55sd8lf2lvu4fw92zsrasvn2wze" + } + ] +} \ No newline at end of file diff --git a/node/external/transactionAPI/testData/scInvokingWithMultipleRefunds.json b/node/external/transactionAPI/testData/scInvokingWithMultipleRefunds.json new file mode 100644 index 00000000000..6223da3db9f --- /dev/null +++ b/node/external/transactionAPI/testData/scInvokingWithMultipleRefunds.json @@ -0,0 +1,115 @@ +{ + "type": "normal", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "nonce": 5720, + "value": "88000000000000000", + "receiver": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "sender": "erd1trqrpnl7e5nsagfqh4qp2tfpqg7hjacsesrstuhjk76rgagag9ws87gy6l", + "gasPrice": 1000000000, + "gasLimit": 45000000, + "gasUsed": 20313408, + "data": "YnV5QDEzMDA5N0A1NjQzNGY0OTRlMmQzMjY0MzQzNDMzNjRAMDFAMDE4NmEw", + "smartContractResults": [ + { + "hash": "ebc994f2e46037fbf16f3426ab3ea40a43b648620209372bcb158153053fb5f9", + "nonce": 5721, + "value": 246865920000000, + "receiver": "erd1trqrpnl7e5nsagfqh4qp2tfpqg7hjacsesrstuhjk76rgagag9ws87gy6l", + "sender": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "data": "@6f6b", + "prevTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "originalTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "gasLimit": 0, + "gasPrice": 1000000000, + "operation": "transfer", + "isRefund": true + }, + { + "hash": "402b39eba60202424565e224ab7121fd49eb8da366bc8b7b5d38496f1ce29f0d", + "nonce": 0, + "value": 2640000000000000, + "receiver": "erd1qqqqqqqqqqqqqpgq8538ku69p97lq4eug75y8d6g6yfwhd7c45qs4zvejt", + "sender": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "data": "depositRoyalties@0000000000000000050073175b6392a2f2661f2fb1fd2552787534433af98638", + "prevTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "originalTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "gasLimit": 5500000, + "gasPrice": 1000000000, + "originalSender": "erd1trqrpnl7e5nsagfqh4qp2tfpqg7hjacsesrstuhjk76rgagag9ws87gy6l", + "operation": "transfer", + "function": "depositRoyalties" + }, + { + "hash": "9912a1b3d3918a79f9c560ff2d81b24b316a89cbefd195325807132319147502", + "nonce": 0, + "value": 84480000000000000, + "receiver": "erd1qtkml3n4lwy5hxdmdfe67nm5jg5v6kqrtsdjt76za35ms4nnvghsjfujaw", + "sender": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "prevTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "originalTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "gasLimit": 0, + "gasPrice": 1000000000, + "originalSender": "erd1trqrpnl7e5nsagfqh4qp2tfpqg7hjacsesrstuhjk76rgagag9ws87gy6l", + "operation": "transfer" + }, + { + "hash": "11c18202b3d117fa3301e8cbc72f6d258d56b70686fa174bffa331079b753b31", + "nonce": 0, + "value": 0, + "receiver": "erd1trqrpnl7e5nsagfqh4qp2tfpqg7hjacsesrstuhjk76rgagag9ws87gy6l", + "sender": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "data": "ESDTNFTTransfer@56434f494e2d326434343364@01@0186a0@08011204000186a022ef020801120d56696c6c6167657220436f696e1a200000000000000000050073175b6392a2f2661f2fb1fd2552787534433af9863820ac022a203e0e25256b5c0a5d5825deb7519eeae0468c2597533db2de10bb560ae317b7f0325068747470733a2f2f697066732e696f2f697066732f6261666b7265696864703577797975706a6174356a6d68726e706c786d3333616570737a67667333656733716c336e776f6268736d72376e747434325068747470733a2f2f697066732e696f2f697066732f6261666b726569636d727763366b6b7472646d6669797a66616f687664357977796f34746f343670776c6b3767363562366d6b74376835697a6f793a71746167733a6769616e74732c6769616e74732076696c6c6167652c6e70632c76696c6c6167657220636f696e3b6d657461646174613a6261666b726569636d727763366b6b7472646d6669797a66616f687664357977796f34746f343670776c6b3767363562366d6b74376835697a6f79", + "prevTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "originalTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "gasLimit": 0, + "gasPrice": 1000000000, + "originalSender": "erd1trqrpnl7e5nsagfqh4qp2tfpqg7hjacsesrstuhjk76rgagag9ws87gy6l", + "operation": "ESDTNFTTransfer" + }, + { + "hash": "3a814d0abb4c00c44bc8ba29007c51edc487daa17c7666efc9fad1f5a86d03a2", + "nonce": 1, + "value": 880000000000000, + "receiver": "erd1qqqqqqqqqqqqqpgq8538ku69p97lq4eug75y8d6g6yfwhd7c45qs4zvejt", + "sender": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "data": "deposit", + "prevTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "originalTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "gasLimit": 3500000, + "gasPrice": 1000000000, + "originalSender": "erd1trqrpnl7e5nsagfqh4qp2tfpqg7hjacsesrstuhjk76rgagag9ws87gy6l", + "operation": "transfer", + "function": "deposit" + }, + { + "hash": "b7a2e5cf1ddad2630ccf8c703c9494b9b446e3a25ce362f6ec7c739448e41cbf", + "nonce": 1, + "value": 26131840000000, + "receiver": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "sender": "erd1qqqqqqqqqqqqqpgq8538ku69p97lq4eug75y8d6g6yfwhd7c45qs4zvejt", + "data": "@6f6b", + "prevTxHash": "402b39eba60202424565e224ab7121fd49eb8da366bc8b7b5d38496f1ce29f0d", + "originalTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "gasLimit": 0, + "gasPrice": 1000000000, + "operation": "transfer", + "isRefund": true + }, + { + "hash": "40d329ecd05ffa543a41efd216c463f2ec229432d7b5c1c9132af29e406f389d", + "nonce": 2, + "value": 7494280000000, + "receiver": "erd1qqqqqqqqqqqqqpgq6wegs2xkypfpync8mn2sa5cmpqjlvrhwz5nqgepyg8", + "sender": "erd1qqqqqqqqqqqqqpgq8538ku69p97lq4eug75y8d6g6yfwhd7c45qs4zvejt", + "data": "@6f6b", + "prevTxHash": "3a814d0abb4c00c44bc8ba29007c51edc487daa17c7666efc9fad1f5a86d03a2", + "originalTxHash": "293256314626408acc866793cb4e762ec4b2925dbce3bfb166e39e4deea66e93", + "gasLimit": 0, + "gasPrice": 1000000000, + "operation": "transfer", + "isRefund": true + } + ] +} diff --git a/outport/process/transactionsfee/transactionsFeeProcessor.go b/outport/process/transactionsfee/transactionsFeeProcessor.go index ffad67ee22f..ac92ce09790 100644 --- a/outport/process/transactionsfee/transactionsFeeProcessor.go +++ b/outport/process/transactionsfee/transactionsFeeProcessor.go @@ -155,6 +155,7 @@ func (tep *transactionsFeeProcessor) prepareNormalTxs(transactionsAndScrs *trans func (tep *transactionsFeeProcessor) prepareTxWithResults(txHashHex string, txWithResults *transactionWithResults) { hasRefund := false + totalRefunds := big.NewInt(0) for _, scrHandler := range txWithResults.scrs { scr, ok := scrHandler.GetTxHandler().(*smartContractResult.SmartContractResult) if !ok { @@ -162,17 +163,18 @@ func (tep *transactionsFeeProcessor) prepareTxWithResults(txHashHex string, txWi } if isSCRForSenderWithRefund(scr, txHashHex, txWithResults.GetTxHandler()) || isRefundForRelayed(scr, txWithResults.GetTxHandler()) { - gasUsed, fee := tep.txFeeCalculator.ComputeGasUsedAndFeeBasedOnRefundValue(txWithResults.GetTxHandler(), scr.Value) - - txWithResults.GetFeeInfo().SetGasUsed(gasUsed) - txWithResults.GetFeeInfo().SetFee(fee) hasRefund = true - break + totalRefunds.Add(totalRefunds, scr.Value) } } - tep.prepareTxWithResultsBasedOnLogs(txHashHex, txWithResults, hasRefund) + if totalRefunds.Cmp(big.NewInt(0)) > 0 { + gasUsed, fee := tep.txFeeCalculator.ComputeGasUsedAndFeeBasedOnRefundValue(txWithResults.GetTxHandler(), totalRefunds) + txWithResults.GetFeeInfo().SetGasUsed(gasUsed) + txWithResults.GetFeeInfo().SetFee(fee) + } + tep.prepareTxWithResultsBasedOnLogs(txHashHex, txWithResults, hasRefund) } func (tep *transactionsFeeProcessor) getFeeOfRelayed(tx *transactionWithResults) (*big.Int, bool) { diff --git a/process/economics/economicsData.go b/process/economics/economicsData.go index a510447dab2..170377e62d3 100644 --- a/process/economics/economicsData.go +++ b/process/economics/economicsData.go @@ -591,8 +591,15 @@ func (ed *economicsData) ComputeGasUsedAndFeeBasedOnRefundValueInEpoch(tx data.T txFee := ed.ComputeTxFeeInEpoch(tx, epoch) if len(tx.GetUserTransactions()) > 0 { - gasUnitsUsed := big.NewInt(0).Div(txFee, big.NewInt(0).SetUint64(tx.GetGasPrice())) - return gasUnitsUsed.Uint64(), txFee + txFeeAfterRefund := txFee.Sub(txFee, refundValue) + + gasPriceForProcessing := ed.GasPriceForProcessingInEpoch(tx, epoch) + gasUnitsRefunded := refundValue.Uint64() / gasPriceForProcessing + + gasUnitsConsideredForInitialFee := ed.computeRelayedTxV3MinGasLimit(tx) + gasUnitsUsed := gasUnitsConsideredForInitialFee - gasUnitsRefunded + + return gasUnitsUsed, txFeeAfterRefund } isPenalizedTooMuchGasFlagEnabled := ed.enableEpochsHandler.IsFlagEnabledInEpoch(common.PenalizedTooMuchGasFlag, epoch) @@ -682,6 +689,20 @@ func (ed *economicsData) ComputeGasLimitBasedOnBalanceInEpoch(tx data.Transactio return totalGasLimit, nil } +func (ed *economicsData) computeRelayedTxV3MinGasLimit(tx data.TransactionWithFeeHandler) uint64 { + relayedTxGasLimit := ed.ComputeGasLimit(tx) + relayedTxMinGasLimit := ed.MinGasLimit() + relayedTxGasLimitDiff := relayedTxGasLimit - relayedTxMinGasLimit // this may be positive if the relayed tx is guarded + + innerTxs := tx.GetUserTransactions() + totalGasLimit := relayedTxGasLimitDiff + relayedTxMinGasLimit*uint64(len(innerTxs)) + for _, innerTx := range innerTxs { + totalGasLimit += innerTx.GetGasLimit() + } + + return totalGasLimit +} + // IsInterfaceNil returns true if there is no value under the interface func (ed *economicsData) IsInterfaceNil() bool { return ed == nil diff --git a/process/economics/economicsData_test.go b/process/economics/economicsData_test.go index 5fdb8c369c2..f1a66e25dcd 100644 --- a/process/economics/economicsData_test.go +++ b/process/economics/economicsData_test.go @@ -1281,6 +1281,39 @@ func TestEconomicsData_ComputeGasUsedAndFeeBasedOnRefundValueSpecialBuiltInTooMu require.Equal(t, expectedFee, fee) } +func TestEconomicsData_ComputeGasUsedAndFeeBasedOnRefundValueRelayedV3(t *testing.T) { + t.Parallel() + + economicData, _ := economics.NewEconomicsData(createArgsForEconomicsDataRealFees()) + tx := &transaction.Transaction{ + GasPrice: 1000000000, + GasLimit: 99000000, + InnerTransactions: []*transaction.Transaction{ + { + GasPrice: 1000000000, + GasLimit: 85000000, + Data: []byte("createNewDelegationContract@00@00"), + }, + { + GasPrice: 1000000000, + GasLimit: 50000, + }, + { + GasPrice: 1000000000, + GasLimit: 50000, + }, + }, + } + + expectedGasUsed := uint64(55349500) + expectedFee, _ := big.NewInt(0).SetString("899500000000000", 10) + + refundValue, _ := big.NewInt(0).SetString("299005000000000", 10) + gasUsed, fee := economicData.ComputeGasUsedAndFeeBasedOnRefundValue(tx, refundValue) + require.Equal(t, expectedGasUsed, gasUsed) + require.Equal(t, expectedFee, fee) +} + func TestEconomicsData_ComputeGasLimitBasedOnBalance(t *testing.T) { t.Parallel()