You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
Summary: Correct (mint-role gate is right and live-proven), type-safe, contract-grounded. Adds getMinters/getBurners (read the BurnMintERC677 role sets), a role-gated manual mint, and the token/contracts.ts helpers getErc20Token, readTokenRole, readTokenRoleHolders.
Key Verification:
mint auth gate is CORRECT — gated on the mint role (readTokenRole(isMinter, sender)), NOT owner. Mirrors the on-chain mint(...) onlyMinter modifier exactly. Owner is only the role admin and need not hold the role.
getMinters()/getBurners() exist as address[] views on FactoryBurnMintERC20 v1.5.1, identical at v1.6.2. v2 CrossChainToken (AccessControl) lacks them → duck-typing family check rejects it.
TypeScript clean: readTokenRoleHolders union typed correctly, returns checksummed string[]; empty set decodes to [] (not BAD_DATA); mintamount via validateUint256; @throws complete.
Live Sepolia Proofs (real v1.5.1 FactoryBurnMintERC20):
getMinters / getBurners: Accurate checksummed role sets, revoked members correctly absent
mint v2 rejection: ✅ CCTContractTypeInvalidError (family check)
mint(recipient, 1000) as role-holder: SUCCESS, balance 0 → 1000
Overlap:getErc20Token and readTokenRole are defined by both unmerged branches → whichever merges first, the second conflicts on those two functions.
Why it happened: Both branches are splitting the mint/burn-role feature (writes in 11352, reads+mint in 11353) and independently re-implementing the shared foundation layer.
Resolution Options:
Stack them: Merge DAPP-11352 first → rebase DAPP-11353 onto cct-sdk (post-11352), removing the duplicate getErc20Token and readTokenRole definitions.
Extract base PR: Create a base/token-contracts-helpers PR with just getErc20Token, readTokenRole, readTokenRoleHolders, readTokenOwner, assertTokenOwner. Land it first, then rebase both 11352 and 11353 onto it (removes the helpers from both).
Coordinate merge: Ensure merge order is deliberate — document in commit message which branch depends on the other.
Recommendation: Option 1 (stack) is lowest friction: merge 11352 (writes), then rebase/merge 11353 (reads+mint) on top. Avoids creating a third PR for the extracted helpers.
Action: Coordinate with the author of DAPP-11352 (@apedrob). Decide merge order before either lands.
[COMMENT 2/4] 🟡 Medium (DX) — isMinter/isBurner not exposed in SDK
Problem: The getMinters/getBurners JSDoc recommends single-address checks via isMinter(address)/"one call instead of an unbounded set plus client scan". However, isMinter/isBurner are not exposed in the SDK facade — they only exist internally as part of readTokenRole.
This creates an asymmetry:
Heavy read (getMinters/getBurners) is exposed and documented
Light read (isMinter/isBurner) is recommended but hidden
Impact: A developer following the recommendation must either:
Drop to raw ethers and call the token contract directly, or
Use readTokenRole which is internal (not a public API)
Fix Options:
Expose the reads: Add thin SDK facades isMinter() and isBurner() (simple wrappers over readTokenRole) to EVMTokenManager, matching the v1.5.1/v1.6.2 contract interface.
Reword the docs: If single-address checks are intentionally not an SDK responsibility, clarify in getMinters/getBurners remarks that isMinter(address) is a raw contract call the SDK doesn't wrap, with an example ethers snippet.
Recommendation: Option 1 (expose) is better DX — keeps the recommendation internal to the SDK without requiring raw contract knowledge.
Problem: The repo convention (established in other CCT families) is to document cross-family counterparts via @remarks and @see links. This PR adds three reads with no cross-family context:
mint has no note mentioning the Solana counterpart mintTokens (different name, different result shape)
getMinters/getBurners have no note that these are EVM-only (Solana uses the SPL authority model, not readable role sets)
No @see links connecting the seeding workflow: deployToken → grant role → mint → check role set
Examples of the pattern elsewhere:
Token pool ops link cross-family equivalent (e.g., "Solana: createTokenPool")
Reads note why a counterpart doesn't exist ("EVM-only because...")
Fix: Add to facades in index.ts:
On mint: Add @remarks noting Solana has mintTokens (different builder pattern, direct to account not intermediate role gate)
On getMinters/getBurners: Add @remarks noting EVM-only (Solana uses SPL authority events, not enumerable role sets)
[COMMENT 4/4] 🔵 Nit — Op-level Mint.execute@throws thinner than facade
Problem: The Mint op class's execute method @throws is minimal:
/** * Signs and submits as a minter... * @throws {@link CCIPWalletInvalidError} if `wallet` is not a valid signer * @throws {@link CCTParamsInvalidError} if `sender` is given and is not the wallet's address... */overrideasyncexecute(...)
But the facade method EVMTokenManager.mint has much fuller documentation:
/** * ... * @throws {@link CCIPWalletInvalidError} if `wallet` is not a valid signer * @throws {@link CCTContractTypeInvalidError} if `tokenAddress` is not a BurnMintERC677 token * @throws {@link CCTParamsInvalidError} if any param is invalid... * @throws {@link CCIPExecTxRevertedError} if the tx reverts on-chain * @throws {@link CCTTxFailedError} if submission fails before broadcast * @throws {@link CCTTxNotConfirmedError} if it is not confirmed in time */mint(opts: EVMExecuteParams<MintParams>): Promise<TransactionResult>{returnthis.#mint.execute(this.chain,opts)}
The op class is missing the family check (CCTContractTypeInvalidError), on-chain revert (CCIPExecTxRevertedError), and submission errors (CCTTxFailedError, CCTTxNotConfirmedError).
Fix: Either:
Mirror the facade @throws onto the op class, or
Add a JSDoc note on the op class directing readers to the facade for the full error contract
Recommendation: Option 1 (mirror). The op class is the source of truth; the facade should reference it or both should be in sync.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
mintand the two role reads for B&M tokens (1.5.1/1.6.2):generateUnsignedMintandmint+getMintersandgetBurnersisMinterandisBurnerqueriesWhy
Testing