Skip to content

solana: refactor token accounts validation with Anchor context#756

Merged
jadepark-dev merged 7 commits intomainfrom
solana/token-accounts-validation-refactor
Mar 24, 2025
Merged

solana: refactor token accounts validation with Anchor context#756
jadepark-dev merged 7 commits intomainfrom
solana/token-accounts-validation-refactor

Conversation

@jadepark-dev
Copy link
Copy Markdown
Contributor

@jadepark-dev jadepark-dev commented Mar 21, 2025

This PR refactors the token account validation logic in CCIP Solana programs by leveraging Anchor's built-in account validation system.

Primary Changes

  • Created TokenAccountsValidationContext account struct in both offramp and router programs
  • Replaced manual validation checks with Anchor's declarative constraints
  • Consolidated PDA derivation and ownership validations in the account context struct
  • Standardized error handling across programs

Others

  • Removed redundant error codes (InvalidInputsConfigAccounts)

  • Created AnchorError enum in common utils to standardize error string handling in tests

  • Updated tests to reference the new standardized error codes

  • Simplified account iteration with next_account_info instead of manual splitting

  • Dependency: [Solana][NONEVM-1452] Multiple deduplications / refactor #750

@jadepark-dev jadepark-dev self-assigned this Mar 21, 2025
@jadepark-dev jadepark-dev marked this pull request as ready for review March 21, 2025 17:11
@jadepark-dev jadepark-dev requested a review from a team as a code owner March 21, 2025 17:11
Copy link
Copy Markdown
Contributor

@toblich toblich left a comment

Choose a reason for hiding this comment

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

Looks great! Some small comments

)]
pub user_token_account: InterfaceAccount<'info, TokenAccount>,

// TODO: determine if this can be zero key for optional billing config?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think billing is not optional, and this TODO can be removed.
Basically, from the user's PoV, they are required to always pass in the billing accounts. Then, Fee Quoter can handle the case where the account is not initialized (i.e. there's no special billing configs for that case), but the user can't be the one to choose whether they pass it in or not.

// Instead of manually checking each account (ownership, PDA derivation, constraints),
// we're using Anchor's `try_accounts` to perform these validations based on the
// constraints defined in the `TokenAccountsValidationContext` account context struct
let program_id = crate::id();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For what it's worth, I spent a bit of time looking into Anchor's internals for this, and it seems like the try_accounts in this case will just ignore the program id set here (which is ok), so I'll ask you to please do the following:

  • Run the tests setting here a random pubkey as well, and confirm that tests should pass just fine
  • Then add a comment clarifying that this value is not used

My original concern was that, as we change program addresses from env to env, I'm not 100% sure that when we're compiling the offramp for a particular env the common crate will correctly have the router address for that same env. That's why I checked the code, and if you can just confirm empirically that it doesn't really matter and then document it, then this LGMT 👍

Copy link
Copy Markdown
Contributor Author

@jadepark-dev jadepark-dev Mar 24, 2025

Choose a reason for hiding this comment

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

Thanks for looking into it! Yes, it’s not being used at all—every PDA derivation in the TokenAccountsValidationContext has explicit program IDs. I’m opting to set it to a default Pubkey so that if we ever modify the context to rely on the context’s program ID, the tests will fail and alert us to the change.
2da1017 (#756)

PabloMansanet
PabloMansanet previously approved these changes Mar 24, 2025
Copy link
Copy Markdown
Contributor

@PabloMansanet PabloMansanet left a comment

Choose a reason for hiding this comment

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

Looks great, pending addressing Tobi's concerns. Good work!

let (user_token_account, remaining_accounts) = accounts.split_first().unwrap();
let (token_billing_config, remaining_accounts) = remaining_accounts.split_first().unwrap();
let (pool_chain_config, remaining_accounts) = remaining_accounts.split_first().unwrap();
let user_token_account = next_account_info(&mut accounts_iter)?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Very minor nit, but those accounts could be retrieved from the iterator a bit later, after the validations. That way it's a bit more clear when they're needed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Make sense, thanks! modified in 51cd88a (#756)

@github-actions
Copy link
Copy Markdown

Metric solana/token-accounts-validation-refactor main
Coverage 72.0% 71.9%

@jadepark-dev jadepark-dev merged commit 1df481f into main Mar 24, 2025
23 checks passed
@jadepark-dev jadepark-dev deleted the solana/token-accounts-validation-refactor branch March 24, 2025 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants