feat(cct-sdk): Add configure allowlist solana op - #323
Conversation
…10498-deploy-token
…10498-deploy-token
…10498-deploy-token
…-create-token-account
…10498-deploy-token
…-create-token-account
…-10498-deploy-token
…-create-token-account
…-create-token-account
…-create-token-account
|
You must have Developer access to commit code to Chainlink Labs on Vercel. If you contact an administrator and receive Developer access, commit again to see your changes. Learn more: https://vercel.com/docs/accounts/team-members-and-roles/access-roles#team-level-roles |
aelmanaa
left a comment
There was a problem hiding this comment.
Reviewed a03421d across type-safety, architecture, and DX — grounded against the chainlink-ccip Solana pool programs and proven end-to-end on devnet (the op configures the allowlist and the allowlist actually gates sends). The op is functionally correct; requesting changes on DX/naming/docs/scope before it ships on the CCT surface.
Proof the op writes correct state (append semantics + duplicate revert), live devnet:
- add A → tx, add B → tx, add C → tx → read-back
allow_list = [A, B, C]in insertion order = append, not replace. - re-add existing A → reverts
AllowlistKeyAlreadyExisted(err 6010) — grounded atburnmint-token-pool/src/lib.rs:376-380(add: Vec<Pubkey>,push,require!(!list.contains…)).
Proof the allowlist ENFORCES sends (2×2 sender matrix, live devnet): two fresh pools (op is append-only → one per case), allowlist written by this op, then the exact gated instruction lock_or_burn_tokens simulated against live pool state:
| pool | original_sender |
in list? | result |
|---|---|---|---|
P1 allow_list=[WALLET] (configure tx) |
WALLET | ✅ | PASS — burn executes, pool returns LockOrBurnOutV1 |
| P1 | OTHER | ❌ | BLOCKED — InvalidSender 6006 |
P2 allow_list=[OTHER] (configure tx) |
OTHER | ✅ | PASS |
| P2 | WALLET | ❌ | BLOCKED — InvalidSender 6006 |
Same pool, flip only original_sender → flips PASS ↔ block, isolating the allowlist as the sole variable. Block is the grounded gate base-token-pool/src/common.rs:659: require!(!allow_list_enabled || allow_list.contains(&original_sender), InvalidSender) → verbatim AnchorError … common.rs:659. Error Code: InvalidSender. Error Number: 6006. Error Message: Sender not allowed (0x1776). Pool states: P1 · P2.
The 5 blockers in the inline comments are all independent of enforcement working — and proving it does enforce actually sharpens B1/B2 (a wrong address genuinely blocks senders, and there's no SDK way to remove it).
I’ve addressed the inline feedback: renamed the append input to |
aelmanaa
left a comment
There was a problem hiding this comment.
Re-reviewed 930a731 across type-safety, architecture, and DX — grounded against the chainlink-ccip Solana pool programs and proven end-to-end on devnet (the op writes the allowlist and the allowlist actually gates sends). The first pass (a03421d) requested changes on 5 DX/naming/docs/test items; b5083b0 "fix: address comments" resolves all five. Approving.
All 5 blockers resolved (verified):
- B1 ✅ param
allowlist→add(matches the IDLadd: Vec<Pubkey>+ mirrors the futureremove); doc now "Addresses to append … Must not contain duplicates"; new client-side dedup parses eachadd[i]thenSet-checks, rejecting within-array duplicates before the on-chainAllowlistKeyAlreadyExistedrevert. - B2 ✅ facade
@remarks Removing addresses is not yet supported by the SDK.on both methods (and now superseded — the companionremoveFromAllowListhas since landed as DAPP-10806). - B3 ✅ facade docs "Every call overwrites enforcement; pass
add: []to toggle it without appending"; execute@exampleshows the pure-toggle pattern (add: [], enabled: false). - B4 ✅
append-to-lookup-table.ts:94—?.restored (!params.additionalAddresses?.length) with a narroweslint-disable-next-line @typescript-eslint/no-unnecessary-condition(this fix rode in via thefix/refactor-solana-operationbase). - B5 ✅ tests: multi-address + append with an
enabled: falsedecoded-assert (catches a swapped-args bug), empty-list toggle, non-array reject, duplicate reject, and an execute success path; the@seecopy-paste nit is fixed (generate↔execute cross-link).
DRY ✓ faithful accept-admin parse/prepare clone, shared validators reused, accountsStrict matches the IDL. Cross-family: interface reused polymorphically — same SolanaOperation lifecycle; EVM has no allowlist SDK op yet (its pool exposes applyAllowListUpdates, a future EVM op is owed). Per-version validity: grounded against burnmint/cctp/lockrelease pool programs — configure_allow_list(add, enabled) identical across all three. npm run check green.
Proof it writes correct state (append semantics + dedup), live devnet @ 930a731 — fresh burn-mint pool mint UmhE5TR…PpFdY: renamed add API lands and appends (ground-truth read allowList=[X, Y] insertion order) — add X, append Y; toggle-only add:[] enabled:false → ground-truth listEnabled=false tx; new dedup guard add:[Z,Z] → rejected pre-RPC CCTParamsInvalidError param=add "must not contain duplicate addresses".
Proof it ENFORCES sends (2×2 sender matrix, live devnet — still valid; the on-chain instruction is byte-identical to a03421d, only the TS param name + a pre-RPC guard changed): two fresh pools (P1 91y9tsa… · P2 2Jhfsf…), allowlist written by this op, then lock_or_burn_tokens simulated against live state:
| pool | original_sender |
in list? | result |
|---|---|---|---|
P1 allow_list=[WALLET] |
WALLET | ✅ | PASS — burn executes |
| P1 | OTHER | ❌ | BLOCKED — InvalidSender 6006 |
P2 allow_list=[OTHER] |
OTHER | ✅ | PASS |
| P2 | WALLET | ❌ | BLOCKED — InvalidSender 6006 |
Flipping only original_sender flips PASS↔block — isolating the allowlist as the sole variable. Block is the grounded gate base-token-pool/src/common.rs:659 require!(!allow_list_enabled || allow_list.contains(&original_sender), InvalidSender) (0x1776).
Minor note (not blocking): deployTokenPool still names its initial-set param allowlist while the append op is now add — defensible (set vs append), flagging for a conscious call.
What
configureAllowlistunsigned and signed operationsWhy