Skip to content

Commit

Permalink
add and fix unit tests for inbound parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
skosito committed Dec 6, 2024
1 parent 821f81f commit 7ea0595
Show file tree
Hide file tree
Showing 8 changed files with 557 additions and 113 deletions.
227 changes: 220 additions & 7 deletions pkg/contracts/solana/inbound_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func LoadSolanaInboundTxResult(

func Test_ParseInboundAsDeposit(t *testing.T) {
// ARRANGE
txHash := "MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
txHash := "8UeJoxY6RbMg6bffsUtZ9f79vSnd4HCRdk5EQgNbAEDYQWXNraiKDtGDZBLp91oyF5eQyWdv6pEwW1vcitiB4px"
chain := chains.SolanaDevnet

txResult := LoadSolanaInboundTxResult(t, txHash)
Expand All @@ -52,11 +52,15 @@ func Test_ParseInboundAsDeposit(t *testing.T) {
require.NoError(t, err)

// expected result
sender := "AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z"
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// solana e2e user evm account
expectedMemo, err := hex.DecodeString("103fd9224f00ce3013e95629e52dfc31d805d68d")
require.NoError(t, err)
expectedDeposit := &Deposit{
Sender: sender,
Amount: 100000,
Memo: []byte("0x7F8ae2ABb69A558CE6bAd546f25F0464D9e09e5B4955a3F38ff86ae92A914445099caa8eA2B9bA32"),
Amount: 12000000,
Memo: expectedMemo,
Slot: txResult.Slot,
Asset: "",
}
Expand Down Expand Up @@ -138,9 +142,114 @@ func Test_ParseInboundAsDeposit(t *testing.T) {
})
}

func Test_ParseInboundAsDepositAndCall(t *testing.T) {
// ARRANGE
txHash := "5b7ShhHf8dvUjUBHgMvgH8FFqpfAd7vAGygZLaeNPhugXtY5fatPSACVkn13o7sw6Awob8EJnrwAuiKYqvi7ZkHa"
chain := chains.SolanaDevnet

txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

// create observer
chainParams := sample.ChainParams(chain.ChainId)
chainParams.GatewayAddress = testutils.OldSolanaGatewayAddressDevnet
require.NoError(t, err)

// expected result
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// example contract deployed during e2e test, read from tx result
expectedReceiver := []byte{117, 160, 106, 140, 37, 135, 57, 218, 223, 226, 53, 45, 87, 151, 61, 239, 158, 231, 162, 186}
expectedMsg := []byte("hello lamports")
expectedDeposit := &Deposit{
Sender: sender,
Amount: 1200000,
Memo: append(expectedReceiver, expectedMsg...),
Slot: txResult.Slot,
Asset: "",
}

t.Run("should parse inbound event deposit SOL and call", func(t *testing.T) {
// ACT
deposit, err := ParseInboundAsDeposit(tx, 0, txResult.Slot)
require.NoError(t, err)

// ASSERT
require.EqualValues(t, expectedDeposit, deposit)
})

t.Run("should skip parsing if wrong discriminator", func(t *testing.T) {
// ARRANGE
txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

instruction := tx.Message.Instructions[0]

// try deserializing instruction as a 'deposit'
var inst DepositInstructionParams
err = borsh.Deserialize(&inst, instruction.Data)
require.NoError(t, err)

// serialize it back with wrong discriminator
data, err := borsh.Serialize(DepositInstructionParams{
Amount: inst.Amount,
Discriminator: DiscriminatorDepositSPL,
Receiver: inst.Receiver,
})
require.NoError(t, err)

tx.Message.Instructions[0].Data = data

// ACT
deposit, err := ParseInboundAsDeposit(tx, 0, txResult.Slot)

// ASSERT
require.NoError(t, err)
require.Nil(t, deposit)
})

t.Run("should fail if wrong accounts count", func(t *testing.T) {
// ARRANGE
txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

// append one more account to instruction
tx.Message.AccountKeys = append(tx.Message.AccountKeys, solana.MustPublicKeyFromBase58(sample.SolanaAddress(t)))
tx.Message.Instructions[0].Accounts = append(tx.Message.Instructions[0].Accounts, 4)

// ACT
deposit, err := ParseInboundAsDeposit(tx, 0, txResult.Slot)

// ASSERT
require.Error(t, err)
require.Nil(t, deposit)
})

t.Run("should fail if first account is not signer", func(t *testing.T) {
// ARRANGE
txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

// switch account places
tx.Message.Instructions[0].Accounts[0] = 1
tx.Message.Instructions[0].Accounts[1] = 0

// ACT
deposit, err := ParseInboundAsDeposit(tx, 0, txResult.Slot)

// ASSERT
require.Error(t, err)
require.Nil(t, deposit)
})
}

func Test_ParseInboundAsDepositSPL(t *testing.T) {
// ARRANGE
txHash := "aY8yLDze6nHSRi7L5REozKAZY1aAyPJ6TfibiqQL5JGwgSBkYux5z5JfXs5ed8LZqpXUy4VijoU3x15mBd66ZGE"
txHash := "5bXSQaq6BY1WhhF3Qm4pLHXxuyM9Mz1MrdMeoCFbimxw4uv11raQgAj4HGULPEQExPKB231rMhm6666dQMwf9fNN"
chain := chains.SolanaDevnet

txResult := LoadSolanaInboundTxResult(t, txHash)
Expand All @@ -159,10 +268,114 @@ func Test_ParseInboundAsDepositSPL(t *testing.T) {
require.NoError(t, err)
expectedDeposit := &Deposit{
Sender: sender,
Amount: 500000,
Amount: 12000000,
Memo: expectedMemo,
Slot: txResult.Slot,
Asset: "4GddKQ7baJpMyKna7bPPnhh7UQtpzfSGL1FgZ31hj4mp", // SPL address
Asset: "BTmtL9Dh2DcwhPntEbjo3rSWpmz1EhXsmohSC7CGSEWw", // SPL address
}

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

// ASSERT
require.EqualValues(t, expectedDeposit, deposit)
})

t.Run("should skip parsing if wrong discriminator", func(t *testing.T) {
// ARRANGE
txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

instruction := tx.Message.Instructions[0]

// try deserializing instruction as a 'deposit_spl'
var inst DepositSPLInstructionParams
err = borsh.Deserialize(&inst, instruction.Data)
require.NoError(t, err)

// serialize it back with wrong discriminator
data, err := borsh.Serialize(DepositInstructionParams{
Amount: inst.Amount,
Discriminator: DiscriminatorDeposit,
Receiver: inst.Receiver,
})
require.NoError(t, err)

tx.Message.Instructions[0].Data = data

// ACT
deposit, err := ParseInboundAsDepositSPL(tx, 0, txResult.Slot)

// ASSERT
require.NoError(t, err)
require.Nil(t, deposit)
})

t.Run("should fail if wrong accounts count", func(t *testing.T) {
// ARRANGE
txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

// append one more account to instruction
tx.Message.AccountKeys = append(tx.Message.AccountKeys, solana.MustPublicKeyFromBase58(sample.SolanaAddress(t)))
tx.Message.Instructions[0].Accounts = append(tx.Message.Instructions[0].Accounts, 4)

// ACT
deposit, err := ParseInboundAsDepositSPL(tx, 0, txResult.Slot)

// ASSERT
require.Error(t, err)
require.Nil(t, deposit)
})

t.Run("should fail if first account is not signer", func(t *testing.T) {
// ARRANGE
txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

// switch account places
tx.Message.Instructions[0].Accounts[0] = 1
tx.Message.Instructions[0].Accounts[1] = 0

// ACT
deposit, err := ParseInboundAsDepositSPL(tx, 0, txResult.Slot)

// ASSERT
require.Error(t, err)
require.Nil(t, deposit)
})
}

