Skip to content

fix(token-2022/metadata/anchor): revive program excluded from CI due to stale spl-token-metadata-interface version - #642

Open
NikkiAung wants to merge 3 commits into
solana-foundation:mainfrom
NikkiAung:fix/token2022-metadata-anchor-deps
Open

fix(token-2022/metadata/anchor): revive program excluded from CI due to stale spl-token-metadata-interface version#642
NikkiAung wants to merge 3 commits into
solana-foundation:mainfrom
NikkiAung:fix/token2022-metadata-anchor-deps

Conversation

@NikkiAung

Copy link
Copy Markdown
Contributor

Summary

tokens/token-2022/metadata/anchor has been excluded from CI with the comment "build failed - program outdated" since anchor-spl was upgraded to 1.x. This PR fixes the root cause and re-enables the program in CI.

Root cause

The program directly pinned two SPL interface crates at 2023-era versions:

spl-token-metadata-interface = "0.3.3"   # stale
spl-type-length-value        = "0.4.3"   # stale

while anchor-spl = "1.0.2" (resolves to 1.1.2) already transitively pulls spl-token-metadata-interface 0.8.0 and spl-type-length-value 0.9.1. Cargo ended up with two incompatible versions of both crates in the dependency tree. The older chain brought in a stale solana-program that conflicted with the solana-zk-token-sdk compile unit, causing the build to fail with unresolved symbol errors.

Fix

Align the direct pins to the versions anchor-spl already resolves:

- spl-token-metadata-interface = "0.3.3"
+ spl-token-metadata-interface = "0.8.0"
- spl-type-length-value = "0.4.3"
+ spl-type-length-value = "0.9.1"

Three minor call-site API fixes to match the newer crate versions:

  • initialize.rs: replace removed DEFAULT_LAMPORTS_PER_BYTE_YEAR / DEFAULT_EXEMPTION_THRESHOLD rent constants with Rent::get()?.minimum_balance() (already the pattern used by update_field.rs in the same program)
  • update_field.rs, update_authority.rs: rename struct field token_program_idprogram_id in TokenMetadataUpdateField / TokenMetadataUpdateAuthority (field was renamed in anchor-spl 1.1.x)

No account structures, instruction logic, or TypeScript test code required changes.

Verification

  • cargo tree -i spl-token-metadata-interface now shows a single v0.8.0 (no more v0.3.4)
  • anchor build succeeds locally
  • All 7 existing tests pass locally

Test plan

  • CI anchor.yml matrix picks up tokens/token-2022/metadata/anchor (no longer in .ghaignore) and goes green
  • anchor build succeeds
  • All 7 tests in tests/metadata.ts pass (initialize mint w/ metadata, update field, update with custom field, remove custom field, change update authority, emit metadata × 2)

🤖 Generated with Claude Code

@NikkiAung
NikkiAung requested a review from dev-jodee as a code owner July 24, 2026 01:40
@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown

Greptile Summary

The PR restores the Token-2022 metadata Anchor example to CI by aligning SPL interface dependencies, adapting renamed CPI account fields, and correcting incremental metadata rent funding.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failures remain in the reviewed fix.

Important Files Changed

Filename Overview
.github/.ghaignore Re-enables CI discovery for the repaired Anchor example.
tokens/token-2022/metadata/anchor/programs/metadata/Cargo.toml Aligns direct SPL interface dependencies with the versions used by anchor-spl.
tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/initialize.rs Funds only the incremental rent required for the metadata TLV bytes using the runtime rent sysvar, completing the prior rent-overhead fix.
tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_authority.rs Adapts the update-authority CPI accounts to the renamed program_id field.
tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_field.rs Adapts the update-field CPI accounts to the renamed program_id field.
tokens/token-2022/metadata/anchor/package.json Adds explicit Node typings and updates TypeScript tooling for the re-enabled project.
tokens/token-2022/metadata/anchor/pnpm-lock.yaml Locks the updated TypeScript and Node type dependencies used by CI.
tokens/token-2022/metadata/anchor/tsconfig.json Updates the TypeScript target, libraries, and type environment for current tooling.

