From b0f44ff6d2078857ac50c8ae84a80f2642ab422a Mon Sep 17 00:00:00 2001 From: skosito Date: Sun, 10 Nov 2024 21:14:36 +0100 Subject: [PATCH] e2e test that rent payer creates receiver ata --- cmd/zetae2e/local/local.go | 1 + contrib/localnet/solana/start-solana.sh | 3 +- e2e/e2etests/e2etests.go | 27 ++++--- ...st_spl_withdraw_and_create_receiver_ata.go | 72 +++++++++++++++++++ 4 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 e2e/e2etests/test_spl_withdraw_and_create_receiver_ata.go diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index 0bc9ec916d..b42a52fef2 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -439,6 +439,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { e2etests.TestSPLDepositName, e2etests.TestSPLDepositAndCallName, e2etests.TestSPLWithdrawName, + e2etests.TestSPLWithdrawAndCreateReceiverAtaName, e2etests.TestSolanaWhitelistSPLName, } eg.Go(solanaTestRoutine(conf, deployerRunner, verbose, solanaTests...)) diff --git a/contrib/localnet/solana/start-solana.sh b/contrib/localnet/solana/start-solana.sh index d87e9672ae..4c74bbce29 100644 --- a/contrib/localnet/solana/start-solana.sh +++ b/contrib/localnet/solana/start-solana.sh @@ -8,9 +8,10 @@ echo "starting solana test validator..." solana-test-validator & sleep 5 -# airdrop to e2e sol account +# airdrop to e2e sol account and rent payer solana airdrop 100 solana airdrop 100 37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ +solana airdrop 100 C6KPvGDYfNusoE4yfRP21F8wK35bxCBMT69xk4xo3X79 solana program deploy gateway.so diff --git a/e2e/e2etests/e2etests.go b/e2e/e2etests/e2etests.go index fc02bb7c5a..0c91eb73f3 100644 --- a/e2e/e2etests/e2etests.go +++ b/e2e/e2etests/e2etests.go @@ -55,15 +55,16 @@ const ( /* * Solana tests */ - TestSolanaDepositName = "solana_deposit" - TestSolanaWithdrawName = "solana_withdraw" - TestSolanaDepositAndCallName = "solana_deposit_and_call" - TestSolanaDepositAndCallRefundName = "solana_deposit_and_call_refund" - TestSolanaDepositRestrictedName = "solana_deposit_restricted" - TestSolanaWithdrawRestrictedName = "solana_withdraw_restricted" - TestSPLDepositName = "spl_deposit" - TestSPLDepositAndCallName = "spl_deposit_and_call" - TestSPLWithdrawName = "spl_withdraw" + TestSolanaDepositName = "solana_deposit" + TestSolanaWithdrawName = "solana_withdraw" + TestSolanaDepositAndCallName = "solana_deposit_and_call" + TestSolanaDepositAndCallRefundName = "solana_deposit_and_call_refund" + TestSolanaDepositRestrictedName = "solana_deposit_restricted" + TestSolanaWithdrawRestrictedName = "solana_withdraw_restricted" + TestSPLDepositName = "spl_deposit" + TestSPLDepositAndCallName = "spl_deposit_and_call" + TestSPLWithdrawName = "spl_withdraw" + TestSPLWithdrawAndCreateReceiverAtaName = "spl_withdraw_and_create_receiver_ata" /** * TON tests @@ -442,6 +443,14 @@ var AllE2ETests = []runner.E2ETest{ }, TestSPLWithdraw, ), + runner.NewE2ETest( + TestSPLWithdrawAndCreateReceiverAtaName, + "withdraw SPL from ZEVM and create receiver ata", + []runner.ArgDefinition{ + {Description: "amount in spl tokens", DefaultValue: "1000000"}, + }, + TestSPLWithdrawAndCreateReceiverAta, + ), runner.NewE2ETest( TestSolanaDepositAndCallRefundName, "deposit SOL into ZEVM and call a contract that reverts; should refund", diff --git a/e2e/e2etests/test_spl_withdraw_and_create_receiver_ata.go b/e2e/e2etests/test_spl_withdraw_and_create_receiver_ata.go new file mode 100644 index 0000000000..bcfdd44490 --- /dev/null +++ b/e2e/e2etests/test_spl_withdraw_and_create_receiver_ata.go @@ -0,0 +1,72 @@ +package e2etests + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/node/e2e/runner" +) + +// TestSPLWithdrawAndCreateReceiverAta withdraws spl, but letting gateway to create receiver ata using rent payer +// instead of providing receiver that has it already created +func TestSPLWithdrawAndCreateReceiverAta(r *runner.E2ERunner, args []string) { + require.Len(r, args, 1) + + withdrawAmount := parseBigInt(r, args[0]) + + // get SPL ZRC20 balance before withdraw + zrc20BalanceBefore, err := r.SPLZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) + require.NoError(r, err) + r.Logger.Info("runner balance of SPL before withdraw: %d", zrc20BalanceBefore) + + require.Equal(r, 1, zrc20BalanceBefore.Cmp(withdrawAmount), "Insufficient balance for withdrawal") + + // parse withdraw amount (in lamports), approve amount is 1 SOL + approvedAmount := new(big.Int).SetUint64(solana.LAMPORTS_PER_SOL) + require.Equal( + r, + -1, + withdrawAmount.Cmp(approvedAmount), + "Withdrawal amount must be less than the approved amount (1e9)", + ) + + // create new priv key, with empty ata + receiverPrivKey, err := solana.NewRandomPrivateKey() + require.NoError(r, err) + + // verify receiver ata account doesn't exist + receiverAta, _, err := solana.FindAssociatedTokenAddress(receiverPrivKey.PublicKey(), r.SPLAddr) + require.NoError(r, err) + + receiverAtaAcc, err := r.SolanaClient.GetAccountInfo(r.Ctx, receiverAta) + require.Error(r, err) + require.Nil(r, receiverAtaAcc) + + // withdraw + r.WithdrawSPLZRC20(receiverPrivKey.PublicKey(), withdrawAmount, approvedAmount) + + // get SPL ZRC20 balance after withdraw + zrc20BalanceAfter, err := r.SPLZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress()) + require.NoError(r, err) + r.Logger.Info("runner balance of SPL after withdraw: %d", zrc20BalanceAfter) + + // verify receiver ata was created + receiverAtaAcc, err = r.SolanaClient.GetAccountInfo(r.Ctx, receiverAta) + require.NoError(r, err) + require.NotNil(r, receiverAtaAcc) + + // verify balances are updated + receiverBalanceAfter, err := r.SolanaClient.GetTokenAccountBalance(r.Ctx, receiverAta, rpc.CommitmentConfirmed) + require.NoError(r, err) + r.Logger.Info("receiver balance of SPL after withdraw: %s", receiverBalanceAfter.Value.Amount) + + // verify amount is added to receiver ata + require.Zero(r, withdrawAmount.Cmp(parseBigInt(r, receiverBalanceAfter.Value.Amount))) + + // verify amount is subtracted on zrc20 + require.Zero(r, new(big.Int).Sub(zrc20BalanceBefore, withdrawAmount).Cmp(zrc20BalanceAfter)) +}