func Test_ParseInboundAsDepositAndCallSPL(t *testing.T) {
// ARRANGE
txHash := "22s5ERRRZmZXAuDMRdwUU33VnWZ7m8NHUZM6hyLH52JQPz5R7mXEkFcvHx88ujq3xDnt3z7sZdZ21JK2FC7vPw1o"
chain := chains.SolanaDevnet

txResult := LoadSolanaInboundTxResult(t, txHash)
tx, err := txResult.Transaction.GetTransaction()
require.NoError(t, err)

// create observer
chainParams := sample.ChainParams(chain.ChainId)
chainParams.GatewayAddress = testutils.OldSolanaGatewayAddressDevnet

// expected result
// solana e2e deployer account
sender := "37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ"
// example contract deployed during e2e test, read from tx result
expectedReceiver := []byte{213, 254, 240, 66, 1, 154, 250, 238, 39, 131, 9, 45, 5, 2, 190, 192, 20, 31, 103, 209}
expectedMsg := []byte("hello spl tokens")
expectedDeposit := &Deposit{
Sender: sender,
Amount: 12000000,
Memo: append(expectedReceiver, expectedMsg...),
Slot: txResult.Slot,
Asset: "7d4ehzE4WNgithQZMyQFDhmHyN6rQNTEC7re1bsRN7TX", // SPL address
}

t.Run("should parse inbound event deposit SPL", func(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"slot": 1111,
"blockTime": 1733490207,
"transaction": {
"signatures": [
"22s5ERRRZmZXAuDMRdwUU33VnWZ7m8NHUZM6hyLH52JQPz5R7mXEkFcvHx88ujq3xDnt3z7sZdZ21JK2FC7vPw1o"
],
"message": {
"accountKeys": [
"37yGiHAnLvWZUNVwu9esp74YQFqxU1qHCbABkDvRddUQ",
"9dcAyYG4bawApZocwZSyJBi9Mynf5EuKAJfifXdfkqik",
"EKZTsmjEMAbkStqWdoqyeFh4DkgB9zXr9yxwBHzcy2Sn",
"C2vKeBZ6yeUdeFC22UR82Drnj5AaXe4oKLgFQMJRpeDv",
"2zioTPUGiVwr4XZgDCy34qo2EbHQBU86jTU568rnKKri",
"7d4ehzE4WNgithQZMyQFDhmHyN6rQNTEC7re1bsRN7TX",
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"11111111111111111111111111111111",
"94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d"
],
"header": {
"numRequiredSignatures": 1,
"numReadonlySignedAccounts": 0,
"numReadonlyUnsignedAccounts": 5
},
"recentBlockhash": "HXK99VqYfwMDMEaJmxPgLLLygUUYpPry1mPkSJkwekDC",
"instructions": [
{
"programIdIndex": 8,
"accounts": [
0,
1,
4,
5,
6,
2,
3,
7
],
"data": "Q6siP5YLNCNi7eDfNNdsuMhgSAJvKMZiozqaPmi1rzGWxAJNPaUg8WK1a5v9GRriHGnLDuwmBZ9L"
}
]
}
},
"meta": {
"err": null,
"fee": 5000,
"preBalances": [
99967505600,
25947680,
2039280,
2039280,
946560,
1461600,
929020800,
1,
1141440
],
"postBalances": [
99965500600,
27947680,
2039280,
2039280,
946560,
1461600,
929020800,
1,
1141440
],
"innerInstructions": [
{
"index": 0,
"instructions": []
}
],
"preTokenBalances": [],
"postTokenBalances": [],
"logMessages": [
"Program 94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d invoke [1] Program log: Instruction: DepositSplTokenAndCall",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success Program",
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
"Program log: Instruction: Transfer Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 179934 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program log: deposit spl token successfully",
"Program 94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d consumed 25580 of 200000 compute units Program 94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d success"
],
"status": {
"Ok": null
},
"rewards": [],
"loadedAddresses": {
"readonly": [],
"writable": []
},
"computeUnitsConsumed": 274902869112
},
"version": 0
}
Loading

0 comments on commit 7ea0595

Please sign in to comment.