Reviews (4): Last reviewed commit: "fix(#642): pin @types/node to ^22.x and ..." | Re-trigger Greptile

// Calculate lamports required for the additional metadata
let lamports =
data_len as u64 * DEFAULT_LAMPORTS_PER_BYTE_YEAR * DEFAULT_EXEMPTION_THRESHOLD as u64;
let lamports = Rent::get()?.minimum_balance(data_len);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Double-charged rent overhead

When initialization runs, Anchor has already rent-funded the mint, but minimum_balance(data_len) includes the fixed account-storage overhead again even though data_len contains only the added metadata TLV bytes, causing every payer to lock excess lamports in the mint.

Knowledge Base Used: Tokens Directory Overview

@NikkiAung

Copy link
Copy Markdown
Contributor Author

Good catch by @greptile-apps — addressed in 2b81753.

minimum_balance(data_len) prices (128 + data_len) bytes, but the mint's base 128-byte account overhead is already funded by Anchor's init constraint. That caused the payer to lock ~890,880 extra lamports (≈0.0009 SOL) per mint.

Fixed by computing only the incremental rent for the extension bytes:

let rent = Rent::get()?;
let lamports = rent.minimum_balance(data_len).saturating_sub(rent.minimum_balance(0));

All 7 tests still pass locally.

@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown

The fix is correct. minimum_balance(data_len) - minimum_balance(0) is the standard pattern for computing incremental rent on Token-2022 extensions — it isolates the cost of the variable-length metadata bytes without re-pricing the 128-byte base account that Anchor's init already covers.

One small thing worth verifying: saturating_sub silently clamps to zero if minimum_balance(data_len) < minimum_balance(0), which can't happen in practice since minimum_balance is monotonically increasing, but it's the right defensive choice here. The pattern is correct.

LGTM on the fix.

NikkiAung and others added 2 commits July 24, 2026 17:18
…d fix API drift

The program pinned spl-token-metadata-interface = "0.3.3" and
spl-type-length-value = "0.4.3", while anchor-spl = "1.0.2" transitively
resolves to 0.8.0 / 0.9.1 respectively. Cargo ended up with two
incompatible spl-token-metadata-interface versions in the dependency tree,
pulling in an older solana-program chain that conflicted with the
solana-zk-token-sdk compile unit, causing the build to fail.

Fix: align the two direct pins to the versions anchor-spl already uses:
  spl-token-metadata-interface 0.3.3 → 0.8.0
  spl-type-length-value        0.4.3 → 0.9.1

Three minor API-drift call-sites also updated:
  - initialize.rs: replace removed DEFAULT_LAMPORTS_PER_BYTE_YEAR /
    DEFAULT_EXEMPTION_THRESHOLD constants with Rent::get()?.minimum_balance()
  - update_field.rs, update_authority.rs: rename struct field
    token_program_id → program_id in TokenMetadataUpdateField /
    TokenMetadataUpdateAuthority (field was renamed in anchor-spl 1.1.x)

All 7 existing tests pass locally. Removes the entry from .ghaignore so
the program is picked up by CI anchor.yml again.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…in initialize

minimum_balance(data_len) prices (128 + data_len) bytes, but the mint's
base 128-byte account overhead is already funded by Anchor's `init`.
Use minimum_balance(data_len) - minimum_balance(0) to charge only for
the incremental metadata extension bytes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@NikkiAung
NikkiAung force-pushed the fix/token2022-metadata-anchor-deps branch from 2b81753 to ac19c16 Compare July 25, 2026 00:28
…fig for token-2022/metadata/anchor

@types/node@20.x has Buffer interface incompatible with TypeScript 5.x causing
tsc --noEmit to fail in CI. Pinning @types/node to ^22.19.1 resolves this.
Also bumps typescript to ^5.5.0, adds skipLibCheck, and updates target/lib to
es2020 to match current project requirements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant