Skip to content

Conversation

@fadeev
Copy link
Member

@fadeev fadeev commented Nov 3, 2025

Program:

https://solana.fm/address/GhVHQQt9R3tHKjsewDphTsXLwnoTkdaZNzTovEgWfTGP/transactions?cluster=devnet-solana

CCTX:

https://zetachain-athens.blockpi.network/lcd/v1/public/zeta-chain/crosschain/inboundHashToCct[…]5da0676493c959522b2b6015a6fb311d331b902d7c4587ecd5c8

Solana tx:

https://solana.fm/tx/4p9X2MRCfbA7XSERVrnzN9kMZfzEXfdyvJaa7NZqDFj7U62AZim2aGpZ7QhHTKBbNkYekHmzhS1z6zHKubcCyvty?cluster=devnet-solana

Tested with: zeta-chain/example-contracts#287

Associated docs: zeta-chain/docs#685

Summary by CodeRabbit

  • Documentation

    • Clarified CLI help: --connected now described as a program address.
  • New Features

    • Added --accounts <accounts...> option to supply extra accounts with writability.
  • Refactor

    • Improved Solana account assembly to include the instructions sysvar alongside existing accounts for both mint and non-mint flows.
  • Tests

    • Replaced hardcoded payload expectations with runtime decoding and programmatic validation of accounts, keys, and writability.

@fadeev fadeev requested review from a team as code owners November 3, 2025 13:14
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

📝 Walkthrough

Walkthrough

Derives a connected PDA from a provided program address (seed "connected"), adds SYSVAR_INSTRUCTIONS_PUBKEY to base account lists in both mint and non-mint branches, adds a CLI --accounts option, and updates tests to decode and validate encoded results programmatically.

Changes

Cohort / File(s) Summary
Account derivation & sysvar inclusion
packages/client/src/solanaEncode.ts
Derives connectedProgramId from the provided connected address and computes connectedPdaAccount via findProgramAddressSync (seed "connected"). Introduces instructionSysvar (SYSVAR_INSTRUCTIONS_PUBKEY) and appends it to baseAccounts in both mint and non-mint flows.
CLI options
packages/commands/src/solana/encode.ts
Changes --connected help text to "Connected program address" and adds a new --accounts <accounts...> option to accept additional accounts in the format address:isWritable.
Tests: dynamic decoding & account verification
test/solanaEncode.test.ts
Replaces hardcoded expected payloads with runtime decoding of encoded data using decodeEncodedResult and tupleSignature; computes PDAs (connected, gateway/meta) and, for mint cases, associated token addresses; validates decoded data bytes and accounts list (including SYSVAR and any extra --accounts) programmatically.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI (--connected, --accounts)
  participant Encoder as solanaEncode
  participant SDK as `@solana/web3` (findProgramAddressSync)
  note right of CLI `#E8F3FF`: User provides <connected> program address and optional extra accounts
  CLI->>Encoder: pass connected address, data, options, accounts...
  Encoder->>SDK: parse connected -> create connectedProgramId
  SDK-->>Encoder: connectedPdaAccount (findProgramAddressSync "connected")
  Encoder->>Encoder: compute gateway/meta PDA(s)
  Encoder->>Encoder: build baseAccounts (pda, gatewayPda, ..., token/systemProgram, instructionSysvar)
  Encoder-->>CLI: return encoded transaction payload and accounts
  note over Encoder `#F6FFF0`: instructionSysvar (SYSVAR_INSTRUCTIONS_PUBKEY) included in accounts
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review findProgramAddressSync usage and seed consistency in packages/client/src/solanaEncode.ts.
  • Verify ordering and isWritable flags for all accounts including instructionSysvar across mint/non-mint branches.
  • Validate CLI parsing/formatting for the new --accounts option (address:isWritable) in packages/commands/src/solana/encode.ts.
  • Inspect test changes (test/solanaEncode.test.ts) for correctness of decoding, PDA/token derivation, and assertions.

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: updating Solana encoding logic to be compatible with the latest Gateway by modifying how connected accounts are derived and adding the instruction sysvar.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch solana-encode-fix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the fix label Nov 3, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 31170ea and ab2f47b.

📒 Files selected for processing (2)
  • packages/client/src/solanaEncode.ts (3 hunks)
  • packages/commands/src/solana/encode.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: fadeev
Repo: zeta-chain/toolkit PR: 346
File: packages/commands/src/ton/depositAndCall.ts:0-0
Timestamp: 2025-06-13T15:33:54.781Z
Learning: fadeev prefers responses in English.
Learnt from: fadeev
Repo: zeta-chain/toolkit PR: 346
File: packages/commands/src/ton/deposit.ts:0-0
Timestamp: 2025-06-13T15:32:09.225Z
Learning: User fadeev prefers that responses be in English; avoid replying in Russian in future interactions.
🪛 ESLint
packages/client/src/solanaEncode.ts

[error] 50-52: Replace ⏎······anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY.toBytes()⏎···· with anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY.toBytes()

(prettier/prettier)

🪛 GitHub Actions: Lint
packages/client/src/solanaEncode.ts

[error] 50-50: Prettier formatting error. Replace the newline-wrapped anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY.toBytes() with anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY.toBytes() according to prettier/prettier.

🪛 GitHub Check: build
packages/client/src/solanaEncode.ts

[failure] 50-50:
Replace ⏎······anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY.toBytes()⏎···· with anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY.toBytes()

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
packages/commands/src/solana/encode.ts (1)

17-20: LGTM! Documentation accurately reflects the implementation change.

The updated help text correctly describes that the --connected parameter is now a program address used to derive the PDA, which aligns with the implementation changes in solanaEncode.ts.

packages/client/src/solanaEncode.ts (3)

