From 168520c1b18011c44242c1ec176c8dbc1e764112 Mon Sep 17 00:00:00 2001 From: cosmatudor Date: Tue, 12 Nov 2024 14:30:40 +0200 Subject: [PATCH 1/7] add checks for mint/burn and locked token balances + initial supply --- .../ethToMultiversXWithChainSimulator_test.go | 15 ++ .../slowTests/framework/ethereumHandler.go | 41 +++- .../slowTests/framework/multiversxHandler.go | 80 +++++-- .../relayers/slowTests/framework/testSetup.go | 206 ++++++++++++++++-- .../slowTests/startsFromEthereumFlow.go | 1 - 5 files changed, 308 insertions(+), 35 deletions(-) diff --git a/integrationTests/relayers/slowTests/ethToMultiversXWithChainSimulator_test.go b/integrationTests/relayers/slowTests/ethToMultiversXWithChainSimulator_test.go index 75ef37da..cb0e0382 100644 --- a/integrationTests/relayers/slowTests/ethToMultiversXWithChainSimulator_test.go +++ b/integrationTests/relayers/slowTests/ethToMultiversXWithChainSimulator_test.go @@ -149,6 +149,21 @@ func TestRelayersShouldExecuteTransfersWithInitSupply(t *testing.T) { ) } +func TestRelayersShouldExecuteTransfersWithInitSupplyMintBurn(t *testing.T) { + eurocToken := GenerateTestEUROCToken() + eurocToken.InitialSupplyValue = "100010" + + mexToken := GenerateTestMEXToken() + mexToken.InitialSupplyValue = "300000" + + _ = testRelayersWithChainSimulatorAndTokens( + t, + make(chan error), + eurocToken, + mexToken, + ) +} + func testRelayersWithChainSimulatorAndTokens(tb testing.TB, manualStopChan chan error, tokens ...framework.TestTokenParams) *framework.TestSetup { startsFromEthFlow, startsFromMvXFlow := createFlowsBasedOnToken(tb, tokens...) diff --git a/integrationTests/relayers/slowTests/framework/ethereumHandler.go b/integrationTests/relayers/slowTests/framework/ethereumHandler.go index 5d3eb69c..7c06922a 100644 --- a/integrationTests/relayers/slowTests/framework/ethereumHandler.go +++ b/integrationTests/relayers/slowTests/framework/ethereumHandler.go @@ -277,14 +277,22 @@ func (handler *EthereumHandler) IssueAndWhitelistToken(ctx context.Context, para handler.checkEthTxResult(ctx, tx.Hash()) if len(params.InitialSupplyValue) > 0 { - if params.IsMintBurnOnEth { - mintAmount, ok := big.NewInt(0).SetString(params.InitialSupplyValue, 10) - require.True(handler, ok) + initialSupply, ok := big.NewInt(0).SetString(params.InitialSupplyValue, 10) + require.True(handler, ok) - tx, err = handler.SafeContract.InitSupplyMintBurn(auth, erc20Address, mintAmount, zeroValueBigInt) - require.NoError(handler, err) + if params.IsMintBurnOnEth { + var tx2 *types.Transaction + var err2 error + if params.IsNativeOnEth { + burnAmount := initialSupply + tx2, err2 = handler.SafeContract.InitSupplyMintBurn(auth, erc20Address, zeroValueBigInt, burnAmount) + } else { + mintAmount := initialSupply + tx2, err2 = handler.SafeContract.InitSupplyMintBurn(auth, erc20Address, mintAmount, zeroValueBigInt) + } + require.NoError(handler, err2) handler.SimulatedChain.Commit() - handler.checkEthTxResult(ctx, tx.Hash()) + handler.checkEthTxResult(ctx, tx2.Hash()) } else { // reset the tokens value for the safe contract, so it will "know" about the balance that it has in the ERC20 contract tx, err = handler.SafeContract.ResetTotalBalance(auth, erc20Address) @@ -492,6 +500,27 @@ func (handler *EthereumHandler) Mint(ctx context.Context, params TestTokenParams handler.checkEthTxResult(ctx, tx.Hash()) } +func (handler *EthereumHandler) GetTotalBalancesForToken(ctx context.Context, address common.Address) *big.Int { + opts := &bind.CallOpts{Context: ctx} + balance, err := handler.SafeContract.TotalBalances(opts, address) + require.NoError(handler, err) + return balance +} + +func (handler *EthereumHandler) GetBurnBalanceForToken(ctx context.Context, address common.Address) *big.Int { + opts := &bind.CallOpts{Context: ctx} + balance, err := handler.SafeContract.BurnBalances(opts, address) + require.NoError(handler, err) + return balance +} + +func (handler *EthereumHandler) GetMintBalanceForToken(ctx context.Context, address common.Address) *big.Int { + opts := &bind.CallOpts{Context: ctx} + balance, err := handler.SafeContract.MintBalances(opts, address) + require.NoError(handler, err) + return balance +} + // Close will close the resources allocated func (handler *EthereumHandler) Close() error { return handler.SimulatedChain.Close() diff --git a/integrationTests/relayers/slowTests/framework/multiversxHandler.go b/integrationTests/relayers/slowTests/framework/multiversxHandler.go index 678fe55e..b59052d4 100644 --- a/integrationTests/relayers/slowTests/framework/multiversxHandler.go +++ b/integrationTests/relayers/slowTests/framework/multiversxHandler.go @@ -75,6 +75,9 @@ const ( getTransactionFeesFunction = "getTransactionFees" initSupplyMintBurnEsdtSafe = "initSupplyMintBurnEsdtSafe" initSupplyEsdtSafe = "initSupplyEsdtSafe" + getMintBalances = "getMintBalances" + getBurnBalances = "getBurnBalances" + getTotalBalances = "getTotalBalances" ) var ( @@ -800,21 +803,41 @@ func (handler *MultiversxHandler) setInitialSupply(ctx context.Context, params I require.True(handler, okConvert) if params.IsMintBurnOnMvX { - hash, txResult := handler.ChainSimulator.ScCall( - ctx, - handler.OwnerKeys.MvxSk, - handler.MultisigAddress, - zeroStringValue, - setCallsGasLimit, - initSupplyMintBurnEsdtSafe, - []string{ - hex.EncodeToString([]byte(tkData.MvxChainSpecificToken)), - hex.EncodeToString(initialSupply.Bytes()), - hex.EncodeToString([]byte{0}), - }, - ) - log.Info("initial supply tx executed", "hash", hash, "status", txResult.Status, - "initial mint", params.InitialSupplyValue, "initial burned", "0") + if params.IsNativeOnMvX { + burnAmount := initialSupply + hash, txResult := handler.ChainSimulator.ScCall( + ctx, + handler.OwnerKeys.MvxSk, + handler.MultisigAddress, + zeroStringValue, + setCallsGasLimit, + initSupplyMintBurnEsdtSafe, + []string{ + hex.EncodeToString([]byte(tkData.MvxChainSpecificToken)), + hex.EncodeToString(zeroValueBigInt.Bytes()), + hex.EncodeToString(burnAmount.Bytes()), + }, + ) + log.Info("initial supply tx executed", "hash", hash, "status", txResult.Status, + "initial mint", "0", "initial burned", params.InitialSupplyValue) + } else { + mintAmount := initialSupply + hash, txResult := handler.ChainSimulator.ScCall( + ctx, + handler.OwnerKeys.MvxSk, + handler.MultisigAddress, + zeroStringValue, + setCallsGasLimit, + initSupplyMintBurnEsdtSafe, + []string{ + hex.EncodeToString([]byte(tkData.MvxChainSpecificToken)), + hex.EncodeToString(mintAmount.Bytes()), + hex.EncodeToString(zeroValueBigInt.Bytes()), + }, + ) + log.Info("initial supply tx executed", "hash", hash, "status", txResult.Status, + "initial mint", params.InitialSupplyValue, "initial burned", "0") + } } else { hash, txResult := handler.ChainSimulator.ScCall( ctx, @@ -1043,6 +1066,33 @@ func (handler *MultiversxHandler) TransferToken(ctx context.Context, source Keys "hash", hash, "status", txResult.Status) } +func (handler *MultiversxHandler) GetTotalBalancesForToken(ctx context.Context, token string) *big.Int { + queryParams := []string{ + hex.EncodeToString([]byte(token)), + } + responseData := handler.ChainSimulator.ExecuteVMQuery(ctx, handler.SafeAddress, getTotalBalances, queryParams) + value := big.NewInt(0).SetBytes(responseData[0]) + return value +} + +func (handler *MultiversxHandler) GetMintedAmountForToken(ctx context.Context, token string) *big.Int { + queryParams := []string{ + hex.EncodeToString([]byte(token)), + } + responseData := handler.ChainSimulator.ExecuteVMQuery(ctx, handler.SafeAddress, getMintBalances, queryParams) + value := big.NewInt(0).SetBytes(responseData[0]) + return value +} + +func (handler *MultiversxHandler) GetBurnedAmountForToken(ctx context.Context, token string) *big.Int { + queryParams := []string{ + hex.EncodeToString([]byte(token)), + } + responseData := handler.ChainSimulator.ExecuteVMQuery(ctx, handler.SafeAddress, getBurnBalances, queryParams) + value := big.NewInt(0).SetBytes(responseData[0]) + return value +} + func getHexBool(input bool) string { if input { return hexTrue diff --git a/integrationTests/relayers/slowTests/framework/testSetup.go b/integrationTests/relayers/slowTests/framework/testSetup.go index 5d07a875..5bc2a23e 100644 --- a/integrationTests/relayers/slowTests/framework/testSetup.go +++ b/integrationTests/relayers/slowTests/framework/testSetup.go @@ -231,12 +231,35 @@ func (setup *TestSetup) IsTransferDoneFromEthereum(sender KeysHolder, receiver K return isDone } -func (setup *TestSetup) isTransferDoneFromEthereumForToken(sender KeysHolder, receiver KeysHolder, params TestTokenParams) bool { - okSender := setup.checkHolderEthBalanceForToken(sender, true, params) - okReceiver := setup.checkHolderMvxBalanceForToken(receiver, false, params) - okContract := setup.checkContractMvxBalanceForToken(params) +func (setup *TestSetup) isTransferDoneFromEthereumForToken(sender, receiver KeysHolder, params TestTokenParams) bool { + if !setup.checkHolderEthBalanceForToken(sender, true, params) { + return false + } + if !setup.checkHolderMvxBalanceForToken(receiver, false, params) { + return false + } + + if !setup.checkContractMvxBalanceForToken(params) { + return false + } + + if params.IsMintBurnOnEth { + if !setup.checkEthBurnedTokenBalance(params) { + return false + } + } else if !setup.checkEthLockedBalanceForToken(params, false) { + return false + } + + if params.IsMintBurnOnMvX { + if !setup.checkMvxMintedBalanceForToken(params) { + return false + } + } else if !setup.checkMvxLockedBalanceForToken(params, true) { + return false + } - return okSender && okReceiver && okContract + return true } func (setup *TestSetup) checkHolderMvxBalanceForToken(holder KeysHolder, isSender bool, params TestTokenParams) bool { @@ -308,6 +331,86 @@ func (setup *TestSetup) checkContractMvxBalanceForToken(params TestTokenParams) return mvxBalance.String() == expectedValueOnContract.String() } +func (setup *TestSetup) checkEthLockedBalanceForToken(params TestTokenParams, isSecondBridge bool) bool { + token := setup.GetTokenData(params.AbstractTokenIdentifier) + lockedTokens := setup.EthereumHandler.GetTotalBalancesForToken(setup.Ctx, token.EthErc20Address) + + expectedValue := setup.computeExpectedValueToMvx(params) + + if params.InitialSupplyValue != "" { + if initialSupply, ok := new(big.Int).SetString(params.InitialSupplyValue, 10); ok { + expectedValue.Add(expectedValue, initialSupply) + } + } + + if isSecondBridge { + expectedValue.Sub(expectedValue, setup.computeExpectedValueFromMvx(params)) + } + + return lockedTokens.String() == expectedValue.String() +} + +func (setup *TestSetup) checkEthBurnedTokenBalance(params TestTokenParams) bool { + token := setup.GetTokenData(params.AbstractTokenIdentifier) + burnedTokens := setup.EthereumHandler.GetBurnBalanceForToken(setup.Ctx, token.EthErc20Address) + + expectedValue := setup.computeExpectedValueToMvx(params) + + if params.IsNativeOnEth { + if params.InitialSupplyValue != "" { + if initialSupply, ok := new(big.Int).SetString(params.InitialSupplyValue, 10); ok { + expectedValue.Add(expectedValue, initialSupply) + } + } + } + + return burnedTokens.String() == expectedValue.String() +} + +func (setup *TestSetup) checkMvxMintedBalanceForToken(params TestTokenParams) bool { + token := setup.GetTokenData(params.AbstractTokenIdentifier) + mintedTokens := setup.MultiversxHandler.GetMintedAmountForToken(setup.Ctx, token.MvxChainSpecificToken) + + expectedValue := setup.computeExpectedValueToMvx(params) + + if params.IsNativeOnEth { + if params.InitialSupplyValue != "" { + if initialSupply, ok := new(big.Int).SetString(params.InitialSupplyValue, 10); ok { + expectedValue.Add(expectedValue, initialSupply) + } + } + } + + return mintedTokens.String() == expectedValue.String() +} + +func (setup *TestSetup) computeExpectedValueToMvx(params TestTokenParams) *big.Int { + expectedValue := big.NewInt(0) + for _, operation := range params.TestOperations { + if operation.ValueToTransferToMvx == nil { + continue + } + + expectedValue.Add(expectedValue, operation.ValueToTransferToMvx) + } + + return expectedValue +} + +func (setup *TestSetup) computeExpectedValueFromMvx(params TestTokenParams) *big.Int { + expectedValue := big.NewInt(0) + for _, operation := range params.TestOperations { + if operation.ValueToSendFromMvX == nil { + continue + } + + expectedValue.Add(expectedValue, operation.ValueToSendFromMvX) + expectedValue.Sub(expectedValue, feeInt) + } + + return expectedValue +} + // IsTransferDoneFromEthereumWithRefund returns true if all provided tokens are bridged from Ethereum towards MultiversX including refunds func (setup *TestSetup) IsTransferDoneFromEthereumWithRefund(tokens ...TestTokenParams) bool { isDone := true @@ -357,19 +460,96 @@ func (setup *TestSetup) IsTransferDoneFromMultiversX(sender KeysHolder, receiver return isDone } -func (setup *TestSetup) isTransferDoneFromMultiversXForToken(sender KeysHolder, receiver KeysHolder, params TestTokenParams) bool { +func (setup *TestSetup) isTransferDoneFromMultiversXForToken(sender, receiver KeysHolder, params TestTokenParams) bool { setup.mutBalances.Lock() - initialBalanceForSafe := setup.esdtBalanceForSafe[params.AbstractTokenIdentifier] + initialBalance := setup.esdtBalanceForSafe[params.AbstractTokenIdentifier] setup.mutBalances.Unlock() - okSender := setup.checkHolderMvxBalanceForToken(sender, true, params) - okReceiver := setup.checkHolderEthBalanceForToken(receiver, false, params) + if !setup.checkHolderMvxBalanceForToken(sender, true, params) { + return false + } + if !setup.checkHolderEthBalanceForToken(receiver, false, params) { + return false + } + + expectedBalance := new(big.Int).Add(initialBalance, params.ESDTSafeExtraBalance) + actualBalance := setup.MultiversxHandler.GetESDTChainSpecificTokenBalance( + setup.Ctx, setup.MultiversxHandler.SafeAddress, params.AbstractTokenIdentifier, + ) + if expectedBalance.Cmp(actualBalance) != 0 { + return false + } + + if params.IsMintBurnOnMvX { + if !setup.checkMvxBurnedTokenBalance(params) { + return false + } + } else if !setup.checkMvxLockedBalanceForToken(params, false) { + return false + } + + if params.IsMintBurnOnEth { + if !setup.checkEthMintedBalanceForToken(params) { + return false + } + } else if !setup.checkEthLockedBalanceForToken(params, true) { + return false + } + + return true +} + +func (setup *TestSetup) checkMvxLockedBalanceForToken(params TestTokenParams, isSecondBridge bool) bool { + token := setup.GetTokenData(params.AbstractTokenIdentifier) + lockedTokens := setup.MultiversxHandler.GetTotalBalancesForToken(setup.Ctx, token.MvxChainSpecificToken) + + expectedValue := setup.computeExpectedValueFromMvx(params) + + if params.InitialSupplyValue != "" { + if initialSupply, ok := new(big.Int).SetString(params.InitialSupplyValue, 10); ok { + expectedValue.Add(expectedValue, initialSupply) + } + } + + if isSecondBridge { + expectedValue.Sub(expectedValue, setup.computeExpectedValueToMvx(params)) + } + + return lockedTokens.String() == expectedValue.String() +} + +func (setup *TestSetup) checkMvxBurnedTokenBalance(params TestTokenParams) bool { + token := setup.GetTokenData(params.AbstractTokenIdentifier) + burnedTokens := setup.MultiversxHandler.GetBurnedAmountForToken(setup.Ctx, token.MvxChainSpecificToken) - expectedEsdtSafe := big.NewInt(0).Add(initialBalanceForSafe, params.ESDTSafeExtraBalance) - balanceForSafe := setup.MultiversxHandler.GetESDTChainSpecificTokenBalance(setup.Ctx, setup.MultiversxHandler.SafeAddress, params.AbstractTokenIdentifier) - isSafeContractOnCorrectBalance := expectedEsdtSafe.String() == balanceForSafe.String() + expectedValue := setup.computeExpectedValueFromMvx(params) + + if params.IsNativeOnMvX { + if params.InitialSupplyValue != "" { + if initialSupply, ok := new(big.Int).SetString(params.InitialSupplyValue, 10); ok { + expectedValue.Add(expectedValue, initialSupply) + } + } + } + + return burnedTokens.String() == expectedValue.String() +} + +func (setup *TestSetup) checkEthMintedBalanceForToken(params TestTokenParams) bool { + token := setup.GetTokenData(params.AbstractTokenIdentifier) + mintedTokens := setup.EthereumHandler.GetMintBalanceForToken(setup.Ctx, token.EthErc20Address) + + expectedValue := setup.computeExpectedValueFromMvx(params) + + if params.IsNativeOnMvX { + if params.InitialSupplyValue != "" { + if initialSupply, ok := new(big.Int).SetString(params.InitialSupplyValue, 10); ok { + expectedValue.Add(expectedValue, initialSupply) + } + } + } - return okSender && okReceiver && isSafeContractOnCorrectBalance + return mintedTokens.String() == expectedValue.String() } // CreateBatchOnMultiversX will create deposits that will be gathered in a batch on MultiversX diff --git a/integrationTests/relayers/slowTests/startsFromEthereumFlow.go b/integrationTests/relayers/slowTests/startsFromEthereumFlow.go index 87a1f704..56f3080b 100644 --- a/integrationTests/relayers/slowTests/startsFromEthereumFlow.go +++ b/integrationTests/relayers/slowTests/startsFromEthereumFlow.go @@ -26,7 +26,6 @@ func (flow *startsFromEthereumFlow) process() (finished bool) { } isTransferDoneFromEthereum := flow.setup.IsTransferDoneFromEthereum(flow.setup.AliceKeys, flow.setup.BobKeys, flow.tokens...) - fmt.Println(isTransferDoneFromEthereum) if !flow.ethToMvxDone && isTransferDoneFromEthereum { flow.ethToMvxDone = true log.Info(fmt.Sprintf(framework.LogStepMarker, "Ethereum->MultiversX transfer finished, now sending back to Ethereum...")) From 826424a8e16678664af988a25497115ed70a2d04 Mon Sep 17 00:00:00 2001 From: cosmatudor Date: Wed, 13 Nov 2024 16:09:51 +0200 Subject: [PATCH 2/7] fixes after review --- .../slowTests/framework/ethereumHandler.go | 20 +-- .../slowTests/framework/multiversxHandler.go | 57 ++++----- .../relayers/slowTests/framework/testSetup.go | 119 ++++++++++-------- 3 files changed, 105 insertions(+), 91 deletions(-) diff --git a/integrationTests/relayers/slowTests/framework/ethereumHandler.go b/integrationTests/relayers/slowTests/framework/ethereumHandler.go index 7c06922a..8dde3c83 100644 --- a/integrationTests/relayers/slowTests/framework/ethereumHandler.go +++ b/integrationTests/relayers/slowTests/framework/ethereumHandler.go @@ -281,18 +281,19 @@ func (handler *EthereumHandler) IssueAndWhitelistToken(ctx context.Context, para require.True(handler, ok) if params.IsMintBurnOnEth { - var tx2 *types.Transaction - var err2 error + mintAmount := big.NewInt(0) + burnAmount := big.NewInt(0) + if params.IsNativeOnEth { - burnAmount := initialSupply - tx2, err2 = handler.SafeContract.InitSupplyMintBurn(auth, erc20Address, zeroValueBigInt, burnAmount) + burnAmount = initialSupply } else { - mintAmount := initialSupply - tx2, err2 = handler.SafeContract.InitSupplyMintBurn(auth, erc20Address, mintAmount, zeroValueBigInt) + mintAmount = initialSupply } - require.NoError(handler, err2) + + tx, err = handler.SafeContract.InitSupplyMintBurn(auth, erc20Address, mintAmount, burnAmount) + require.NoError(handler, err) handler.SimulatedChain.Commit() - handler.checkEthTxResult(ctx, tx2.Hash()) + handler.checkEthTxResult(ctx, tx.Hash()) } else { // reset the tokens value for the safe contract, so it will "know" about the balance that it has in the ERC20 contract tx, err = handler.SafeContract.ResetTotalBalance(auth, erc20Address) @@ -500,6 +501,7 @@ func (handler *EthereumHandler) Mint(ctx context.Context, params TestTokenParams handler.checkEthTxResult(ctx, tx.Hash()) } +// GetTotalBalancesForToken will return the total locked balance for the provided token func (handler *EthereumHandler) GetTotalBalancesForToken(ctx context.Context, address common.Address) *big.Int { opts := &bind.CallOpts{Context: ctx} balance, err := handler.SafeContract.TotalBalances(opts, address) @@ -507,6 +509,7 @@ func (handler *EthereumHandler) GetTotalBalancesForToken(ctx context.Context, ad return balance } +// GetBurnBalanceForToken will return burn balance for the provided token func (handler *EthereumHandler) GetBurnBalanceForToken(ctx context.Context, address common.Address) *big.Int { opts := &bind.CallOpts{Context: ctx} balance, err := handler.SafeContract.BurnBalances(opts, address) @@ -514,6 +517,7 @@ func (handler *EthereumHandler) GetBurnBalanceForToken(ctx context.Context, addr return balance } +// GetMintBalanceForToken will return mint balance for the provided token func (handler *EthereumHandler) GetMintBalanceForToken(ctx context.Context, address common.Address) *big.Int { opts := &bind.CallOpts{Context: ctx} balance, err := handler.SafeContract.MintBalances(opts, address) diff --git a/integrationTests/relayers/slowTests/framework/multiversxHandler.go b/integrationTests/relayers/slowTests/framework/multiversxHandler.go index b59052d4..cf48a830 100644 --- a/integrationTests/relayers/slowTests/framework/multiversxHandler.go +++ b/integrationTests/relayers/slowTests/framework/multiversxHandler.go @@ -803,41 +803,31 @@ func (handler *MultiversxHandler) setInitialSupply(ctx context.Context, params I require.True(handler, okConvert) if params.IsMintBurnOnMvX { + mintAmount := big.NewInt(0) + burnAmount := big.NewInt(0) + if params.IsNativeOnMvX { - burnAmount := initialSupply - hash, txResult := handler.ChainSimulator.ScCall( - ctx, - handler.OwnerKeys.MvxSk, - handler.MultisigAddress, - zeroStringValue, - setCallsGasLimit, - initSupplyMintBurnEsdtSafe, - []string{ - hex.EncodeToString([]byte(tkData.MvxChainSpecificToken)), - hex.EncodeToString(zeroValueBigInt.Bytes()), - hex.EncodeToString(burnAmount.Bytes()), - }, - ) - log.Info("initial supply tx executed", "hash", hash, "status", txResult.Status, - "initial mint", "0", "initial burned", params.InitialSupplyValue) + burnAmount = initialSupply } else { - mintAmount := initialSupply - hash, txResult := handler.ChainSimulator.ScCall( - ctx, - handler.OwnerKeys.MvxSk, - handler.MultisigAddress, - zeroStringValue, - setCallsGasLimit, - initSupplyMintBurnEsdtSafe, - []string{ - hex.EncodeToString([]byte(tkData.MvxChainSpecificToken)), - hex.EncodeToString(mintAmount.Bytes()), - hex.EncodeToString(zeroValueBigInt.Bytes()), - }, - ) - log.Info("initial supply tx executed", "hash", hash, "status", txResult.Status, - "initial mint", params.InitialSupplyValue, "initial burned", "0") + mintAmount = initialSupply } + + hash, txResult := handler.ChainSimulator.ScCall( + ctx, + handler.OwnerKeys.MvxSk, + handler.MultisigAddress, + zeroStringValue, + setCallsGasLimit, + initSupplyMintBurnEsdtSafe, + []string{ + hex.EncodeToString([]byte(tkData.MvxChainSpecificToken)), + hex.EncodeToString(mintAmount.Bytes()), + hex.EncodeToString(burnAmount.Bytes()), + }, + ) + + log.Info("initial supply tx executed", "hash", hash, "status", txResult.Status, + "initial mint", mintAmount.String(), "initial burned", burnAmount.String()) } else { hash, txResult := handler.ChainSimulator.ScCall( ctx, @@ -1066,6 +1056,7 @@ func (handler *MultiversxHandler) TransferToken(ctx context.Context, source Keys "hash", hash, "status", txResult.Status) } +// GetTotalBalancesForToken will return the total locked balance for the provided token func (handler *MultiversxHandler) GetTotalBalancesForToken(ctx context.Context, token string) *big.Int { queryParams := []string{ hex.EncodeToString([]byte(token)), @@ -1075,6 +1066,7 @@ func (handler *MultiversxHandler) GetTotalBalancesForToken(ctx context.Context, return value } +// GetMintedAmountForToken will return mint balance for token func (handler *MultiversxHandler) GetMintedAmountForToken(ctx context.Context, token string) *big.Int { queryParams := []string{ hex.EncodeToString([]byte(token)), @@ -1084,6 +1076,7 @@ func (handler *MultiversxHandler) GetMintedAmountForToken(ctx context.Context, t return value } +// GetBurnedAmountForToken will return burn balance of token func (handler *MultiversxHandler) GetBurnedAmountForToken(ctx context.Context, token string) *big.Int { queryParams := []string{ hex.EncodeToString([]byte(token)), diff --git a/integrationTests/relayers/slowTests/framework/testSetup.go b/integrationTests/relayers/slowTests/framework/testSetup.go index 5bc2a23e..a229f982 100644 --- a/integrationTests/relayers/slowTests/framework/testSetup.go +++ b/integrationTests/relayers/slowTests/framework/testSetup.go @@ -19,15 +19,19 @@ import ( // framework constants const ( - LogStepMarker = "#################################### %s ####################################" - proxyCacherExpirationSeconds = 600 - proxyMaxNoncesDelta = 7 - NumRelayers = 3 - NumOracles = 3 - quorum = "03" - mvxHrp = "erd" + LogStepMarker = "#################################### %s ####################################" + proxyCacherExpirationSeconds = 600 + proxyMaxNoncesDelta = 7 + NumRelayers = 3 + NumOracles = 3 + quorum = "03" + mvxHrp = "erd" + firstBridge currentBridge = "first bridge" + secondBridge currentBridge = "second bridge" ) +type currentBridge string + // TestSetup is the struct that holds all subcomponents for the testing infrastructure type TestSetup struct { testing.TB @@ -243,45 +247,33 @@ func (setup *TestSetup) isTransferDoneFromEthereumForToken(sender, receiver Keys return false } - if params.IsMintBurnOnEth { - if !setup.checkEthBurnedTokenBalance(params) { - return false - } - } else if !setup.checkEthLockedBalanceForToken(params, false) { - return false - } - - if params.IsMintBurnOnMvX { - if !setup.checkMvxMintedBalanceForToken(params) { - return false - } - } else if !setup.checkMvxLockedBalanceForToken(params, true) { + if !setup.checkTokenOnEthFirstBridge(params) { return false } - return true + return setup.checkTokenOnMvxSecondBridge(params) } -func (setup *TestSetup) checkHolderMvxBalanceForToken(holder KeysHolder, isSender bool, params TestTokenParams) bool { - balanceMapping, exists := setup.getBalanceMappingForAddress(holder.MvxAddress.String()) +func (setup *TestSetup) checkHolderEthBalanceForToken(holder KeysHolder, isSender bool, params TestTokenParams) bool { + balanceMapping, exists := setup.getBalanceMappingForAddress(holder.EthAddress.String()) if !exists { return false } - actualBalance := setup.MultiversxHandler.GetESDTUniversalTokenBalance(setup.Ctx, holder.MvxAddress, params.AbstractTokenIdentifier) + actualBalance := setup.EthereumHandler.GetBalance(holder.EthAddress, params.AbstractTokenIdentifier) - return setup.checkHolderBalanceForTokenHelper(balanceMapping, params, actualBalance, holder.MvxAddress.String(), isSender) + return setup.checkHolderBalanceForTokenHelper(balanceMapping, params, actualBalance, holder.EthAddress.String(), isSender) } -func (setup *TestSetup) checkHolderEthBalanceForToken(holder KeysHolder, isSender bool, params TestTokenParams) bool { - balanceMapping, exists := setup.getBalanceMappingForAddress(holder.EthAddress.String()) +func (setup *TestSetup) checkHolderMvxBalanceForToken(holder KeysHolder, isSender bool, params TestTokenParams) bool { + balanceMapping, exists := setup.getBalanceMappingForAddress(holder.MvxAddress.String()) if !exists { return false } - actualBalance := setup.EthereumHandler.GetBalance(holder.EthAddress, params.AbstractTokenIdentifier) + actualBalance := setup.MultiversxHandler.GetESDTUniversalTokenBalance(setup.Ctx, holder.MvxAddress, params.AbstractTokenIdentifier) - return setup.checkHolderBalanceForTokenHelper(balanceMapping, params, actualBalance, holder.EthAddress.String(), isSender) + return setup.checkHolderBalanceForTokenHelper(balanceMapping, params, actualBalance, holder.MvxAddress.String(), isSender) } func (setup *TestSetup) getBalanceMappingForAddress(addr string) (map[string]*big.Int, bool) { @@ -331,7 +323,23 @@ func (setup *TestSetup) checkContractMvxBalanceForToken(params TestTokenParams) return mvxBalance.String() == expectedValueOnContract.String() } -func (setup *TestSetup) checkEthLockedBalanceForToken(params TestTokenParams, isSecondBridge bool) bool { +func (setup *TestSetup) checkTokenOnEthFirstBridge(params TestTokenParams) bool { + if params.IsMintBurnOnEth { + return setup.checkEthBurnedTokenBalance(params) + } + + return setup.checkEthLockedBalanceForToken(params, firstBridge) +} + +func (setup *TestSetup) checkTokenOnMvxSecondBridge(params TestTokenParams) bool { + if params.IsMintBurnOnMvX { + return setup.checkMvxMintedBalanceForToken(params) + } + + return setup.checkMvxLockedBalanceForToken(params, secondBridge) +} + +func (setup *TestSetup) checkEthLockedBalanceForToken(params TestTokenParams, bridgeNumber currentBridge) bool { token := setup.GetTokenData(params.AbstractTokenIdentifier) lockedTokens := setup.EthereumHandler.GetTotalBalancesForToken(setup.Ctx, token.EthErc20Address) @@ -343,7 +351,7 @@ func (setup *TestSetup) checkEthLockedBalanceForToken(params TestTokenParams, is } } - if isSecondBridge { + if bridgeNumber == secondBridge { expectedValue.Sub(expectedValue, setup.computeExpectedValueFromMvx(params)) } @@ -461,10 +469,6 @@ func (setup *TestSetup) IsTransferDoneFromMultiversX(sender KeysHolder, receiver } func (setup *TestSetup) isTransferDoneFromMultiversXForToken(sender, receiver KeysHolder, params TestTokenParams) bool { - setup.mutBalances.Lock() - initialBalance := setup.esdtBalanceForSafe[params.AbstractTokenIdentifier] - setup.mutBalances.Unlock() - if !setup.checkHolderMvxBalanceForToken(sender, true, params) { return false } @@ -472,34 +476,47 @@ func (setup *TestSetup) isTransferDoneFromMultiversXForToken(sender, receiver Ke return false } + if !setup.checkMvxBalanceForSafe(params) { + return false + } + + if !setup.checkTokenOnMvxFirstBridge(params) { + return false + } + + return setup.checkTokenOnEthSecondBridge(params) +} + +func (setup *TestSetup) checkMvxBalanceForSafe(params TestTokenParams) bool { + setup.mutBalances.Lock() + initialBalance := setup.esdtBalanceForSafe[params.AbstractTokenIdentifier] + setup.mutBalances.Unlock() + expectedBalance := new(big.Int).Add(initialBalance, params.ESDTSafeExtraBalance) actualBalance := setup.MultiversxHandler.GetESDTChainSpecificTokenBalance( setup.Ctx, setup.MultiversxHandler.SafeAddress, params.AbstractTokenIdentifier, ) - if expectedBalance.Cmp(actualBalance) != 0 { - return false - } + return expectedBalance.Cmp(actualBalance) == 0 +} + +func (setup *TestSetup) checkTokenOnMvxFirstBridge(params TestTokenParams) bool { if params.IsMintBurnOnMvX { - if !setup.checkMvxBurnedTokenBalance(params) { - return false - } - } else if !setup.checkMvxLockedBalanceForToken(params, false) { - return false + return setup.checkMvxBurnedTokenBalance(params) } + return setup.checkMvxLockedBalanceForToken(params, secondBridge) +} + +func (setup *TestSetup) checkTokenOnEthSecondBridge(params TestTokenParams) bool { if params.IsMintBurnOnEth { - if !setup.checkEthMintedBalanceForToken(params) { - return false - } - } else if !setup.checkEthLockedBalanceForToken(params, true) { - return false + return setup.checkEthMintedBalanceForToken(params) } - return true + return setup.checkEthLockedBalanceForToken(params, firstBridge) } -func (setup *TestSetup) checkMvxLockedBalanceForToken(params TestTokenParams, isSecondBridge bool) bool { +func (setup *TestSetup) checkMvxLockedBalanceForToken(params TestTokenParams, bridgeNumber currentBridge) bool { token := setup.GetTokenData(params.AbstractTokenIdentifier) lockedTokens := setup.MultiversxHandler.GetTotalBalancesForToken(setup.Ctx, token.MvxChainSpecificToken) @@ -511,7 +528,7 @@ func (setup *TestSetup) checkMvxLockedBalanceForToken(params TestTokenParams, is } } - if isSecondBridge { + if bridgeNumber == secondBridge { expectedValue.Sub(expectedValue, setup.computeExpectedValueToMvx(params)) } From 25e9ccd950fff7f96d4d8d77ee3d664b94f3dd76 Mon Sep 17 00:00:00 2001 From: cosmatudor Date: Thu, 14 Nov 2024 11:26:09 +0200 Subject: [PATCH 3/7] fix --- integrationTests/relayers/slowTests/framework/testSetup.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integrationTests/relayers/slowTests/framework/testSetup.go b/integrationTests/relayers/slowTests/framework/testSetup.go index a229f982..b25ff39c 100644 --- a/integrationTests/relayers/slowTests/framework/testSetup.go +++ b/integrationTests/relayers/slowTests/framework/testSetup.go @@ -505,7 +505,7 @@ func (setup *TestSetup) checkTokenOnMvxFirstBridge(params TestTokenParams) bool return setup.checkMvxBurnedTokenBalance(params) } - return setup.checkMvxLockedBalanceForToken(params, secondBridge) + return setup.checkMvxLockedBalanceForToken(params, firstBridge) } func (setup *TestSetup) checkTokenOnEthSecondBridge(params TestTokenParams) bool { @@ -513,7 +513,7 @@ func (setup *TestSetup) checkTokenOnEthSecondBridge(params TestTokenParams) bool return setup.checkEthMintedBalanceForToken(params) } - return setup.checkEthLockedBalanceForToken(params, firstBridge) + return setup.checkEthLockedBalanceForToken(params, secondBridge) } func (setup *TestSetup) checkMvxLockedBalanceForToken(params TestTokenParams, bridgeNumber currentBridge) bool { From 8331a7367226c6302619d9fae7a8b11b4e1abff2 Mon Sep 17 00:00:00 2001 From: cosmatudor Date: Thu, 14 Nov 2024 15:13:37 +0200 Subject: [PATCH 4/7] fix for refund tests --- .../relayers/slowTests/framework/testSetup.go | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/integrationTests/relayers/slowTests/framework/testSetup.go b/integrationTests/relayers/slowTests/framework/testSetup.go index b25ff39c..474b9cce 100644 --- a/integrationTests/relayers/slowTests/framework/testSetup.go +++ b/integrationTests/relayers/slowTests/framework/testSetup.go @@ -352,7 +352,8 @@ func (setup *TestSetup) checkEthLockedBalanceForToken(params TestTokenParams, br } if bridgeNumber == secondBridge { - expectedValue.Sub(expectedValue, setup.computeExpectedValueFromMvx(params)) + expectedValue.Sub(expectedValue, setup.computeExpectedValueFromMvx(params)) // unlock amount of tokens sent back from Eth to Mvx + expectedValue.Sub(expectedValue, setup.getMvxTotalRefundAmountForToken(params)) // unlock possible refund amount to be bridged back to Eth } return lockedTokens.String() == expectedValue.String() @@ -530,6 +531,7 @@ func (setup *TestSetup) checkMvxLockedBalanceForToken(params TestTokenParams, br if bridgeNumber == secondBridge { expectedValue.Sub(expectedValue, setup.computeExpectedValueToMvx(params)) + expectedValue.Add(expectedValue, setup.getMvxTotalRefundAmountForToken(params)) // lock possible refund amount from failed SC call on Mvx } return lockedTokens.String() == expectedValue.String() @@ -547,6 +549,8 @@ func (setup *TestSetup) checkMvxBurnedTokenBalance(params TestTokenParams) bool expectedValue.Add(expectedValue, initialSupply) } } + } else { + expectedValue.Add(expectedValue, setup.getMvxTotalRefundAmountForToken(params)) // burn possible refund amount to be bridged back to Eth } return burnedTokens.String() == expectedValue.String() @@ -564,11 +568,27 @@ func (setup *TestSetup) checkEthMintedBalanceForToken(params TestTokenParams) bo expectedValue.Add(expectedValue, initialSupply) } } + } else { + expectedValue.Add(expectedValue, setup.getMvxTotalRefundAmountForToken(params)) // mint possible refund amount from failed SC call on Mvx } return mintedTokens.String() == expectedValue.String() } +func (setup *TestSetup) getMvxTotalRefundAmountForToken(params TestTokenParams) *big.Int { + totalRefund := big.NewInt(0) + for _, operation := range params.TestOperations { + if len(operation.MvxSCCallData) > 0 || operation.MvxForceSCCall { + if operation.MvxFaultySCCall { + // the balance should be bridged back to the receiver on Ethereum - fee + totalRefund.Add(totalRefund, operation.ValueToTransferToMvx) + totalRefund.Sub(totalRefund, feeInt) + } + } + } + return totalRefund +} + // CreateBatchOnMultiversX will create deposits that will be gathered in a batch on MultiversX func (setup *TestSetup) CreateBatchOnMultiversX(tokensParams ...TestTokenParams) { for _, params := range tokensParams { From f781e65500710966609c5324d78e1f23d1a4d56c Mon Sep 17 00:00:00 2001 From: cosmatudor Date: Mon, 18 Nov 2024 14:38:10 +0200 Subject: [PATCH 5/7] ifs refactor --- .../relayers/slowTests/framework/testSetup.go | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/integrationTests/relayers/slowTests/framework/testSetup.go b/integrationTests/relayers/slowTests/framework/testSetup.go index 474b9cce..ed3ce09b 100644 --- a/integrationTests/relayers/slowTests/framework/testSetup.go +++ b/integrationTests/relayers/slowTests/framework/testSetup.go @@ -312,12 +312,17 @@ func (setup *TestSetup) checkContractMvxBalanceForToken(params TestTokenParams) if operation.ValueToTransferToMvx == nil { continue } - - if len(operation.MvxSCCallData) > 0 || operation.MvxForceSCCall { - if !operation.MvxFaultySCCall { - expectedValueOnContract.Add(expectedValueOnContract, operation.ValueToTransferToMvx) - } + if !operation.MvxForceSCCall { + continue } + if len(operation.MvxSCCallData) == 0 { + continue + } + if !operation.MvxFaultySCCall { + continue + } + + expectedValueOnContract.Add(expectedValueOnContract, operation.ValueToTransferToMvx) } return mvxBalance.String() == expectedValueOnContract.String() @@ -446,13 +451,19 @@ func (setup *TestSetup) isTransferDoneFromEthereumWithRefundForToken(params Test } expectedValueOnReceiver.Add(expectedValueOnReceiver, big.NewInt(0).Sub(valueToSendFromMvX, valueToTransferToMvx)) - if len(operation.MvxSCCallData) > 0 || operation.MvxForceSCCall { - if operation.MvxFaultySCCall { - // the balance should be bridged back to the receiver on Ethereum - fee - expectedValueOnReceiver.Add(expectedValueOnReceiver, valueToTransferToMvx) - expectedValueOnReceiver.Sub(expectedValueOnReceiver, feeInt) - } + if !operation.MvxForceSCCall { + continue + } + if len(operation.MvxSCCallData) == 0 { + continue + } + if !operation.MvxFaultySCCall { + continue } + + // the balance should be bridged back to the receiver on Ethereum - fee + expectedValueOnReceiver.Add(expectedValueOnReceiver, valueToTransferToMvx) + expectedValueOnReceiver.Sub(expectedValueOnReceiver, feeInt) } receiverBalance := setup.EthereumHandler.GetBalance(setup.BobKeys.EthAddress, params.AbstractTokenIdentifier) @@ -578,13 +589,19 @@ func (setup *TestSetup) checkEthMintedBalanceForToken(params TestTokenParams) bo func (setup *TestSetup) getMvxTotalRefundAmountForToken(params TestTokenParams) *big.Int { totalRefund := big.NewInt(0) for _, operation := range params.TestOperations { - if len(operation.MvxSCCallData) > 0 || operation.MvxForceSCCall { - if operation.MvxFaultySCCall { - // the balance should be bridged back to the receiver on Ethereum - fee - totalRefund.Add(totalRefund, operation.ValueToTransferToMvx) - totalRefund.Sub(totalRefund, feeInt) - } + if !operation.MvxForceSCCall { + continue } + if len(operation.MvxSCCallData) == 0 { + continue + } + if !operation.MvxFaultySCCall { + continue + } + + // the balance should be bridged back to the receiver on Ethereum - fee + totalRefund.Add(totalRefund, operation.ValueToTransferToMvx) + totalRefund.Sub(totalRefund, feeInt) } return totalRefund } From e05f33c06e0e0a8a1488b83aeeaf4d0f5164f7f0 Mon Sep 17 00:00:00 2001 From: cosmatudor Date: Mon, 18 Nov 2024 16:42:44 +0200 Subject: [PATCH 6/7] fixes --- .../relayers/slowTests/framework/testSetup.go | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/integrationTests/relayers/slowTests/framework/testSetup.go b/integrationTests/relayers/slowTests/framework/testSetup.go index ed3ce09b..263bc2cc 100644 --- a/integrationTests/relayers/slowTests/framework/testSetup.go +++ b/integrationTests/relayers/slowTests/framework/testSetup.go @@ -312,13 +312,10 @@ func (setup *TestSetup) checkContractMvxBalanceForToken(params TestTokenParams) if operation.ValueToTransferToMvx == nil { continue } - if !operation.MvxForceSCCall { + if len(operation.MvxSCCallData) == 0 && !operation.MvxForceSCCall { continue } - if len(operation.MvxSCCallData) == 0 { - continue - } - if !operation.MvxFaultySCCall { + if operation.MvxFaultySCCall { continue } @@ -451,10 +448,7 @@ func (setup *TestSetup) isTransferDoneFromEthereumWithRefundForToken(params Test } expectedValueOnReceiver.Add(expectedValueOnReceiver, big.NewInt(0).Sub(valueToSendFromMvX, valueToTransferToMvx)) - if !operation.MvxForceSCCall { - continue - } - if len(operation.MvxSCCallData) == 0 { + if len(operation.MvxSCCallData) == 0 && !operation.MvxForceSCCall { continue } if !operation.MvxFaultySCCall { @@ -589,10 +583,7 @@ func (setup *TestSetup) checkEthMintedBalanceForToken(params TestTokenParams) bo func (setup *TestSetup) getMvxTotalRefundAmountForToken(params TestTokenParams) *big.Int { totalRefund := big.NewInt(0) for _, operation := range params.TestOperations { - if !operation.MvxForceSCCall { - continue - } - if len(operation.MvxSCCallData) == 0 { + if len(operation.MvxSCCallData) == 0 && !operation.MvxForceSCCall { continue } if !operation.MvxFaultySCCall { From 5b0cf8be01da93386c38bde1a65c10be11f690fe Mon Sep 17 00:00:00 2001 From: cosmatudor Date: Mon, 18 Nov 2024 17:47:18 +0200 Subject: [PATCH 7/7] add check for nil value queries --- .../relayers/slowTests/framework/multiversxHandler.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/integrationTests/relayers/slowTests/framework/multiversxHandler.go b/integrationTests/relayers/slowTests/framework/multiversxHandler.go index cf48a830..580bec33 100644 --- a/integrationTests/relayers/slowTests/framework/multiversxHandler.go +++ b/integrationTests/relayers/slowTests/framework/multiversxHandler.go @@ -999,6 +999,7 @@ func (handler *MultiversxHandler) withdrawFees(ctx context.Context, hex.EncodeToString([]byte(token)), } responseData := handler.ChainSimulator.ExecuteVMQuery(ctx, handler.SafeAddress, getFunction, queryParams) + require.Greater(handler, len(responseData), 0) value := big.NewInt(0).SetBytes(responseData[0]) require.Equal(handler, expectedDelta.String(), value.String()) if expectedDelta.Cmp(zeroValueBigInt) == 0 { @@ -1062,6 +1063,7 @@ func (handler *MultiversxHandler) GetTotalBalancesForToken(ctx context.Context, hex.EncodeToString([]byte(token)), } responseData := handler.ChainSimulator.ExecuteVMQuery(ctx, handler.SafeAddress, getTotalBalances, queryParams) + require.Greater(handler, len(responseData), 0) value := big.NewInt(0).SetBytes(responseData[0]) return value } @@ -1072,6 +1074,7 @@ func (handler *MultiversxHandler) GetMintedAmountForToken(ctx context.Context, t hex.EncodeToString([]byte(token)), } responseData := handler.ChainSimulator.ExecuteVMQuery(ctx, handler.SafeAddress, getMintBalances, queryParams) + require.Greater(handler, len(responseData), 0) value := big.NewInt(0).SetBytes(responseData[0]) return value } @@ -1082,6 +1085,7 @@ func (handler *MultiversxHandler) GetBurnedAmountForToken(ctx context.Context, t hex.EncodeToString([]byte(token)), } responseData := handler.ChainSimulator.ExecuteVMQuery(ctx, handler.SafeAddress, getBurnBalances, queryParams) + require.Greater(handler, len(responseData), 0) value := big.NewInt(0).SetBytes(responseData[0]) return value }