Skip to content

Commit 7b34d1d

Browse files
authored
fix: ask for 3 accounts (signer, pda, system_program) when parsing Sonala inbound signer address (#2787)
* explicitly ask for 3 accounts on solana gateway deposit; use default relayer key path if not set * add changelog entry and revert the modification on localnet docker file * add unit test for default relayer key path * move changelog entry to Fixes section
1 parent 91c323d commit 7b34d1d

11 files changed

+117
-92
lines changed

changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
* [2654](https://github.com/zeta-chain/node/pull/2654) - add validation for authorization list in when validating genesis state for authorization module
3535
* [2674](https://github.com/zeta-chain/node/pull/2674) - allow operators to vote on ballots associated with discarded keygen without affecting the status of the current keygen.
3636
* [2672](https://github.com/zeta-chain/node/pull/2672) - check observer set for duplicates when adding a new observer or updating an existing one
37+
* [2787](https://github.com/zeta-chain/node/pull/2787) - ask for 3 accounts (signer, pda, system_program) on solana gateway deposit
3738

3839
## v19.0.0
3940

cmd/zetaclientd/import_relayer_keys.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/zeta-chain/zetacore/pkg/chains"
1313
"github.com/zeta-chain/zetacore/pkg/crypto"
1414
zetaos "github.com/zeta-chain/zetacore/pkg/os"
15+
"github.com/zeta-chain/zetacore/zetaclient/config"
1516
"github.com/zeta-chain/zetacore/zetaclient/keys"
1617
)
1718

@@ -52,8 +53,7 @@ func init() {
5253
RootCmd.AddCommand(CmdRelayerAddress)
5354

5455
// resolve default relayer key path
55-
defaultRelayerKeyPath := "~/.zetacored/relayer-keys"
56-
defaultRelayerKeyPath, err := zetaos.ExpandHomeDir(defaultRelayerKeyPath)
56+
defaultRelayerKeyPath, err := zetaos.ExpandHomeDir(config.DefaultRelayerKeyPath)
5757
if err != nil {
5858
log.Fatal().Err(err).Msg("failed to resolve default relayer key path")
5959
}

e2e/runner/solana.go

-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ func (r *E2ERunner) CreateDepositInstruction(
4444
accountSlice = append(accountSlice, solana.Meta(signer).WRITE().SIGNER())
4545
accountSlice = append(accountSlice, solana.Meta(pdaComputed).WRITE())
4646
accountSlice = append(accountSlice, solana.Meta(solana.SystemProgramID))
47-
accountSlice = append(accountSlice, solana.Meta(programID))
4847
inst.ProgID = programID
4948
inst.AccountValues = accountSlice
5049

pkg/contracts/solana/gateway.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ const (
1414
PDASeed = "meta"
1515

1616
// AccountsNumberOfDeposit is the number of accounts required for Solana gateway deposit instruction
17-
// [signer, pda, system_program, gateway_program]
18-
AccountsNumDeposit = 4
17+
// [signer, pda, system_program]
18+
AccountsNumDeposit = 3
1919
)
2020

2121
// DiscriminatorInitialize returns the discriminator for Solana gateway 'initialize' instruction

zetaclient/chains/solana/observer/inbound.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,13 @@ func (ob *Observer) ParseInboundAsDeposit(
285285
return nil, nil
286286
}
287287

288-
// get the sender address (the signer must exist)
288+
// get the sender address (skip if unable to parse signer address)
289289
sender, err := ob.GetSignerDeposit(tx, &instruction)
290290
if err != nil {
291-
return nil, errors.Wrap(err, "error GetSignerDeposit")
291+
ob.Logger().
292+
Inbound.Err(err).
293+
Msgf("unable to get signer for sig %s instruction %d", tx.Signatures[0], instructionIndex)
294+
return nil, nil
292295
}
293296

294297
// build inbound event
@@ -323,13 +326,13 @@ func (ob *Observer) ParseInboundAsDepositSPL(
323326
// GetSignerDeposit returns the signer address of the deposit instruction
324327
// Note: solana-go is not able to parse the AccountMeta 'is_signer' ATM. This is a workaround.
325328
func (ob *Observer) GetSignerDeposit(tx *solana.Transaction, inst *solana.CompiledInstruction) (string, error) {
326-
// there should be 4 accounts for a deposit instruction
329+
// there should be 3 accounts for a deposit instruction
327330
if len(inst.Accounts) != solanacontracts.AccountsNumDeposit {
328331
return "", fmt.Errorf("want %d accounts, got %d", solanacontracts.AccountsNumDeposit, len(inst.Accounts))
329332
}
330333

331-
// the accounts are [signer, pda, system_program, gateway_program]
332-
signerIndex, pdaIndex, systemIndex, gatewayIndex := -1, -1, -1, -1
334+
// the accounts are [signer, pda, system_program]
335+
signerIndex, pdaIndex, systemIndex := -1, -1, -1
333336

334337
// try to find the indexes of all above accounts
335338
for _, accIndex := range inst.Accounts {
@@ -340,8 +343,6 @@ func (ob *Observer) GetSignerDeposit(tx *solana.Transaction, inst *solana.Compil
340343
switch accKey {
341344
case ob.pda:
342345
pdaIndex = accIndexInt
343-
case ob.gatewayID:
344-
gatewayIndex = accIndexInt
345346
case solana.SystemProgramID:
346347
systemIndex = accIndexInt
347348
default:
@@ -351,7 +352,7 @@ func (ob *Observer) GetSignerDeposit(tx *solana.Transaction, inst *solana.Compil
351352
}
352353

353354
// all above accounts must be found
354-
if signerIndex == -1 || pdaIndex == -1 || systemIndex == -1 || gatewayIndex == -1 {
355+
if signerIndex == -1 || pdaIndex == -1 || systemIndex == -1 {
355356
return "", fmt.Errorf("invalid accounts for deposit instruction")
356357
}
357358

zetaclient/chains/solana/observer/inbound_test.go

+14-14
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ var (
2626

2727
func Test_FilterInboundEventAndVote(t *testing.T) {
2828
// load archived inbound vote tx result
29-
// https://explorer.solana.com/tx/5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk?cluster=devnet
30-
txHash := "5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk"
29+
// https://explorer.solana.com/tx/MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j?cluster=devnet
30+
txHash := "MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
3131
chain := chains.SolanaDevnet
3232
txResult := testutils.LoadSolanaInboundTxResult(t, TestDataDir, chain.ChainId, txHash, false)
3333

@@ -51,8 +51,8 @@ func Test_FilterInboundEventAndVote(t *testing.T) {
5151

5252
func Test_FilterInboundEvents(t *testing.T) {
5353
// load archived inbound deposit tx result
54-
// https://explorer.solana.com/tx/5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk?cluster=devnet
55-
txHash := "5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk"
54+
// https://explorer.solana.com/tx/MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j?cluster=devnet
55+
txHash := "MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
5656
chain := chains.SolanaDevnet
5757
txResult := testutils.LoadSolanaInboundTxResult(t, TestDataDir, chain.ChainId, txHash, false)
5858

@@ -61,20 +61,20 @@ func Test_FilterInboundEvents(t *testing.T) {
6161

6262
// create observer
6363
chainParams := sample.ChainParams(chain.ChainId)
64-
chainParams.GatewayAddress = GatewayAddressTest
64+
chainParams.GatewayAddress = testutils.GatewayAddresses[chain.ChainId]
6565

6666
ob, err := observer.NewObserver(chain, nil, *chainParams, nil, nil, database, base.DefaultLogger(), nil)
6767
require.NoError(t, err)
6868

6969
// expected result
70-
sender := "AKbG83jg2V65R7XvaPFrnUvUTWsFENEzDPbLJFEiAk6L"
70+
sender := "AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z"
7171
eventExpected := &clienttypes.InboundEvent{
7272
SenderChainID: chain.ChainId,
7373
Sender: sender,
7474
Receiver: sender,
7575
TxOrigin: sender,
76-
Amount: 1280,
77-
Memo: []byte("hello this is a good memo for you to enjoy"),
76+
Amount: 100000,
77+
Memo: []byte("0x7F8ae2ABb69A558CE6bAd546f25F0464D9e09e5B4955a3F38ff86ae92A914445099caa8eA2B9bA32"),
7878
BlockNumber: txResult.Slot,
7979
TxHash: txHash,
8080
Index: 0, // not a EVM smart contract call
@@ -156,8 +156,8 @@ func Test_BuildInboundVoteMsgFromEvent(t *testing.T) {
156156

157157
func Test_ParseInboundAsDeposit(t *testing.T) {
158158
// load archived inbound deposit tx result
159-
// https://explorer.solana.com/tx/5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk?cluster=devnet
160-
txHash := "5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk"
159+
// https://explorer.solana.com/tx/MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j?cluster=devnet
160+
txHash := "MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
161161
chain := chains.SolanaDevnet
162162

163163
txResult := testutils.LoadSolanaInboundTxResult(t, TestDataDir, chain.ChainId, txHash, false)
@@ -169,19 +169,19 @@ func Test_ParseInboundAsDeposit(t *testing.T) {
169169

170170
// create observer
171171
chainParams := sample.ChainParams(chain.ChainId)
172-
chainParams.GatewayAddress = GatewayAddressTest
172+
chainParams.GatewayAddress = testutils.GatewayAddresses[chain.ChainId]
173173
ob, err := observer.NewObserver(chain, nil, *chainParams, nil, nil, database, base.DefaultLogger(), nil)
174174
require.NoError(t, err)
175175

176176
// expected result
177-
sender := "AKbG83jg2V65R7XvaPFrnUvUTWsFENEzDPbLJFEiAk6L"
177+
sender := "AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z"
178178
eventExpected := &clienttypes.InboundEvent{
179179
SenderChainID: chain.ChainId,
180180
Sender: sender,
181181
Receiver: sender,
182182
TxOrigin: sender,
183-
Amount: 1280,
184-
Memo: []byte("hello this is a good memo for you to enjoy"),
183+
Amount: 100000,
184+
Memo: []byte("0x7F8ae2ABb69A558CE6bAd546f25F0464D9e09e5B4955a3F38ff86ae92A914445099caa8eA2B9bA32"),
185185
BlockNumber: txResult.Slot,
186186
TxHash: txHash,
187187
Index: 0, // not a EVM smart contract call

zetaclient/config/types.go

+8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ const (
2020

2121
// KeyringBackendFile is the file Cosmos keyring backend
2222
KeyringBackendFile KeyringBackend = "file"
23+
24+
// DefaultRelayerKeyPath is the default path that relayer keys are stored
25+
DefaultRelayerKeyPath = "~/.zetacored/relayer-keys"
2326
)
2427

2528
// ClientConfiguration is a subset of zetaclient config that is used by zetacore client
@@ -163,6 +166,11 @@ func (c Config) GetKeyringBackend() KeyringBackend {
163166
func (c Config) GetRelayerKeyPath() string {
164167
c.mu.RLock()
165168
defer c.mu.RUnlock()
169+
170+
// use default path if not configured
171+
if c.RelayerKeyPath == "" {
172+
return DefaultRelayerKeyPath
173+
}
166174
return c.RelayerKeyPath
167175
}
168176

zetaclient/config/types_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package config_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
"github.com/zeta-chain/zetacore/zetaclient/config"
8+
)
9+
10+
func Test_GetRelayerKeyPath(t *testing.T) {
11+
// create config
12+
cfg := config.New(false)
13+
14+
// should return default relayer key path
15+
require.Equal(t, config.DefaultRelayerKeyPath, cfg.GetRelayerKeyPath())
16+
}

zetaclient/testdata/solana/chain_901_inbound_tx_result_5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk.json

-64
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"slot": 321701608,
3+
"blockTime": 1724732369,
4+
"transaction": {
5+
"signatures": [
6+
"MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
7+
],
8+
"message": {
9+
"accountKeys": [
10+
"AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z",
11+
"2f9SLuUNb7TNeM6gzBwT4ZjbL5ZyKzzHg1Ce9yiquEjj",
12+
"11111111111111111111111111111111",
13+
"ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis"
14+
],
15+
"header": {
16+
"numRequiredSignatures": 1,
17+
"numReadonlySignedAccounts": 0,
18+
"numReadonlyUnsignedAccounts": 2
19+
},
20+
"recentBlockhash": "41txNvjedo2eu6aAofQfyLskAcgtrtgch9RpqnrKcv1a",
21+
"instructions": [
22+
{
23+
"programIdIndex": 3,
24+
"accounts": [0, 1, 2],
25+
"data": "4ALHYcAj3zFsNjmfeq7nDK1E8BsxRQRzhLjrqzmjYzL97Qkiz4rP1iQePmFAehfFEET7uczYLhhEVhtndBYNNm6ekHSkgsLzYDeSD2JSudHa6D5tqhVGjvXZ7qEouPiy9eptZfuYHE9X"
26+
}
27+
]
28+
}
29+
},
30+
"meta": {
31+
"err": null,
32+
"fee": 5000,
33+
"preBalances": [9999364000, 1001447680, 1, 1141440],
34+
"postBalances": [9999259000, 1001547680, 1, 1141440],
35+
"innerInstructions": [
36+
{
37+
"index": 0,
38+
"instructions": [
39+
{
40+
"programIdIndex": 2,
41+
"accounts": [0, 1],
42+
"data": "3Bxs4ThwQbE4vyj5"
43+
}
44+
]
45+
}
46+
],
47+
"preTokenBalances": [],
48+
"postTokenBalances": [],
49+
"logMessages": [
50+
"Program ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis invoke [1]",
51+
"Program log: Instruction: Deposit",
52+
"Program 11111111111111111111111111111111 invoke [2]",
53+
"Program 11111111111111111111111111111111 success",
54+
"Program log: AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z deposits 100000 lamports to PDA",
55+
"Program ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis consumed 17006 of 200000 compute units",
56+
"Program ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis success"
57+
],
58+
"status": { "Ok": null },
59+
"rewards": [],
60+
"loadedAddresses": { "readonly": [], "writable": [] },
61+
"computeUnitsConsumed": 17006
62+
},
63+
"version": 0
64+
}

zetaclient/testutils/constant.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const (
3636
// GatewayAddresses contains constants gateway addresses for testing
3737
var GatewayAddresses = map[int64]string{
3838
// Gateway address on Solana devnet
39-
chains.SolanaDevnet.ChainId: "94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d",
39+
chains.SolanaDevnet.ChainId: "ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis",
4040
}
4141

4242
// ConnectorAddresses contains constants ERC20 connector addresses for testing

0 commit comments

Comments
 (0)