79-87: LGTM! Instruction sysvar correctly added to mint path.

Adding SYSVAR_INSTRUCTIONS_PUBKEY to the base accounts enables the Gateway to introspect the current transaction's instructions, which is essential for security validations in the latest Gateway implementation.


88-90: LGTM! Instruction sysvar correctly added to non-mint path.

Consistent with the mint path, SYSVAR_INSTRUCTIONS_PUBKEY is properly added to ensure Gateway compatibility.


23-27: Verify seed "connected" against Gateway protocol documentation.

The PDA derivation logic is implemented correctly and follows Solana best practices. However, codebase analysis reveals:

  • The seed "connected" appears only in solanaEncode.ts and is not referenced elsewhere
  • The derivation pattern (Buffer.from seed + programId) is consistent with other PDAs in the codebase (e.g., "meta", "whitelist")
  • No contradictions found in the codebase

To confirm the seed is correct for Gateway compatibility, verify against the latest Solana Gateway protocol specification or implementation, as this validation point exists outside the repository.

Copy link

@lumtis lumtis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fadeev
Copy link
Member Author

fadeev commented Nov 3, 2025

@hernan-clich please, review as code owner. Thanks!

Copy link
Member

@skosito skosito left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me, we can also work on supporting ALT, nothing needs to change on example programs, just in a way it is called

there are tests in gateway.ts in solana repo with (ALT) in the name

.requiredOption("--connected <address>", "Connected PDA account address")
.requiredOption(
"--connected <address>",
"Connected program address used to derive the PDA"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be just Connected program address i think

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect(accounts[3].publicKey).toBe(
hexlifyPubkey(anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY)
);
expect(accounts[3].isWritable).toBe(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also add some remainingAccounts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand what you mean 🤔

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
test/solanaEncode.test.ts (3)

185-197: Consider extracting the base account count as a constant.

The hardcoded 7 on line 194 assumes the base account count for mint scenarios. This could break if the base accounts change. Consider making this more explicit.

+    const BASE_ACCOUNTS_WITH_MINT = 7;
+
     additionalAccounts.forEach((expectedAccount, index) => {
-      const account = accounts[index + 7];
+      const account = accounts[index + BASE_ACCOUNTS_WITH_MINT];
       expect(account.publicKey).toBe(expectedAccount.publicKey);
       expect(account.isWritable).toBe(expectedAccount.isWritable);
     });

200-219: Consider more specific error assertions.

The error tests verify that invalid inputs throw, but could be more specific about the expected error type or message for better test documentation and catching unintended errors.

Example:

await expect(solanaEncode(input)).rejects.toThrow(/Invalid account format/);

26-198: Consider extracting common PDA derivation logic.

The three main test cases duplicate PDA and account derivation logic. Extracting this into a helper function would improve maintainability and make the tests more focused on their specific scenarios.

Example helper:

const deriveTestAccounts = async (input: any) => {
  const connectedProgramId = new anchor.web3.PublicKey(input.connected);
  const [connectedPdaAccount] = anchor.web3.PublicKey.findProgramAddressSync(
    [Buffer.from("connected", "utf-8")],
    connectedProgramId
  );
  const [gatewayPdaAccount] = anchor.web3.PublicKey.findProgramAddressSync(
    [Buffer.from("meta", "utf-8")],
    new anchor.web3.PublicKey(input.gateway)
  );
  
  let connectedPdaAta;
  let mintPubkey;
  if (input.mint) {
    mintPubkey = new anchor.web3.PublicKey(input.mint);
    connectedPdaAta = await getAssociatedTokenAddress(
      mintPubkey,
      connectedPdaAccount,
      true
    );
  }
  
  return { connectedPdaAccount, gatewayPdaAccount, connectedPdaAta, mintPubkey };
};

This would reduce duplication and make test updates easier.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c805b27 and 4eeecbd.

📒 Files selected for processing (2)
  • packages/commands/src/solana/encode.ts (1 hunks)
  • test/solanaEncode.test.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/commands/src/solana/encode.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: fadeev
Repo: zeta-chain/toolkit PR: 346
File: packages/commands/src/ton/depositAndCall.ts:0-0
Timestamp: 2025-06-13T15:33:54.781Z
Learning: fadeev prefers responses in English.
Learnt from: fadeev
Repo: zeta-chain/toolkit PR: 346
File: packages/commands/src/ton/deposit.ts:0-0
Timestamp: 2025-06-13T15:32:09.225Z
Learning: User fadeev prefers that responses be in English; avoid replying in Russian in future interactions.
🧬 Code graph analysis (1)
test/solanaEncode.test.ts (1)
packages/client/src/solanaEncode.ts (1)
  • solanaEncode (16-103)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: build
🔇 Additional comments (3)
test/solanaEncode.test.ts (3)

1-24: LGTM! Well-structured test utilities.

The helper functions and type definitions are clean and promote code reuse throughout the test suite. The decodeEncodedResult and hexlifyPubkey helpers effectively reduce duplication and improve test readability.


26-64: LGTM! Comprehensive validation of base encoding.

The test properly validates both the encoded data and the account structure. The test at lines 124-198 addresses the previous review comment about remainingAccounts by including additional accounts scenarios.


66-122: LGTM! Thorough validation of mint scenario.

The test comprehensively validates the mint encoding path, including the associated token address derivation and all seven expected accounts with correct writability flags.

Copy link
Member

@hernan-clich hernan-clich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK

@fadeev
Copy link
Member Author

fadeev commented Nov 4, 2025

Merging this. Will be adding ALT support in follow up PR.

@fadeev fadeev merged commit e7969f9 into main Nov 4, 2025
13 checks passed
@fadeev fadeev deleted the solana-encode-fix branch November 4, 2025 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants