From 45b593cc3588209e0a3384b503e4b2a82f46c529 Mon Sep 17 00:00:00 2001 From: miiu Date: Thu, 17 Oct 2024 11:34:02 +0300 Subject: [PATCH] fix gas used and fee relayed v3 --- genesis/process/disabled/feeHandler.go | 10 + go.mod | 2 +- go.sum | 4 +- node/external/timemachine/fee/feeComputer.go | 5 + .../transactionAPI/gasUsedAndFeeProcessor.go | 12 + .../gasUsedAndFeeProcessor_test.go | 114 ++++ node/external/transactionAPI/interface.go | 1 + .../relayedV3WithAllInnerTxFailed.json | 174 +++++ ...ayedV3WithOneInnerFailedAndTwoRefunds.json | 605 ++++++++++++++++++ outport/mock/economicsDataMock.go | 15 + outport/process/interface.go | 3 + outport/process/transactionsfee/interface.go | 3 + .../transactionsFeeProcessor.go | 31 +- .../transactionsFeeProcessor_test.go | 109 ++++ process/economics/economicsData.go | 21 + process/economics/economicsData_test.go | 76 +++ process/interface.go | 2 + .../economicsDataHandlerStub.go | 10 + .../economicsmocks/economicsHandlerMock.go | 10 + testscommon/feeComputerStub.go | 9 + 20 files changed, 1211 insertions(+), 5 deletions(-) create mode 100644 node/external/transactionAPI/testData/relayedV3WithAllInnerTxFailed.json create mode 100644 node/external/transactionAPI/testData/relayedV3WithOneInnerFailedAndTwoRefunds.json diff --git a/genesis/process/disabled/feeHandler.go b/genesis/process/disabled/feeHandler.go index f81e7e978eb..94333833b40 100644 --- a/genesis/process/disabled/feeHandler.go +++ b/genesis/process/disabled/feeHandler.go @@ -12,6 +12,16 @@ import ( type FeeHandler struct { } +// ComputeRelayedTxV3GasUnits - +func (fh *FeeHandler) ComputeRelayedTxV3GasUnits(_ data.TransactionWithFeeHandler, _ uint32) uint64 { + return 0 +} + +// ComputeGasUnitsFromRefundValue - +func (fh *FeeHandler) ComputeGasUnitsFromRefundValue(_ data.TransactionWithFeeHandler, _ *big.Int) uint64 { + return 0 +} + // GasPriceModifier returns 1.0 func (fh *FeeHandler) GasPriceModifier() float64 { return 1.0 diff --git a/go.mod b/go.mod index d2b76ce9593..a2d27a2787b 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/klauspost/cpuid/v2 v2.2.5 github.com/mitchellh/mapstructure v1.5.0 github.com/multiversx/mx-chain-communication-go v1.1.0 - github.com/multiversx/mx-chain-core-go v1.2.22 + github.com/multiversx/mx-chain-core-go v1.2.23-0.20241016115557-6a55050d2ade github.com/multiversx/mx-chain-crypto-go v1.2.12 github.com/multiversx/mx-chain-es-indexer-go v1.7.9 github.com/multiversx/mx-chain-logger-go v1.0.15 diff --git a/go.sum b/go.sum index 0b789eb79b2..93b1956657a 100644 --- a/go.sum +++ b/go.sum @@ -387,8 +387,8 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-communication-go v1.1.0 h1:J7bX6HoN3HiHY7cUeEjG8AJWgQDDPcY+OPDOsSUOkRE= github.com/multiversx/mx-chain-communication-go v1.1.0/go.mod h1:WK6bP4pGEHGDDna/AYRIMtl6G9OA0NByI1Lw8PmOnRM= -github.com/multiversx/mx-chain-core-go v1.2.22 h1:yDYrvoQOBbsDerEp7L3+de5AfMy3pTF333gWPpd+FNk= -github.com/multiversx/mx-chain-core-go v1.2.22/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.23-0.20241016115557-6a55050d2ade h1:29XqGze9121Z4UxujgEeiBdNS9Nw9Q+VC7w62iVGk7o= +github.com/multiversx/mx-chain-core-go v1.2.23-0.20241016115557-6a55050d2ade/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.12 h1:zWip7rpUS4CGthJxfKn5MZfMfYPjVjIiCID6uX5BSOk= github.com/multiversx/mx-chain-crypto-go v1.2.12/go.mod h1:HzcPpCm1zanNct/6h2rIh+MFrlXbjA5C8+uMyXj3LI4= github.com/multiversx/mx-chain-es-indexer-go v1.7.9 h1:rWq9phJu8GG6TtoJ5cL+MmhyReWCEyqBE5ymXUvudCg= diff --git a/node/external/timemachine/fee/feeComputer.go b/node/external/timemachine/fee/feeComputer.go index 6d19ce05ceb..584659273b0 100644 --- a/node/external/timemachine/fee/feeComputer.go +++ b/node/external/timemachine/fee/feeComputer.go @@ -45,6 +45,11 @@ func (computer *feeComputer) ComputeGasLimit(tx *transaction.ApiTransactionResul return computer.economicsInstance.ComputeGasLimitInEpoch(tx.Tx, tx.Epoch) } +// ComputeGasUnitForRelayedV3 will compute the gas units for a relayed v3 transaction +func (computer *feeComputer) ComputeGasUnitForRelayedV3(tx *transaction.ApiTransactionResult) uint64 { + return computer.economicsInstance.ComputeRelayedTxV3GasUnits(tx.Tx, tx.Epoch) +} + // ComputeTransactionFee computes a transaction fee, at a given epoch func (computer *feeComputer) ComputeTransactionFee(tx *transaction.ApiTransactionResult) *big.Int { return computer.economicsInstance.ComputeTxFeeInEpoch(tx.Tx, tx.Epoch) diff --git a/node/external/transactionAPI/gasUsedAndFeeProcessor.go b/node/external/transactionAPI/gasUsedAndFeeProcessor.go index 530b6b81b3d..57ce2ed0c05 100644 --- a/node/external/transactionAPI/gasUsedAndFeeProcessor.go +++ b/node/external/transactionAPI/gasUsedAndFeeProcessor.go @@ -78,6 +78,18 @@ func (gfp *gasUsedAndFeeProcessor) computeAndAttachGasUsedAndFee(tx *transaction return } + isRelayedV3AndNoRefund := len(tx.InnerTransactions) > 0 && !hasRefundForSender + if isRelayedV3AndNoRefund { + txFee := gfp.feeComputer.ComputeTransactionFee(tx) + gasUsedRelayed := gfp.feeComputer.ComputeGasUnitForRelayedV3(tx) + + tx.GasUsed = gasUsedRelayed + tx.Fee = txFee.String() + tx.InitiallyPaidFee = txFee.String() + + return + } + gfp.prepareTxWithResultsBasedOnLogs(tx, hasRefundForSender) } diff --git a/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go b/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go index 7e4011e0f2c..1d7a7819bd0 100644 --- a/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go +++ b/node/external/transactionAPI/gasUsedAndFeeProcessor_test.go @@ -6,16 +6,20 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/pubkeyConverter" + "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/marshal" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/node/external/timemachine/fee" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/economics" + "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/process/smartContract" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/epochNotifier" + datafield "github.com/multiversx/mx-chain-vm-common-go/parsers/dataField" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -28,6 +32,26 @@ func createEconomicsData(enableEpochsHandler common.EnableEpochsHandler) process EpochNotifier: &epochNotifier.EpochNotifierStub{}, }) + dataFieldParser, _ := datafield.NewOperationDataFieldParser(&datafield.ArgsOperationDataFieldParser{ + AddressLength: 32, + Marshalizer: &mock.MarshalizerMock{}, + }) + + _ = economicsData.SetTxTypeHandler(&testscommon.TxTypeHandlerMock{ + ComputeTransactionTypeCalled: func(tx data.TransactionHandler) (process.TransactionType, process.TransactionType) { + if core.IsSmartContractAddress(tx.GetRcvAddr()) { + return process.SCInvoking, process.SCInvoking + } + + res := dataFieldParser.Parse(tx.GetData(), tx.GetSndAddr(), tx.GetRcvAddr(), 3) + if len(res.Tokens) > 0 { + return process.BuiltInFunctionCall, process.BuiltInFunctionCall + } + + return process.MoveBalance, process.MoveBalance + }, + }) + return economicsData } @@ -409,3 +433,93 @@ func TestComputeAndAttachGasUsedAndFeeFailedRelayedV1(t *testing.T) { require.Equal(t, "1274230000000000", txWithSRefundSCR.Fee) require.Equal(t, "1274230000000000", txWithSRefundSCR.InitiallyPaidFee) } + +func TestComputeAndAttachGasUsedAndFeeRelayedV3WithAllInnerTxFailed(t *testing.T) { + t.Parallel() + + t.Run("all inner txs are failed", testComputeAndAttachGasUsedAndFeeRelayedV3WithInnerTxFailed( + "testData/relayedV3WithAllInnerTxFailed.json", + uint64(60150000), + "2226090000000000", + "2226090000000000", + )) + t.Run("one inner tx is failed, other have refunds", testComputeAndAttachGasUsedAndFeeRelayedV3WithInnerTxFailed( + "testData/relayedV3WithOneInnerFailedAndTwoRefunds.json", + uint64(160766000), + "2670920000000000", + "2864760000000000", + )) + +} + +func testComputeAndAttachGasUsedAndFeeRelayedV3WithInnerTxFailed( + inputFile string, + expectedGasUsed uint64, + expectedFee string, + expectedInitiallyPaidFee string, +) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + + enableEpochsHandler := &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.GasPriceModifierFlag || + flag == common.PenalizedTooMuchGasFlag || + flag == common.RelayedTransactionsV3Flag + }, + } + feeComp, _ := fee.NewFeeComputer(createEconomicsData(enableEpochsHandler)) + computer := fee.NewTestFeeComputer(feeComp) + + gasUsedAndFeeProc := newGasUsedAndFeeProcessor( + computer, + pubKeyConverter, + smartContract.NewArgumentParser(), + &marshal.JsonMarshalizer{}, + enableEpochsHandler, + ) + + txWithFailedInners := &transaction.ApiTransactionResult{} + err := core.LoadJsonFile(txWithFailedInners, inputFile) + require.NoError(t, err) + + innerTxs := make([]*transaction.Transaction, 0, len(txWithFailedInners.InnerTransactions)) + for _, innerTx := range txWithFailedInners.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(txWithFailedInners.Sender) + rcv, _ := pubKeyConverter.Decode(txWithFailedInners.Receiver) + val, _ := big.NewInt(0).SetString(txWithFailedInners.Value, 10) + txWithFailedInners.Tx = &transaction.Transaction{ + Nonce: txWithFailedInners.Nonce, + Value: val, + RcvAddr: rcv, + SndAddr: snd, + GasPrice: txWithFailedInners.GasPrice, + GasLimit: txWithFailedInners.GasLimit, + Data: txWithFailedInners.Data, + InnerTransactions: innerTxs, + } + + txWithFailedInners.InitiallyPaidFee = "" + txWithFailedInners.Fee = "" + txWithFailedInners.GasUsed = 0 + + gasUsedAndFeeProc.computeAndAttachGasUsedAndFee(txWithFailedInners) + assert.Equal(t, expectedGasUsed, txWithFailedInners.GasUsed) + assert.Equal(t, expectedFee, txWithFailedInners.Fee) + assert.Equal(t, expectedInitiallyPaidFee, txWithFailedInners.InitiallyPaidFee) + } +} diff --git a/node/external/transactionAPI/interface.go b/node/external/transactionAPI/interface.go index a32cac06184..5b7837d6579 100644 --- a/node/external/transactionAPI/interface.go +++ b/node/external/transactionAPI/interface.go @@ -11,6 +11,7 @@ type feeComputer interface { ComputeGasUsedAndFeeBasedOnRefundValue(tx *transaction.ApiTransactionResult, refundValue *big.Int) (uint64, *big.Int) ComputeTxFeeBasedOnGasUsed(tx *transaction.ApiTransactionResult, gasUsed uint64) *big.Int ComputeGasLimit(tx *transaction.ApiTransactionResult) uint64 + ComputeGasUnitForRelayedV3(tx *transaction.ApiTransactionResult) uint64 ComputeTransactionFee(tx *transaction.ApiTransactionResult) *big.Int IsInterfaceNil() bool } diff --git a/node/external/transactionAPI/testData/relayedV3WithAllInnerTxFailed.json b/node/external/transactionAPI/testData/relayedV3WithAllInnerTxFailed.json new file mode 100644 index 00000000000..68d0aa3178d --- /dev/null +++ b/node/external/transactionAPI/testData/relayedV3WithAllInnerTxFailed.json @@ -0,0 +1,174 @@ +{ + "type": "normal", + "processingTypeOnSource": "RelayedTxV3", + "processingTypeOnDestination": "RelayedTxV3", + "hash": "9034190d93ab39cf1c6e82832238777512d274c0867e6a3462950695606f10f8", + "nonce": 3, + "value": "0", + "receiver": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "sender": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "gasPrice": 1000000000, + "gasLimit": 500000000, + "isRelayed": true, + "innerTransactions": [ + { + "type": "inner", + "hash": "f820c6cef9288bc627c42df6ac57c64429f7822fa01ba58db5d57f138f3833bf", + "nonce": 6, + "value": "0", + "receiver": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "gasPrice": 1000000000, + "gasLimit": 20000000, + "data": "RVNEVE5GVENyZWF0ZUA0MTRjNDU1ODJkMzk2NDY1MzgzOTY2QDAxQDU0NjU3Mzc0QDAzZThANTE2ZDY2NDEzMjQ4NzQ2NTcyNmU2NzRkNjI0MjY1NTQ2NzUwNmIzMjYxMzI3YTZmNGQzNTc5NjU2MTZmMzM0NTZmNjEzNzM2Nzg1MTM3NzUzNDZkNjM2NDY5NDdANzQ2MTY3NzMzYTc0NjU3Mzc0MmM2NjcyNjU2NTJjNjY3NTZlM2I2ZDY1NzQ2MTY0NjE3NDYxM2E1NDY4Njk3MzIwNjk3MzIwNjEyMDc0NjU3Mzc0MjA2NDY1NzM2MzcyNjk3MDc0Njk2ZjZlMjA2NjZmNzIyMDYxNmUyMDYxNzc2NTczNmY2ZDY1MjA2ZTY2NzRAMDEwMQ==", + "smartContractResults": [ + { + "hash": "8cee6b30bc1ed2efdc6cc1ad08d7e8ab5cda5dec54cec2f690679e8c2b672b93", + "nonce": 6, + "value": 0, + "receiver": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTNFTCreate@414c45582d396465383966@01@54657374@03e8@516d664132487465726e674d6242655467506b3261327a6f4d357965616f33456f61373678513775346d63646947@746167733a746573742c667265652c66756e3b6d657461646174613a5468697320697320612074657374206465736372697074696f6e20666f7220616e20617765736f6d65206e6674@0101", + "prevTxHash": "f820c6cef9288bc627c42df6ac57c64429f7822fa01ba58db5d57f138f3833bf", + "originalTxHash": "9034190d93ab39cf1c6e82832238777512d274c0867e6a3462950695606f10f8", + "gasLimit": 19503000, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "events": [ + { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "identifier": "signalError", + "topics": [ + "KQclkV+pF/02MiTDTYE5sCvEqMWPbC093vxwHQBTJEM=", + "YWN0aW9uIGlzIG5vdCBhbGxvd2Vk" + ], + "data": "QDYxNjM3NDY5NmY2ZTIwNjk3MzIwNmU2Zjc0MjA2MTZjNmM2Zjc3NjU2NA==", + "additionalData": [ + "QDYxNjM3NDY5NmY2ZTIwNjk3MzIwNmU2Zjc0MjA2MTZjNmM2Zjc3NjU2NA==" + ] + } + ] + }, + "tokens": [ + "ALEX-9de89f" + ], + "esdtValues": [ + "1" + ], + "operation": "ESDTNFTCreate" + } + ], + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n" + }, + { + "type": "inner", + "hash": "68c279534fbc7c737355463233a6d792b8fcf1d37502501da2586aee89068ceb", + "nonce": 7, + "value": "0", + "receiver": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "gasPrice": 1000000000, + "gasLimit": 20000000, + "data": "RVNEVE5GVENyZWF0ZUA0MTRjNDU1ODJkMzk2NDY1MzgzOTY2QDAxQDU0NjU3Mzc0QDAzZThANTE2ZDY2NDEzMjQ4NzQ2NTcyNmU2NzRkNjI0MjY1NTQ2NzUwNmIzMjYxMzI3YTZmNGQzNTc5NjU2MTZmMzM0NTZmNjEzNzM2Nzg1MTM3NzUzNDZkNjM2NDY5NDdANzQ2MTY3NzMzYTc0NjU3Mzc0MmM2NjcyNjU2NTJjNjY3NTZlM2I2ZDY1NzQ2MTY0NjE3NDYxM2E1NDY4Njk3MzIwNjk3MzIwNjEyMDc0NjU3Mzc0MjA2NDY1NzM2MzcyNjk3MDc0Njk2ZjZlMjA2NjZmNzIyMDYxNmUyMDYxNzc2NTczNmY2ZDY1MjA2ZTY2NzRAMDEwMQ==", + "smartContractResults": [ + { + "hash": "633a15dbd5300c49a947d264501b4068a1b9c70a86ddfb31615b346594de76f7", + "nonce": 7, + "value": 0, + "receiver": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTNFTCreate@414c45582d396465383966@01@54657374@03e8@516d664132487465726e674d6242655467506b3261327a6f4d357965616f33456f61373678513775346d63646947@746167733a746573742c667265652c66756e3b6d657461646174613a5468697320697320612074657374206465736372697074696f6e20666f7220616e20617765736f6d65206e6674@0101", + "prevTxHash": "68c279534fbc7c737355463233a6d792b8fcf1d37502501da2586aee89068ceb", + "originalTxHash": "9034190d93ab39cf1c6e82832238777512d274c0867e6a3462950695606f10f8", + "gasLimit": 19503000, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "events": [ + { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "identifier": "signalError", + "topics": [ + "KQclkV+pF/02MiTDTYE5sCvEqMWPbC093vxwHQBTJEM=", + "YWN0aW9uIGlzIG5vdCBhbGxvd2Vk" + ], + "data": "QDYxNjM3NDY5NmY2ZTIwNjk3MzIwNmU2Zjc0MjA2MTZjNmM2Zjc3NjU2NA==", + "additionalData": [ + "QDYxNjM3NDY5NmY2ZTIwNjk3MzIwNmU2Zjc0MjA2MTZjNmM2Zjc3NjU2NA==" + ] + } + ] + }, + "tokens": [ + "ALEX-9de89f" + ], + "esdtValues": [ + "1" + ], + "operation": "ESDTNFTCreate" + } + ], + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n" + }, + { + "type": "inner", + "hash": "098ad3df7abab3d5603438995983f81923279ee849397c56e10969f83ed7041c", + "nonce": 8, + "value": "0", + "receiver": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "gasPrice": 1000000000, + "gasLimit": 20000000, + "data": "RVNEVE5GVENyZWF0ZUA0MTRjNDU1ODJkMzk2NDY1MzgzOTY2QDAxQDU0NjU3Mzc0QDAzZThANTE2ZDY2NDEzMjQ4NzQ2NTcyNmU2NzRkNjI0MjY1NTQ2NzUwNmIzMjYxMzI3YTZmNGQzNTc5NjU2MTZmMzM0NTZmNjEzNzM2Nzg1MTM3NzUzNDZkNjM2NDY5NDdANzQ2MTY3NzMzYTc0NjU3Mzc0MmM2NjcyNjU2NTJjNjY3NTZlM2I2ZDY1NzQ2MTY0NjE3NDYxM2E1NDY4Njk3MzIwNjk3MzIwNjEyMDc0NjU3Mzc0MjA2NDY1NzM2MzcyNjk3MDc0Njk2ZjZlMjA2NjZmNzIyMDYxNmUyMDYxNzc2NTczNmY2ZDY1MjA2ZTY2NzRAMDEwMQ==", + "smartContractResults": [ + { + "hash": "19ea4142f37c3079bd511aed503ffb0bafad1b4921ef618d79c6a0a185753b78", + "nonce": 8, + "value": 0, + "receiver": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTNFTCreate@414c45582d396465383966@01@54657374@03e8@516d664132487465726e674d6242655467506b3261327a6f4d357965616f33456f61373678513775346d63646947@746167733a746573742c667265652c66756e3b6d657461646174613a5468697320697320612074657374206465736372697074696f6e20666f7220616e20617765736f6d65206e6674@0101", + "prevTxHash": "098ad3df7abab3d5603438995983f81923279ee849397c56e10969f83ed7041c", + "originalTxHash": "9034190d93ab39cf1c6e82832238777512d274c0867e6a3462950695606f10f8", + "gasLimit": 19503000, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "events": [ + { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "identifier": "signalError", + "topics": [ + "KQclkV+pF/02MiTDTYE5sCvEqMWPbC093vxwHQBTJEM=", + "YWN0aW9uIGlzIG5vdCBhbGxvd2Vk" + ], + "data": "QDYxNjM3NDY5NmY2ZTIwNjk3MzIwNmU2Zjc0MjA2MTZjNmM2Zjc3NjU2NA==", + "additionalData": [ + "QDYxNjM3NDY5NmY2ZTIwNjk3MzIwNmU2Zjc0MjA2MTZjNmM2Zjc3NjU2NA==" + ] + } + ] + }, + "tokens": [ + "ALEX-9de89f" + ], + "esdtValues": [ + "1" + ], + "operation": "ESDTNFTCreate" + } + ], + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n" + } + ] +} diff --git a/node/external/transactionAPI/testData/relayedV3WithOneInnerFailedAndTwoRefunds.json b/node/external/transactionAPI/testData/relayedV3WithOneInnerFailedAndTwoRefunds.json new file mode 100644 index 00000000000..46e71194b11 --- /dev/null +++ b/node/external/transactionAPI/testData/relayedV3WithOneInnerFailedAndTwoRefunds.json @@ -0,0 +1,605 @@ +{ + "type": "normal", + "processingTypeOnSource": "RelayedTxV3", + "processingTypeOnDestination": "RelayedTxV3", + "hash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "nonce": 47, + "value": "0", + "receiver": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "sender": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "gasPrice": 1000000000, + "gasLimit": 500000000, + "isRelayed": true, + "innerTransactions": [ + { + "type": "inner", + "hash": "9a64f50a80a71e9234447aaa6209c0b6dc543790192432908a024bdaf0100c73", + "nonce": 7, + "value": "5000000000000000000", + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd1e2ftj4hj43lkduwps9xdmtgjnmugkh9mndph4n2cxfmf6ufvn4ks0zut84", + "gasPrice": 1000000000, + "gasLimit": 60000000, + "data": "aXNzdWVOb25GdW5naWJsZUA0ZDU5NGU0NjU0QDQxNGM0NTU4QDYzNjE2ZTQ2NzI2NTY1N2E2NUA3NDcyNzU2NUA2MzYxNmU1NzY5NzA2NUA3NDcyNzU2NUA2MzYxNmU1MDYxNzU3MzY1QDc0NzI3NTY1QDYzNjE2RTU0NzI2MTZFNzM2NjY1NzI0RTQ2NTQ0MzcyNjU2MTc0NjU1MjZGNkM2NUA3NDcyNzU2NQ==", + "smartContractResults": [ + { + "hash": "c4535975592aaa2a1f69b2f5b2b069416a96b06cd9c6a3e6e6b9840c39f834c9", + "nonce": 1, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetTokenType@414c45582d396536393235@4e6f6e46756e6769626c65455344547632", + "prevTxHash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "events": [ + { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "identifier": "completedTxEvent", + "topics": [ + "c2Se1God4pE5YSpIifQx2MbbzRN+Hb9PaYdlHBSF/zU=" + ], + "data": null, + "additionalData": null + } + ] + }, + "operation": "ESDTSetTokenType" + }, + { + "hash": "ae6a1c55783b7dcb27817e22e498985ae32fa17b3f6ce00642cfb6c1e5784f8e", + "nonce": 0, + "value": 0, + "receiver": "erd1lllllllllllllllllllllllllllllllllllllllllllllllllupq9x7ny0", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetBurnRoleForAll@414c45582d396536393235", + "prevTxHash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer" + }, + { + "hash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "nonce": 7, + "value": 5000000000000000000, + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd1e2ftj4hj43lkduwps9xdmtgjnmugkh9mndph4n2cxfmf6ufvn4ks0zut84", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "issueNonFungible@4d594e4654@414c4558@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616E5472616E736665724E4654437265617465526F6C65@74727565", + "prevTxHash": "9a64f50a80a71e9234447aaa6209c0b6dc543790192432908a024bdaf0100c73", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 59692000, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "events": [ + { + "address": "erd1e2ftj4hj43lkduwps9xdmtgjnmugkh9mndph4n2cxfmf6ufvn4ks0zut84", + "identifier": "upgradeProperties", + "topics": [ + "QUxFWC05ZTY5MjU=", + "", + "Y2FuRnJlZXpl", + "dHJ1ZQ==", + "Y2FuV2lwZQ==", + "dHJ1ZQ==", + "Y2FuUGF1c2U=", + "dHJ1ZQ==", + "Y2FuVHJhbnNmZXJORlRDcmVhdGVSb2xl", + "dHJ1ZQ==", + "Y2FuVXBncmFkZQ==", + "dHJ1ZQ==", + "Y2FuQWRkU3BlY2lhbFJvbGVz", + "dHJ1ZQ==" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd1e2ftj4hj43lkduwps9xdmtgjnmugkh9mndph4n2cxfmf6ufvn4ks0zut84", + "identifier": "ESDTSetBurnRoleForAll", + "topics": [ + "QUxFWC05ZTY5MjU=", + "", + "", + "RVNEVFJvbGVCdXJuRm9yQWxs" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd1e2ftj4hj43lkduwps9xdmtgjnmugkh9mndph4n2cxfmf6ufvn4ks0zut84", + "identifier": "ESDTSetTokenType", + "topics": [ + "QUxFWC05ZTY5MjU=", + "Tm9uRnVuZ2libGVFU0RUdjI=" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd1e2ftj4hj43lkduwps9xdmtgjnmugkh9mndph4n2cxfmf6ufvn4ks0zut84", + "identifier": "issueNonFungible", + "topics": [ + "QUxFWC05ZTY5MjU=", + "TVlORlQ=", + "QUxFWA==", + "Tm9uRnVuZ2libGVFU0RUdjI=", + "" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "identifier": "writeLog", + "topics": [ + "ypK5VvKsf2bxwYFM3a0SnviLXLubQ3rNWDJ2nXEsnW0=" + ], + "data": "QDZmNmJANDE0YzQ1NTgyZDM5NjUzNjM5MzIzNQ==", + "additionalData": [ + "QDZmNmJANDE0YzQ1NTgyZDM5NjUzNjM5MzIzNQ==" + ] + } + ] + }, + "operation": "transfer", + "function": "issueNonFungible" + }, + { + "hash": "2bcadb8911a7b027073ff9da3ead77b533856da31033b86970dcfc4cab58c32a", + "nonce": 0, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetBurnRoleForAll@414c45582d396536393235", + "prevTxHash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "events": [ + { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "identifier": "completedTxEvent", + "topics": [ + "c2Se1God4pE5YSpIifQx2MbbzRN+Hb9PaYdlHBSF/zU=" + ], + "data": null, + "additionalData": null + } + ] + }, + "operation": "transfer" + }, + { + "hash": "78e4c87f3cc29dfd111fd72a424e1155e901aed7edcf6a32a6eef8c884607c6b", + "nonce": 1, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetTokenType@414c45582d396536393235@4e6f6e46756e6769626c65455344547632", + "prevTxHash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "ESDTSetTokenType" + }, + { + "hash": "227d1bb7322a956594f4caef7a28a67b5decf400753fab971c17278905b14ae6", + "nonce": 8, + "value": 96920000000000, + "receiver": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "prevTxHash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "returnMessage": "gas refund for relayer", + "logs": { + "address": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "events": [ + { + "address": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "identifier": "completedTxEvent", + "topics": [ + "c2Se1God4pE5YSpIifQx2MbbzRN+Hb9PaYdlHBSF/zU=" + ], + "data": null, + "additionalData": null + } + ] + }, + "operation": "transfer", + "isRefund": true + }, + { + "hash": "21abaea2ef611b30f5dcc79302bcfcc460f95a0c899ac705d1bbb7624de844c1", + "nonce": 1, + "value": 0, + "receiver": "erd1lllllllllllllllllllllllllllllllllllllllllllllllllupq9x7ny0", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetTokenType@414c45582d396536393235@4e6f6e46756e6769626c65455344547632", + "prevTxHash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "ESDTSetTokenType" + }, + { + "hash": "4b1676a8dcbc21513122c73a8474e2d4aca3941071d1df80fd694ca3770f7931", + "nonce": 0, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetBurnRoleForAll@414c45582d396536393235", + "prevTxHash": "73649ed46a1de29139612a4889f431d8c6dbcd137e1dbf4f6987651c1485ff35", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer" + } + ], + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n" + }, + { + "type": "inner", + "hash": "a7c5512b661949fe8323fc530a893eb822c361e658096c91a50f64c359d08f00", + "nonce": 16, + "value": "5000000000000000000", + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "gasPrice": 1000000000, + "gasLimit": 60000000, + "data": "aXNzdWVOb25GdW5naWJsZUA0ZDU5NGU0NjU0QDQxNGM0NTU4QDYzNjE2ZTQ2NzI2NTY1N2E2NUA3NDcyNzU2NUA2MzYxNmU1NzY5NzA2NUA3NDcyNzU2NUA2MzYxNmU1MDYxNzU3MzY1QDc0NzI3NTY1QDYzNjE2RTU0NzI2MTZFNzM2NjY1NzI0RTQ2NTQ0MzcyNjU2MTc0NjU1MjZGNkM2NUA3NDcyNzU2NQ==", + "smartContractResults": [ + { + "hash": "ffdf2a00e1d34065b7aaf4cdfcc85dbb83c75abd390a3eeaee61af79850868b4", + "nonce": 1, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetTokenType@414c45582d333765636131@4e6f6e46756e6769626c65455344547632", + "prevTxHash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "events": [ + { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "identifier": "completedTxEvent", + "topics": [ + "JST6zYrwXu6XFLoWsyM55+rmfAE1UB6UBMviH+e4594=" + ], + "data": null, + "additionalData": null + } + ] + }, + "operation": "ESDTSetTokenType" + }, + { + "hash": "4d51196e7c911c8486fed2a50eaa771e7e3bf86ebd3f04e2d13087f204f38fb2", + "nonce": 0, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetBurnRoleForAll@414c45582d333765636131", + "prevTxHash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "events": [ + { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", + "identifier": "completedTxEvent", + "topics": [ + "JST6zYrwXu6XFLoWsyM55+rmfAE1UB6UBMviH+e4594=" + ], + "data": null, + "additionalData": null + } + ] + }, + "operation": "transfer" + }, + { + "hash": "d0690fc92d1f9ad2ad3f8140d7400b0795382aa9f427b7206a2a54a7eda3eafc", + "nonce": 0, + "value": 0, + "receiver": "erd1lllllllllllllllllllllllllllllllllllllllllllllllllupq9x7ny0", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetBurnRoleForAll@414c45582d333765636131", + "prevTxHash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer" + }, + { + "hash": "50b212f61af4908a102e6b6896cb794ee3721efe4643b5a4cf3a60a4f88dc0d1", + "nonce": 17, + "value": 96920000000000, + "receiver": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "prevTxHash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "returnMessage": "gas refund for relayer", + "logs": { + "address": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "events": [ + { + "address": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "identifier": "completedTxEvent", + "topics": [ + "JST6zYrwXu6XFLoWsyM55+rmfAE1UB6UBMviH+e4594=" + ], + "data": null, + "additionalData": null + } + ] + }, + "operation": "transfer", + "isRefund": true + }, + { + "hash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "nonce": 16, + "value": 5000000000000000000, + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "issueNonFungible@4d594e4654@414c4558@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616E5472616E736665724E4654437265617465526F6C65@74727565", + "prevTxHash": "a7c5512b661949fe8323fc530a893eb822c361e658096c91a50f64c359d08f00", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 59692000, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "events": [ + { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "identifier": "upgradeProperties", + "topics": [ + "QUxFWC0zN2VjYTE=", + "", + "Y2FuRnJlZXpl", + "dHJ1ZQ==", + "Y2FuV2lwZQ==", + "dHJ1ZQ==", + "Y2FuUGF1c2U=", + "dHJ1ZQ==", + "Y2FuVHJhbnNmZXJORlRDcmVhdGVSb2xl", + "dHJ1ZQ==", + "Y2FuVXBncmFkZQ==", + "dHJ1ZQ==", + "Y2FuQWRkU3BlY2lhbFJvbGVz", + "dHJ1ZQ==" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "identifier": "ESDTSetBurnRoleForAll", + "topics": [ + "QUxFWC0zN2VjYTE=", + "", + "", + "RVNEVFJvbGVCdXJuRm9yQWxs" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "identifier": "ESDTSetTokenType", + "topics": [ + "QUxFWC0zN2VjYTE=", + "Tm9uRnVuZ2libGVFU0RUdjI=" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw", + "identifier": "issueNonFungible", + "topics": [ + "QUxFWC0zN2VjYTE=", + "TVlORlQ=", + "QUxFWA==", + "Tm9uRnVuZ2libGVFU0RUdjI=", + "" + ], + "data": null, + "additionalData": null + }, + { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "identifier": "writeLog", + "topics": [ + "KQclkV+pF/02MiTDTYE5sCvEqMWPbC093vxwHQBTJEM=" + ], + "data": "QDZmNmJANDE0YzQ1NTgyZDMzMzc2NTYzNjEzMQ==", + "additionalData": [ + "QDZmNmJANDE0YzQ1NTgyZDMzMzc2NTYzNjEzMQ==" + ] + } + ] + }, + "operation": "transfer", + "function": "issueNonFungible" + }, + { + "hash": "76a53f1fef3ed830e6c0a0d13a6eb22bde6d3e9e012badc647aeb4920f61c326", + "nonce": 0, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetBurnRoleForAll@414c45582d333765636131", + "prevTxHash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer" + }, + { + "hash": "9c4aefdc190c3e24a3dc8b6aea3bab00d113d35cc68f9ee771a4129f18f7418f", + "nonce": 1, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetTokenType@414c45582d333765636131@4e6f6e46756e6769626c65455344547632", + "prevTxHash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "ESDTSetTokenType" + }, + { + "hash": "c1bf11e58cd047f116514198b218001a82ae951c69166f36b391277cf0700b9e", + "nonce": 1, + "value": 0, + "receiver": "erd1lllllllllllllllllllllllllllllllllllllllllllllllllupq9x7ny0", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "ESDTSetTokenType@414c45582d333765636131@4e6f6e46756e6769626c65455344547632", + "prevTxHash": "2524facd8af05eee9714ba16b32339e7eae67c0135501e9404cbe21fe7b8e7de", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "ESDTSetTokenType" + } + ], + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n" + }, + { + "type": "inner", + "hash": "6ae9c096b35ff7c62e47d3fcc38fd5fcc9c91a6b19db450aa7805017d54290ba", + "nonce": 1, + "value": "50000000000000000", + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd136rl878j09mev24gzpy70k2wfm3xmvj5ucwxffs9v5t5sk3kshtszz25z9", + "gasPrice": 1000000000, + "gasLimit": 60000000, + "data": "aXNzdWVOb25GdW5naWJsZUA0ZDU5NGU0NjU0QDQxNGM0NTU4QDYzNjE2ZTQ2NzI2NTY1N2E2NUA3NDcyNzU2NUA2MzYxNmU1NzY5NzA2NUA3NDcyNzU2NUA2MzYxNmU1MDYxNzU3MzY1QDc0NzI3NTY1QDYzNjE2RTU0NzI2MTZFNzM2NjY1NzI0RTQ2NTQ0MzcyNjU2MTc0NjU1MjZGNkM2NUA3NDcyNzU2NQ==", + "smartContractResults": [ + { + "hash": "f1bca8643524bee2451253bb390cf9b805fd06baea04513423d5fdbf2ab01bf8", + "nonce": 1, + "value": 50000000000000000, + "receiver": "erd136rl878j09mev24gzpy70k2wfm3xmvj5ucwxffs9v5t5sk3kshtszz25z9", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "data": "@6f7574206f662066756e6473", + "prevTxHash": "e05b22281de80469629d5fbfa50362d7ac7f44e31bd66cb420f2409e8569b69a", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 0, + "gasPrice": 0, + "callType": 0, + "returnMessage": "callValue not equals with baseIssuingCost", + "originalSender": "erd136rl878j09mev24gzpy70k2wfm3xmvj5ucwxffs9v5t5sk3kshtszz25z9", + "operation": "transfer" + }, + { + "hash": "e05b22281de80469629d5fbfa50362d7ac7f44e31bd66cb420f2409e8569b69a", + "nonce": 1, + "value": 50000000000000000, + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd136rl878j09mev24gzpy70k2wfm3xmvj5ucwxffs9v5t5sk3kshtszz25z9", + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n", + "relayedValue": 0, + "data": "issueNonFungible@4d594e4654@414c4558@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616E5472616E736665724E4654437265617465526F6C65@74727565", + "prevTxHash": "6ae9c096b35ff7c62e47d3fcc38fd5fcc9c91a6b19db450aa7805017d54290ba", + "originalTxHash": "5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae", + "gasLimit": 59692000, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "identifier": "signalError", + "topics": [ + "jofz+PJ5d5YqqBBJ59lOTuJtslTmHGSmBWUXSFo2hdc=", + "Y2FsbFZhbHVlIG5vdCBlcXVhbHMgd2l0aCBiYXNlSXNzdWluZ0Nvc3Q=" + ], + "data": "QDZmNzU3NDIwNmY2NjIwNjY3NTZlNjQ3Mw==", + "additionalData": [ + "QDZmNzU3NDIwNmY2NjIwNjY3NTZlNjQ3Mw==" + ] + }, + { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "identifier": "signalError", + "topics": [ + "9NowIif4EqFJGQM/krxwmXMhtLwJj5ZYjLny/dDfDek=", + "Y2FsbFZhbHVlIG5vdCBlcXVhbHMgd2l0aCBiYXNlSXNzdWluZ0Nvc3Q=" + ], + "data": null, + "additionalData": [ + "" + ] + } + ] + }, + "operation": "transfer", + "function": "issueNonFungible" + } + ], + "relayerAddress": "erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n" + } + ] +} diff --git a/outport/mock/economicsDataMock.go b/outport/mock/economicsDataMock.go index cf9cf4dc848..30d83ebce8d 100644 --- a/outport/mock/economicsDataMock.go +++ b/outport/mock/economicsDataMock.go @@ -20,6 +20,21 @@ const ( type EconomicsHandlerMock struct { } +// ComputeRelayedTxV3GasUnits - +func (e *EconomicsHandlerMock) ComputeRelayedTxV3GasUnits(_ coreData.TransactionWithFeeHandler, _ uint32) uint64 { + return 0 +} + +// ComputeRelayedTxFees - +func (e *EconomicsHandlerMock) ComputeRelayedTxFees(_ coreData.TransactionWithFeeHandler) (*big.Int, *big.Int, error) { + return nil, nil, nil +} + +// ComputeGasUnitsFromRefundValue - +func (e *EconomicsHandlerMock) ComputeGasUnitsFromRefundValue(_ coreData.TransactionWithFeeHandler, _ *big.Int) uint64 { + return 0 +} + // MaxGasLimitPerBlock - func (e *EconomicsHandlerMock) MaxGasLimitPerBlock(_ uint32) uint64 { return 0 diff --git a/outport/process/interface.go b/outport/process/interface.go index bec97f362b3..d4050e298f3 100644 --- a/outport/process/interface.go +++ b/outport/process/interface.go @@ -32,6 +32,9 @@ type GasConsumedProvider interface { // EconomicsDataHandler defines the functionality needed for economics data type EconomicsDataHandler interface { + ComputeRelayedTxV3GasUnits(tx data.TransactionWithFeeHandler, epoch uint32) uint64 + ComputeRelayedTxFees(tx data.TransactionWithFeeHandler) (*big.Int, *big.Int, error) + ComputeGasUnitsFromRefundValue(tx data.TransactionWithFeeHandler, refundValue *big.Int) uint64 ComputeGasUsedAndFeeBasedOnRefundValue(tx data.TransactionWithFeeHandler, refundValue *big.Int) (uint64, *big.Int) ComputeTxFeeBasedOnGasUsed(tx data.TransactionWithFeeHandler, gasUsed uint64) *big.Int ComputeTxFee(tx data.TransactionWithFeeHandler) *big.Int diff --git a/outport/process/transactionsfee/interface.go b/outport/process/transactionsfee/interface.go index 53042467442..94991486e0f 100644 --- a/outport/process/transactionsfee/interface.go +++ b/outport/process/transactionsfee/interface.go @@ -10,6 +10,9 @@ import ( // FeesProcessorHandler defines the interface for the transaction fees processor type FeesProcessorHandler interface { + ComputeRelayedTxV3GasUnits(tx data.TransactionWithFeeHandler, epoch uint32) uint64 + ComputeRelayedTxFees(tx data.TransactionWithFeeHandler) (*big.Int, *big.Int, error) + ComputeGasUnitsFromRefundValue(tx data.TransactionWithFeeHandler, refundValue *big.Int) uint64 ComputeGasUsedAndFeeBasedOnRefundValue(tx data.TransactionWithFeeHandler, refundValue *big.Int) (uint64, *big.Int) ComputeTxFeeBasedOnGasUsed(tx data.TransactionWithFeeHandler, gasUsed uint64) *big.Int ComputeTxFee(tx data.TransactionWithFeeHandler) *big.Int diff --git a/outport/process/transactionsfee/transactionsFeeProcessor.go b/outport/process/transactionsfee/transactionsFeeProcessor.go index dccf0366b23..12f51d59108 100644 --- a/outport/process/transactionsfee/transactionsFeeProcessor.go +++ b/outport/process/transactionsfee/transactionsFeeProcessor.go @@ -136,7 +136,7 @@ func (tep *transactionsFeeProcessor) prepareNormalTxs(transactionsAndScrs *trans } if len(txHandler.GetUserTransactions()) > 0 { - tep.prepareRelayedTxV3WithResults(txHashHex, txWithResult) + tep.prepareRelayedTxV3WithResults(txHashHex, txWithResult, epoch) continue } @@ -243,7 +243,7 @@ func (tep *transactionsFeeProcessor) handleRelayedV2(args [][]byte, tx *transact return big.NewInt(0).Add(fee, innerFee), true } -func (tep *transactionsFeeProcessor) prepareRelayedTxV3WithResults(txHashHex string, txWithResults *transactionWithResults) { +func (tep *transactionsFeeProcessor) prepareRelayedTxV3WithResults(txHashHex string, txWithResults *transactionWithResults, epoch uint32) { refundsValue := big.NewInt(0) for _, scrHandler := range txWithResults.scrs { scr, ok := scrHandler.GetTxHandler().(*smartContractResult.SmartContractResult) @@ -258,6 +258,22 @@ func (tep *transactionsFeeProcessor) prepareRelayedTxV3WithResults(txHashHex str refundsValue.Add(refundsValue, scr.Value) } + isRelayedV3 := len(txWithResults.GetTxHandler().GetUserTransactions()) > 0 + if isRelayedV3 { + _, totalRelayedFee, err := tep.txFeeCalculator.ComputeRelayedTxFees(txWithResults.GetTxHandler()) + if err != nil { + tep.log.Warn("transactionsFeeProcessor.prepareRelayedTxV3WithResults: cannot compute relayed tx fee", "hash", txHashHex, "error", err.Error()) + return + } + + relayedTxGasUnits := tep.txFeeCalculator.ComputeRelayedTxV3GasUnits(txWithResults.GetTxHandler(), epoch) + + txWithResults.GetFeeInfo().SetGasUsed(relayedTxGasUnits) + txWithResults.GetFeeInfo().SetFee(totalRelayedFee) + + return + } + gasUsed, fee := tep.txFeeCalculator.ComputeGasUsedAndFeeBasedOnRefundValue(txWithResults.GetTxHandler(), refundsValue) txWithResults.GetFeeInfo().SetGasUsed(gasUsed) @@ -328,6 +344,17 @@ func (tep *transactionsFeeProcessor) prepareScrsNoTx(transactionsAndScrs *transa continue } + isRelayedV3 := len(txFromStorage.InnerTransactions) > 0 + if isRelayedV3 { + gasUnits := tep.txFeeCalculator.ComputeGasUnitsFromRefundValue(txFromStorage, scr.Value) + + scrHandler.GetFeeInfo().SetForRelayed() + scrHandler.GetFeeInfo().SetGasUsed(gasUnits) + scrHandler.GetFeeInfo().SetFee(scr.Value) + + continue + } + gasUsed, fee := tep.txFeeCalculator.ComputeGasUsedAndFeeBasedOnRefundValue(txFromStorage, scr.Value) scrHandler.GetFeeInfo().SetGasUsed(gasUsed) diff --git a/outport/process/transactionsfee/transactionsFeeProcessor_test.go b/outport/process/transactionsfee/transactionsFeeProcessor_test.go index 6f0e0f94c35..9150939b2ec 100644 --- a/outport/process/transactionsfee/transactionsFeeProcessor_test.go +++ b/outport/process/transactionsfee/transactionsFeeProcessor_test.go @@ -10,10 +10,14 @@ import ( outportcore "github.com/multiversx/mx-chain-core-go/data/outport" "github.com/multiversx/mx-chain-core-go/data/smartContractResult" "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/multiversx/mx-chain-go/common" + "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/outport/mock" "github.com/multiversx/mx-chain-go/process" + "github.com/multiversx/mx-chain-go/process/economics" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" + epochNotifierMock "github.com/multiversx/mx-chain-go/testscommon/epochNotifier" "github.com/multiversx/mx-chain-go/testscommon/genericMocks" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" logger "github.com/multiversx/mx-chain-logger-go" @@ -597,3 +601,108 @@ func TestMoveBalanceWithSignalError(t *testing.T) { require.Nil(t, err) require.Equal(t, uint64(225_500), initialTx.GetFeeInfo().GetGasUsed()) } + +func newEconomicsData(t *testing.T) FeesProcessorHandler { + economicsDataMock, err := economics.NewEconomicsData(economics.ArgsNewEconomicsData{ + TxVersionChecker: &testscommon.TxVersionCheckerStub{}, + Economics: &config.EconomicsConfig{ + GlobalSettings: config.GlobalSettings{ + GenesisTotalSupply: "2000000000000000000000", + MinimumInflation: 0, + YearSettings: []*config.YearSetting{ + { + Year: 0, + MaximumInflation: 0.01, + }, + }, + }, + RewardsSettings: config.RewardsSettings{ + RewardsConfigByEpoch: []config.EpochRewardSettings{{ + ProtocolSustainabilityAddress: "erd1932eft30w753xyvme8d49qejgkjc09n5e49w4mwdjtm0neld797su0dlxp", + TopUpGradientPoint: "300000000000000000000", + }}, + }, + FeeSettings: config.FeeSettings{ + GasLimitSettings: []config.GasLimitSetting{ + { + MaxGasLimitPerBlock: "10000000000", + MaxGasLimitPerMiniBlock: "10000000000", + MaxGasLimitPerMetaBlock: "10000000000", + MaxGasLimitPerMetaMiniBlock: "10000000000", + MaxGasLimitPerTx: "10000000000", + MinGasLimit: "50000", + ExtraGasLimitGuardedTx: "50000", + }, + }, + + MinGasPrice: "1000000000", + GasPerDataByte: "1500", + GasPriceModifier: 0.01, + MaxGasPriceSetGuardian: "100000", + }, + }, + EpochNotifier: &epochNotifierMock.EpochNotifierStub{}, + EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(common.GasPriceModifierFlag), + }) + require.Nil(t, err) + + _ = economicsDataMock.SetTxTypeHandler(&testscommon.TxTypeHandlerMock{}) + + return economicsDataMock +} + +func TestRelayedV3WithMultipleInnerTxs(t *testing.T) { + txHash := []byte("5c5cdb939473e76ee85af17eb02dbeca5d879bd19c7c050d0be6d2c901b9f6ae") + + initialTx := &outportcore.TxInfo{Transaction: &transaction.Transaction{ + Nonce: 47, + GasLimit: 500_000_000, + GasPrice: 1000000000, + SndAddr: []byte("erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n"), + RcvAddr: []byte("erd17ndrqg38lqf2zjgeqvle90rsn9ejrd9upx8evkyvh8e0m5xlph5scv9l6n"), + InnerTransactions: []*transaction.Transaction{ + { + Nonce: 7, + SndAddr: []byte("erd1e2ftj4hj43lkduwps9xdmtgjnmugkh9mndph4n2cxfmf6ufvn4ks0zut84"), + RcvAddr: []byte("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"), + Data: []byte("issueNonFungible@4d594e4654@414c4558@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616E5472616E736665724E4654437265617465526F6C65@74727565"), + GasPrice: 1000000000, + GasLimit: 60_000_000, + }, + { + Nonce: 16, + SndAddr: []byte("erd19yrjty2l4ytl6d3jynp5mqfekq4uf2x93akz60w7l3cp6qzny3psnfyerw"), + RcvAddr: []byte("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"), + Data: []byte("issueNonFungible@4d594e4654@414c4558@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616E5472616E736665724E4654437265617465526F6C65@74727565"), + GasPrice: 1000000000, + GasLimit: 60_000_000, + }, + { + Nonce: 1, + SndAddr: []byte("erd136rl878j09mev24gzpy70k2wfm3xmvj5ucwxffs9v5t5sk3kshtszz25z9"), + RcvAddr: []byte("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"), + Data: []byte("issueNonFungible@4d594e4654@414c4558@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616E5472616E736665724E4654437265617465526F6C65@74727565"), + GasPrice: 1000000000, + GasLimit: 60_000_000, + }, + }, + }, FeeInfo: &outportcore.FeeInfo{Fee: big.NewInt(0)}} + + pool := &outportcore.TransactionPool{ + Transactions: map[string]*outportcore.TxInfo{ + hex.EncodeToString(txHash): initialTx, + }, + } + + arg := prepareMockArg() + arg.TxFeeCalculator = newEconomicsData(t) + txsFeeProc, err := NewTransactionsFeeProcessor(arg) + require.NotNil(t, txsFeeProc) + require.Nil(t, err) + + err = txsFeeProc.PutFeeAndGasUsed(pool, 0) + require.Nil(t, err) + require.Equal(t, uint64(180_150_000), initialTx.GetFeeInfo().GetGasUsed()) + require.Equal(t, "1074000000000000", initialTx.GetFeeInfo().GetFee().String()) + require.Equal(t, "1074000000000000", initialTx.GetFeeInfo().GetInitialPaidFee().String()) +} diff --git a/process/economics/economicsData.go b/process/economics/economicsData.go index 170377e62d3..47970c6b3a9 100644 --- a/process/economics/economicsData.go +++ b/process/economics/economicsData.go @@ -351,6 +351,17 @@ func (ed *economicsData) ComputeRelayedTxFees(tx data.TransactionWithFeeHandler) return relayerFee, totalFee, nil } +// ComputeRelayedTxV3GasUnits will compute the relayed tx gas units based on epoch +func (ed *economicsData) ComputeRelayedTxV3GasUnits(tx data.TransactionWithFeeHandler, epoch uint32) uint64 { + gasUnits := uint64(len(tx.GetUserTransactions())) * ed.getMinGasLimit(epoch) + + for _, innerTx := range tx.GetUserTransactions() { + gasUnits += innerTx.GetGasLimit() + } + + return gasUnits +} + func (ed *economicsData) getTotalFeesRequiredForInnerTxs(innerTxs []data.TransactionHandler) *big.Int { totalFees := big.NewInt(0) for _, innerTx := range innerTxs { @@ -580,6 +591,16 @@ func (ed *economicsData) ComputeGasUsedAndFeeBasedOnRefundValue(tx data.Transact return ed.ComputeGasUsedAndFeeBasedOnRefundValueInEpoch(tx, refundValue, currentEpoch) } +// ComputeGasUnitsFromRefundValue will compute the gas unit based on the refund value +func (ed *economicsData) ComputeGasUnitsFromRefundValue(tx data.TransactionWithFeeHandler, refundValue *big.Int) uint64 { + currentEpoch := ed.enableEpochsHandler.GetCurrentEpoch() + gasPrice := ed.GasPriceForProcessingInEpoch(tx, currentEpoch) + refund := big.NewInt(0).Set(refundValue) + gasUnits := refund.Div(refund, big.NewInt(int64(gasPrice))) + + return gasUnits.Uint64() +} + // ComputeGasUsedAndFeeBasedOnRefundValueInEpoch will compute gas used value and transaction fee using refund value from a SCR in a specific epoch func (ed *economicsData) ComputeGasUsedAndFeeBasedOnRefundValueInEpoch(tx data.TransactionWithFeeHandler, refundValue *big.Int, epoch uint32) (uint64, *big.Int) { if refundValue.Cmp(big.NewInt(0)) == 0 { diff --git a/process/economics/economicsData_test.go b/process/economics/economicsData_test.go index f1a66e25dcd..1c17feb6833 100644 --- a/process/economics/economicsData_test.go +++ b/process/economics/economicsData_test.go @@ -1754,3 +1754,79 @@ func TestEconomicsData_SetTxTypeHandler(t *testing.T) { err = economicsData.SetTxTypeHandler(&testscommon.TxTypeHandlerMock{}) require.NoError(t, err) } + +func TestEconomicsData_ComputeRelayedTxV3GasUnits(t *testing.T) { + args := createArgsForEconomicsData(0.01) + economicsData, _ := economics.NewEconomicsData(args) + require.NotNil(t, economicsData) + + tx := &transaction.Transaction{ + Nonce: 0, + Value: big.NewInt(0), + RcvAddr: []byte("rel"), + SndAddr: []byte("rel"), + GasPrice: 1, + GasLimit: 500_000, + InnerTransactions: []*transaction.Transaction{ + { + Nonce: 0, + Value: big.NewInt(1), + RcvAddr: []byte("rcv1"), + SndAddr: []byte("snd1"), + GasPrice: 1, + GasLimit: 3_000, + RelayerAddr: []byte("rel"), + }, + { + Nonce: 0, + Value: big.NewInt(1), + RcvAddr: []byte("rcv1"), + SndAddr: []byte("snd2"), + GasPrice: 1, + GasLimit: 7_000, + RelayerAddr: []byte("rel"), + }, + }, + } + + gasUnits := economicsData.ComputeRelayedTxV3GasUnits(tx, 0) + require.Equal(t, uint64(11_000), gasUnits) +} + +func TestEconomicsData_ComputeGasUnitsFromRefundValue(t *testing.T) { + args := createArgsForEconomicsData(0.01) + economicsData, _ := economics.NewEconomicsData(args) + require.NotNil(t, economicsData) + + tx := &transaction.Transaction{ + Nonce: 0, + Value: big.NewInt(0), + RcvAddr: []byte("rel"), + SndAddr: []byte("rel"), + GasPrice: 1000000000, + GasLimit: 200_000_000, + InnerTransactions: []*transaction.Transaction{ + { + Nonce: 0, + Value: big.NewInt(1), + RcvAddr: []byte("rcv1"), + SndAddr: []byte("snd1"), + GasPrice: 1, + GasLimit: 3_000, + RelayerAddr: []byte("rel"), + }, + { + Nonce: 0, + Value: big.NewInt(1), + RcvAddr: []byte("rcv1"), + SndAddr: []byte("snd2"), + GasPrice: 1, + GasLimit: 7_000, + RelayerAddr: []byte("rel"), + }, + }, + } + + gasUnits := economicsData.ComputeGasUnitsFromRefundValue(tx, big.NewInt(1074000000000000)) + require.Equal(t, uint64(107_400_000), gasUnits) +} diff --git a/process/interface.go b/process/interface.go index 8e943d0a44e..f93e5ed130c 100644 --- a/process/interface.go +++ b/process/interface.go @@ -700,6 +700,8 @@ type feeHandler interface { ComputeGasUsedAndFeeBasedOnRefundValueInEpoch(tx data.TransactionWithFeeHandler, refundValue *big.Int, epoch uint32) (uint64, *big.Int) ComputeTxFeeBasedOnGasUsedInEpoch(tx data.TransactionWithFeeHandler, gasUsed uint64, epoch uint32) *big.Int ComputeRelayedTxFees(tx data.TransactionWithFeeHandler) (*big.Int, *big.Int, error) + ComputeRelayedTxV3GasUnits(tx data.TransactionWithFeeHandler, epoch uint32) uint64 + ComputeGasUnitsFromRefundValue(tx data.TransactionWithFeeHandler, refundValue *big.Int) uint64 } // TxGasHandler handles a transaction gas and gas cost diff --git a/testscommon/economicsmocks/economicsDataHandlerStub.go b/testscommon/economicsmocks/economicsDataHandlerStub.go index c76ce6c59a2..7c5c8a7ad4f 100644 --- a/testscommon/economicsmocks/economicsDataHandlerStub.go +++ b/testscommon/economicsmocks/economicsDataHandlerStub.go @@ -52,6 +52,16 @@ type EconomicsHandlerStub struct { ComputeMoveBalanceFeeInEpochCalled func(tx data.TransactionWithFeeHandler, epoch uint32) *big.Int } +// ComputeRelayedTxV3GasUnits - +func (e *EconomicsHandlerStub) ComputeRelayedTxV3GasUnits(_ data.TransactionWithFeeHandler, _ uint32) uint64 { + return 0 +} + +// ComputeGasUnitsFromRefundValue - +func (e *EconomicsHandlerStub) ComputeGasUnitsFromRefundValue(_ data.TransactionWithFeeHandler, _ *big.Int) uint64 { + return 0 +} + // ComputeFeeForProcessing - func (e *EconomicsHandlerStub) ComputeFeeForProcessing(tx data.TransactionWithFeeHandler, gasToUse uint64) *big.Int { if e.ComputeFeeForProcessingCalled != nil { diff --git a/testscommon/economicsmocks/economicsHandlerMock.go b/testscommon/economicsmocks/economicsHandlerMock.go index 0c92fff0238..d169de8aa60 100644 --- a/testscommon/economicsmocks/economicsHandlerMock.go +++ b/testscommon/economicsmocks/economicsHandlerMock.go @@ -52,6 +52,16 @@ type EconomicsHandlerMock struct { SetTxTypeHandlerCalled func(txTypeHandler process.TxTypeHandler) error } +// ComputeRelayedTxV3GasUnits - +func (ehm *EconomicsHandlerMock) ComputeRelayedTxV3GasUnits(_ data.TransactionWithFeeHandler, _ uint32) uint64 { + return 0 +} + +// ComputeGasUnitsFromRefundValue - +func (ehm *EconomicsHandlerMock) ComputeGasUnitsFromRefundValue(_ data.TransactionWithFeeHandler, _ *big.Int) uint64 { + return 0 +} + // LeaderPercentage - func (ehm *EconomicsHandlerMock) LeaderPercentage() float64 { return ehm.LeaderPercentageCalled() diff --git a/testscommon/feeComputerStub.go b/testscommon/feeComputerStub.go index 884351576d9..aba0176117b 100644 --- a/testscommon/feeComputerStub.go +++ b/testscommon/feeComputerStub.go @@ -13,6 +13,15 @@ type FeeComputerStub struct { ComputeTxFeeBasedOnGasUsedCalled func(tx *transaction.ApiTransactionResult, gasUsed uint64) *big.Int ComputeGasLimitCalled func(tx *transaction.ApiTransactionResult) uint64 ComputeMoveBalanceFeeCalled func(tx *transaction.ApiTransactionResult) *big.Int + ComputeGasUnitForRelayedV3Called func(tx *transaction.ApiTransactionResult) uint64 +} + +func (stub *FeeComputerStub) ComputeGasUnitForRelayedV3(tx *transaction.ApiTransactionResult) uint64 { + if stub.ComputeGasUnitForRelayedV3Called != nil { + return stub.ComputeGasUnitForRelayedV3Called(tx) + } + + return 0 } // ComputeTransactionFee -