Skip to content

Commit

Permalink
add inbound parse unit test and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
skosito committed Nov 7, 2024
1 parent 30e4571 commit 1b0afb0
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 55 deletions.
6 changes: 3 additions & 3 deletions e2e/e2etests/test_solana_deposit_and_call_spl.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ func TestSolanaDepositSPLAndCall(r *runner.E2ERunner, args []string) {
senderBalanceBefore, err := r.SolanaClient.GetTokenAccountBalance(r.Ctx, senderAta, rpc.CommitmentConfirmed)
require.NoError(r, err)

// get zrc20 balance for recepient
// get zrc20 balance for recipient
zrc20BalanceBefore, err := r.SPLZRC20.BalanceOf(&bind.CallOpts{}, contractAddr)
require.NoError(r, err)

// execute the deposit transaction
data := []byte("hello spl tokens")
// #nosec G115 e2eTest - always in range
sig := r.DepositSPL(&privKey, uint64(amount), r.SPLAddr, contractAddr, data)
sig := r.SPLDepositAndCall(&privKey, uint64(amount), r.SPLAddr, contractAddr, data)

// wait for the cctx to be mined
cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, sig.String(), r.CctxClient, r.Logger, r.CctxTimeout)
Expand All @@ -68,7 +68,7 @@ func TestSolanaDepositSPLAndCall(r *runner.E2ERunner, args []string) {
// verify amount is deposited to pda ata
require.Equal(r, parseInt(r, pdaBalanceBefore.Value.Amount)+amount, parseInt(r, pdaBalanceAfter.Value.Amount))

// verify amount is substracted from sender ata
// verify amount is subtracted from sender ata
require.Equal(r, parseInt(r, senderBalanceBefore.Value.Amount)-amount, parseInt(r, senderBalanceAfter.Value.Amount))

// verify amount is minted to receiver
Expand Down
6 changes: 3 additions & 3 deletions e2e/e2etests/test_solana_deposit_spl.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ func TestSolanaDepositSPL(r *runner.E2ERunner, args []string) {
senderBalanceBefore, err := r.SolanaClient.GetTokenAccountBalance(r.Ctx, senderAta, rpc.CommitmentConfirmed)
require.NoError(r, err)

// get zrc20 balance for recepient
// get zrc20 balance for recipient
zrc20BalanceBefore, err := r.SPLZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress())
require.NoError(r, err)

// deposit SPL tokens
// #nosec G115 e2eTest - always in range
sig := r.DepositSPL(&privKey, uint64(amount), r.SPLAddr, r.EVMAddress(), nil)
sig := r.SPLDepositAndCall(&privKey, uint64(amount), r.SPLAddr, r.EVMAddress(), nil)

// wait for the cctx to be mined
cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, sig.String(), r.CctxClient, r.Logger, r.CctxTimeout)
Expand All @@ -58,7 +58,7 @@ func TestSolanaDepositSPL(r *runner.E2ERunner, args []string) {
// verify amount is deposited to pda ata
require.Equal(r, parseInt(r, pdaBalanceBefore.Value.Amount)+amount, parseInt(r, pdaBalanceAfter.Value.Amount))

// verify amount is substracted from sender ata
// verify amount is subtracted from sender ata
require.Equal(r, parseInt(r, senderBalanceBefore.Value.Amount)-amount, parseInt(r, senderBalanceAfter.Value.Amount))

// verify amount is minted to receiver
Expand Down
24 changes: 2 additions & 22 deletions e2e/runner/solana.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,6 @@ func (r *E2ERunner) CreateWhitelistSPLMintInstruction(
return inst
}

/*
#[account(mut)]
pub signer: Signer<'info>,
#[account(seeds = [b"meta"], bump)]
pub pda: Account<'info, Pda>,
#[account(seeds=[b"whitelist", mint_account.key().as_ref()], bump)]
pub whitelist_entry: Account<'info, WhitelistEntry>, // attach whitelist entry to show the mint_account is whitelisted
pub mint_account: Account<'info, Mint>,
pub token_program: Program<'info, Token>,
#[account(mut)]
pub from: Account<'info, TokenAccount>, // this must be owned by signer; normally the ATA of signer
#[account(mut)]
pub to: Account<'info, TokenAccount>, // this must be ATA of PDA
*/

func (r *E2ERunner) CreateDepositSPLInstruction(
amount uint64,
signer solana.PublicKey,
Expand Down Expand Up @@ -213,7 +192,8 @@ func (r *E2ERunner) FindOrCreateAssociatedTokenAccount(
return pdaAta
}

func (r *E2ERunner) DepositSPL(
// SPLDepositAndCall deposits an amount of SPL tokens and calls a contract (if data is provided)
func (r *E2ERunner) SPLDepositAndCall(
privateKey *solana.PrivateKey,
amount uint64,
tokenAccount solana.PublicKey,
Expand Down
2 changes: 2 additions & 0 deletions pkg/contracts/solana/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const (
// [signer, pda, system_program]
AccountsNumDeposit = 3

// AccountsNumberOfDeposit is the number of accounts required for Solana gateway deposit spl instruction
// [signer, pda, whitelist_entry, mint_account, token_program, from, to]
AccountsNumberDepositSPL = 7
)

Expand Down
2 changes: 1 addition & 1 deletion pkg/contracts/solana/instruction.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type DepositInstructionParams struct {
Memo []byte
}

// DepositSPLInstructionParams contains the parameters for a gateway deposit instruction
// DepositSPLInstructionParams contains the parameters for a gateway deposit spl instruction
type DepositSPLInstructionParams struct {
// Discriminator is the unique identifier for the deposit instruction
Discriminator [8]byte
Expand Down
19 changes: 0 additions & 19 deletions x/fungible/keeper/foreign_coins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,25 +135,6 @@ func TestKeeperGetForeignCoinFromAsset(t *testing.T) {
fc, found = k.GetForeignCoinFromAsset(ctx, gasAsset, 3)
require.False(t, found)
})

// TODO: add validation per chain on setting foreign coin, not when getting
// t.Run("can get foreign coin with non-checksum address", func(t *testing.T) {
// k, ctx, _, _ := keepertest.FungibleKeeper(t)

// setForeignCoins(ctx, k,
// types.ForeignCoins{
// Zrc20ContractAddress: sample.EthAddress().String(),
// Asset: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
// ForeignChainId: 1,
// CoinType: coin.CoinType_ERC20,
// Name: "foo",
// },
// )

// fc, found := k.GetForeignCoinFromAsset(ctx, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 1)
// require.True(t, found)
// require.Equal(t, "foo", fc.Name)
// })
}

func TestKeeperGetAllForeignCoinMap(t *testing.T) {
Expand Down
14 changes: 7 additions & 7 deletions zetaclient/chains/solana/observer/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ func (ob *Observer) ParseInboundAsDeposit(
event := &clienttypes.InboundEvent{
SenderChainID: ob.Chain().ChainId,
Sender: sender,
Receiver: sender,
Receiver: sender, // receiver is pulled out from memo
TxOrigin: sender,
Amount: inst.Amount,
Memo: inst.Memo,
Expand Down Expand Up @@ -329,25 +329,25 @@ func (ob *Observer) ParseInboundAsDepositSPL(
return nil, nil
}

// check if the instruction is a deposit or not
// check if the instruction is a deposit spl or not
if inst.Discriminator != solanacontracts.DiscriminatorDepositSPL {
return nil, nil
}

// get the sender address (skip if unable to parse signer address)
sender, spl, err := ob.GetFromDepositSPLAccounts(tx, &instruction)
// get the sender and spl addresses
sender, spl, err := ob.GetSignerAndSPLFromDepositSPLAccounts(tx, &instruction)
if err != nil {
ob.Logger().
Inbound.Err(err).
Msgf("unable to get signer for sig %s instruction %d", tx.Signatures[0], instructionIndex)
Msgf("unable to get signer and spl for sig %s instruction %d", tx.Signatures[0], instructionIndex)
return nil, nil
}

// build inbound event
event := &clienttypes.InboundEvent{
SenderChainID: ob.Chain().ChainId,
Sender: sender,
Receiver: sender,
Receiver: sender, // receiver is pulled out from memo
TxOrigin: sender,
Amount: inst.Amount,
Memo: inst.Memo,
Expand Down Expand Up @@ -398,7 +398,7 @@ func (ob *Observer) GetSignerDeposit(tx *solana.Transaction, inst *solana.Compil
return tx.Message.AccountKeys[signerIndex].String(), nil
}

func (ob *Observer) GetFromDepositSPLAccounts(
func (ob *Observer) GetSignerAndSPLFromDepositSPLAccounts(
tx *solana.Transaction,
inst *solana.CompiledInstruction,
) (string, string, error) {
Expand Down
49 changes: 49 additions & 0 deletions zetaclient/chains/solana/observer/inbound_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package observer_test

import (
"context"
"encoding/hex"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -207,3 +208,51 @@ func Test_ParseInboundAsDeposit(t *testing.T) {
require.EqualValues(t, eventExpected, event)
})
}

func Test_ParseInboundAsDepositSPL(t *testing.T) {
// load archived inbound deposit spl tx from localnet result
txHash := "aY8yLDze6nHSRi7L5REozKAZY1aAyPJ6TfibiqQL5JGwgSBkYux5z5JfXs5ed8LZqpXUy4VijoU3x15mBd66ZGE"

chain := chains.SolanaDevnet

txResult := testutils.LoadSolanaInboundTxResult(t, TestDataDir, chain.ChainId, txHash, false)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

database, err := db.NewFromSqliteInMemory(true)
require.NoError(t, err)

// create observer
chainParams := sample.ChainParams(chain.ChainId)
chainParams.GatewayAddress = testutils.GatewayAddresses[chain.ChainId]
ob, err := observer.NewObserver(chain, nil, *chainParams, nil, nil, 60, database, base.DefaultLogger(), nil)
require.NoError(t, err)

// expected result
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// solana e2e user evm account
expectedMemo, err := hex.DecodeString("103fd9224f00ce3013e95629e52dfc31d805d68d")
require.NoError(t, err)
eventExpected := &clienttypes.InboundEvent{
SenderChainID: chain.ChainId,
Sender: sender,
Receiver: sender,
TxOrigin: sender,
Amount: 500000,
Memo: expectedMemo,
BlockNumber: txResult.Slot,
TxHash: txHash,
Index: 0, // not a EVM smart contract call
CoinType: coin.CoinType_ERC20,
Asset: "4GddKQ7baJpMyKna7bPPnhh7UQtpzfSGL1FgZ31hj4mp", // SPL address
}

t.Run("should parse inbound event deposit SPL", func(t *testing.T) {
event, err := ob.ParseInboundAsDepositSPL(tx, 0, txResult.Slot)
require.NoError(t, err)

// check result
require.EqualValues(t, eventExpected, event)
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"slot": 539,
"blockTime": 1730986363,
"transaction": {
"signatures": [
"aY8yLDze6nHSRi7L5REozKAZY1aAyPJ6TfibiqQL5JGwgSBkYux5z5JfXs5ed8LZqpXUy4VijoU3x15mBd66ZGE"
],
"message": {
"accountKeys": [
"37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ",
"HX8BXQKVw1xpoyDXMr9ujyrrpSYRWcFZ4oB3fRHpM8V7",
"5EVPJV5hjwYGYko2pSykSdJG5ZfBbMEDhYci2PrqQmby",
"9dcAyYG4bawApZocwZSyJBi9Mynf5EuKAJfifXdfkqik",
"8vquQi8xNxxBTsohf1u8xQHYbo7Fv8BEWCJz63RJSaeE",
"4GddKQ7baJpMyKna7bPPnhh7UQtpzfSGL1FgZ31hj4mp",
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d"
],
"header": {
"numRequiredSignatures": 1,
"numReadonlySignedAccounts": 0,
"numReadonlyUnsignedAccounts": 5
},
"recentBlockhash": "5ZB2NWKwp86t47ojCHPjRyd5vMKSWBdhxqDdtSZVPUj",
"instructions": [
{
"programIdIndex": 7,
"accounts": [
0,
3,
4,
5,
6,
1,
2
],
"data": "5JndgWCNHDyr2qQccK9VM1NxJFrVbUDvG2hfAxRC5z6nPPAVPsj7q3A"
}
]
}
},
"meta": {
"err": null,
"fee": 5000,
"preBalances": [
99992030600,
2039280,
2039280,
1447680,
946560,
1461600,
929020800,
1141440
],
"postBalances": [
99992025600,
2039280,
2039280,
1447680,
946560,
1461600,
929020800,
1141440
],
"innerInstructions": [
{
"index": 0,
"instructions": []
}
],
"preTokenBalances": [],
"postTokenBalances": [],
"logMessages": [
"Program 94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d invoke [1]",
"Program log: Instruction: DepositSplToken",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
"Program log: Instruction: Transfer Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 181038 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success Program log: deposit spl token successfully",
"Program 94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d consumed 24017 of 200000 compute units",
"Program 94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d success"
],
"status": {
"Ok": null
},
"rewards": [],
"loadedAddresses": {
"readonly": [],
"writable": []
},
"computeUnitsConsumed": 274902869112
},
"version": 0
}

0 comments on commit 1b0afb0

Please sign in to comment.