diff --git a/e2e-polybft/e2e/bridge_test.go b/e2e-polybft/e2e/bridge_test.go index 2bac118325..201b376c40 100644 --- a/e2e-polybft/e2e/bridge_test.go +++ b/e2e-polybft/e2e/bridge_test.go @@ -146,7 +146,7 @@ func TestE2E_Bridge_RootchainTokensTransfers(t *testing.T) { // assert that all deposits are executed successfully // because of the token mapping with the first deposit - checkStateSyncResultLogs(t, logs, transfersCount+1) + assertStateSyncResultSuccess(t, logs, transfersCount+1) // get child token address childERC20Token := getChildToken(t, contractsapi.RootERC20Predicate.Abi, @@ -282,7 +282,7 @@ func TestE2E_Bridge_RootchainTokensTransfers(t *testing.T) { require.NoError(t, err) // assert that all state syncs are executed successfully - checkStateSyncResultLogs(t, logs, transfersCount) + assertStateSyncResultSuccess(t, logs, transfersCount) }) } @@ -384,7 +384,7 @@ func TestE2E_Bridge_ERC721Transfer(t *testing.T) { // assert that all deposits are executed successfully. // All deposits are sent using a single transaction, so arbitrary message bridge emits two state sync events: // MAP_TOKEN_SIG and DEPOSIT_BATCH_SIG state sync events - checkStateSyncResultLogs(t, logs, stateSyncedLogsCount) + assertStateSyncResultSuccess(t, logs, stateSyncedLogsCount) break } @@ -558,7 +558,7 @@ func TestE2E_Bridge_ERC1155Transfer(t *testing.T) { // assert that all deposits are executed successfully. // All deposits are sent using a single transaction, so arbitrary message bridge emits two state sync events: // MAP_TOKEN_SIG and DEPOSIT_BATCH_SIG state sync events - checkStateSyncResultLogs(t, logs, stateSyncedLogsCount) + assertStateSyncResultSuccess(t, logs, stateSyncedLogsCount) break } @@ -1146,7 +1146,7 @@ func TestE2E_Bridge_Transfers_AccessLists(t *testing.T) { // assert that all deposits are executed successfully // (token mapping and transferCount of deposits) - checkStateSyncResultLogs(t, logs, transfersCount+1) + assertStateSyncResultSuccess(t, logs, transfersCount+1) // get child token address childERC20Token := getChildToken(t, contractsapi.RootERC20Predicate.Abi, @@ -1256,6 +1256,7 @@ func TestE2E_Bridge_NonMintableERC20Token_WithPremine(t *testing.T) { numBlockConfirmations = uint64(2) exitEventsCount = uint64(2) tokensToTransfer = ethgo.Gwei(10) + tenMilionTokens = ethgo.Ether(10000000) bigZero = big.NewInt(0) ) @@ -1290,7 +1291,7 @@ func TestE2E_Bridge_NonMintableERC20Token_WithPremine(t *testing.T) { tcc.Premine = append(tcc.Premine, fmt.Sprintf("%s:%s:%s", nonValidatorKey.Address(), - command.DefaultPremineBalance.String(), + new(big.Int).Mul(big.NewInt(10), tenMilionTokens).String(), nonValidatorKeyString)) // do premine to reward wallet address @@ -1301,14 +1302,13 @@ func TestE2E_Bridge_NonMintableERC20Token_WithPremine(t *testing.T) { rewardWalletKeyString)) }), ) + defer cluster.Stop() rootchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) childEthEndpoint := cluster.Servers[0].JSONRPC() - defer cluster.Stop() - cluster.WaitForReady(t) polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) @@ -1354,7 +1354,7 @@ func TestE2E_Bridge_NonMintableERC20Token_WithPremine(t *testing.T) { }) // this test case will check first if they can withdraw some of the premined amount of non-mintable token - t.Run("Do a withdraw for premined validator address and premined non-validator address", func(t *testing.T) { + t.Run("do a withdraw for premined validator address and premined non-validator address", func(t *testing.T) { validatorSrv := cluster.Servers[1] validatorAcc, err := validatorHelper.GetAccountFromDir(validatorSrv.DataDir()) require.NoError(t, err) @@ -1422,7 +1422,7 @@ func TestE2E_Bridge_NonMintableERC20Token_WithPremine(t *testing.T) { checkBalancesFn(types.Address(nonValidatorKey.Address()), tokensToTransfer, nonValidatorBalanceAfterWithdraw, false) }) - t.Run("Do a deposit to some validator and non-validator address", func(t *testing.T) { + t.Run("do a deposit to some validator and non-validator address", func(t *testing.T) { validatorSrv := cluster.Servers[4] validatorAcc, err := validatorHelper.GetAccountFromDir(validatorSrv.DataDir()) require.NoError(t, err) @@ -1456,7 +1456,56 @@ func TestE2E_Bridge_NonMintableERC20Token_WithPremine(t *testing.T) { if len(logs) == stateSyncedLogsCount || i == numberOfAttempts-1 { // assert that all deposits are executed successfully - checkStateSyncResultLogs(t, logs, stateSyncedLogsCount) + assertStateSyncResultSuccess(t, logs, stateSyncedLogsCount) + + break + } + + require.NoError(t, cluster.WaitForBlock(finalBlockNum+(i+1)*epochSize, time.Minute)) + } + }) + + t.Run("transfer more native tokens than 0x0 balance is", func(t *testing.T) { + const expectedStateSyncsCount = 1 + + // since bridging native token is essentially minting + // (i.e. transferring tokens from 0x0 to receiver address using native transfer precompile), + // this test tries to deposit more tokens than 0x0 address has on its balance + currentBlock, err := childEthEndpoint.GetBlockByNumber(jsonrpc.LatestBlockNumber, false) + require.NoError(t, err) + + require.NoError(t, cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + bridgeHelper.TestAccountPrivKey, + strings.Join([]string{nonValidatorKey.Address().String()}, ","), + strings.Join([]string{tenMilionTokens.String()}, ","), + "", + cluster.Bridge.JSONRPCAddr(), + bridgeHelper.TestAccountPrivKey, + false), + ) + + // wait for couple of epoches + finalBlockNum := currentBlock.Header.Number + epochSize + require.NoError(t, cluster.WaitForBlock(finalBlockNum, 2*time.Minute)) + + // the transaction is processed and there should be a success event + var stateSyncedResult contractsapi.StateSyncResultEvent + + for i := uint64(0); i < numberOfAttempts; i++ { + logs, err := getFilteredLogs(stateSyncedResult.Sig(), currentBlock.Number()+1, finalBlockNum+i*epochSize, childEthEndpoint) + require.NoError(t, err) + + if len(logs) == expectedStateSyncsCount || i == numberOfAttempts-1 { + // assert that sent deposit has failed + checkStateSyncResultLogs(t, logs, expectedStateSyncsCount, + func(t *testing.T, ssre contractsapi.StateSyncResultEvent) { + t.Helper() + + require.False(t, ssre.Status) + }) break } diff --git a/e2e-polybft/e2e/helpers_test.go b/e2e-polybft/e2e/helpers_test.go index 59d82e64ab..70d862a2f4 100644 --- a/e2e-polybft/e2e/helpers_test.go +++ b/e2e-polybft/e2e/helpers_test.go @@ -24,6 +24,10 @@ import ( const nativeTokenNonMintableConfig = "Blade:BLD:18:false" +var ( + stateSyncResultEvent contractsapi.StateSyncResultEvent +) + func ABICall(relayer txrelayer.TxRelayer, artifact *contracts.Artifact, contractAddress types.Address, senderAddr types.Address, method string, params ...interface{}) (string, error) { input, err := artifact.Abi.GetMethod(method).Encode(params) if err != nil { @@ -59,11 +63,11 @@ func checkStateSyncResultLogs( t *testing.T, logs []*ethgo.Log, expectedCount int, + handler func(*testing.T, contractsapi.StateSyncResultEvent), ) { t.Helper() require.Equal(t, expectedCount, len(logs)) - var stateSyncResultEvent contractsapi.StateSyncResultEvent for _, log := range logs { doesMatch, err := stateSyncResultEvent.ParseLog(log) require.NoError(t, err) @@ -71,10 +75,29 @@ func checkStateSyncResultLogs( t.Logf("Block Number=%d, Decoded Log=%+v\n", log.BlockNumber, stateSyncResultEvent) - require.True(t, stateSyncResultEvent.Status) + if handler != nil { + handler(t, stateSyncResultEvent) + } } } +// assertStateSyncResultSuccess asserts that: +// 1. there are required amount of logs, +// 2. they are of contractsapi.StateSyncResult type +// 3. status is true, meaning that the state syncs were executed successfully +func assertStateSyncResultSuccess( + t *testing.T, + logs []*ethgo.Log, + expectedCount int) { + t.Helper() + checkStateSyncResultLogs(t, logs, expectedCount, + func(t *testing.T, ssre contractsapi.StateSyncResultEvent) { + t.Helper() + + require.True(t, ssre.Status) + }) +} + // getCheckpointBlockNumber gets current checkpoint block number from checkpoint manager smart contract func getCheckpointBlockNumber(l1Relayer txrelayer.TxRelayer, checkpointManagerAddr types.Address) (uint64, error) { checkpointBlockNumRaw, err := ABICall(l1Relayer, contractsapi.CheckpointManager,