Skip to content

Gated mint program#456

Merged
metapileks merged 149 commits into
developfrom
pileks/met-339-private-token
Jun 10, 2026
Merged

Gated mint program#456
metapileks merged 149 commits into
developfrom
pileks/met-339-private-token

Conversation

@pileks

@pileks pileks commented May 1, 2026

Copy link
Copy Markdown
Contributor

Introduces gated_mint, a new program that gates an SPL Mint behind an admin-managed whitelist by holding the mint's freeze authority. Whitelisted users move tokens through gated_invoke, which thaws relevant token accounts before a CPI into a whitelisted target program and re-freezes them after. Couples into v08_launchpad: any base mint with a freeze authority must point it at the deterministic gated_mint_config PDA.

The gated_mint_config PDA stores two authorities: a privileged admin (set once at init, controls everything) and an optional whitelist_admin (a delegated role that can only add whitelisted users). The admin can rotate or clear the whitelist_admin at any time.

Instructions

Instruction Role
initialize_gated_mint Moves the mint's freeze authority into the gated_mint_config PDA (seed ["gated_mint_config", mint]) via set_authority CPI; stores per-mint admin and an optional whitelist_admin (must differ from admin).
add_whitelisted_user Callable by either admin or the configured whitelist_admin; creates a WhitelistedUser PDA at ["whitelisted_user", mint, user].
set_whitelist_admin Admin-only; sets, rotates, or clears the optional whitelist_admin on gated_mint_config. New value must differ from admin. Blocked once gating_disabled is true.
gated_invoke Whitelisted-user-only; for each mint token account in remaining_accounts, thaws if frozen, runs invoke on target_program (must be in WHITELISTED_PROGRAMS, must not be gated_mint::ID), then re-freezes any account left in Initialized state.
disable_gating Admin-only one-way switch; blocks gated_invoke, add_whitelisted_user, and set_whitelist_admin, unlocks permissionless thaw_account.
thaw_account Permissionless unwind path callable only after disable_gating; thaws a single token account of the gated mint.

Other Changes

  • v08_launchpad::initialize_launch now requires that, if base_mint.freeze_authority is set, it equals the canonical gated_mint_config PDA derived from base_mint. This is a pure on-chain find_program_address check, no CPI into gated_mint. Mints without a freeze authority continue to work unchanged.
  • SDK: new @metadaoproject/programs/gated_mint (v0.1) module with GatedMintClient, PDA helpers, and generated types; re-exported from the package root.
  • Tests: unit tests for each gated_mint instruction (including set_whitelist_admin coverage and whitelist_admin-signed paths in add_whitelisted_user) plus tests/integration/gatedLaunchpadV8.test.ts exercising the full lifecycle: init gated mint → init/start/fund/settle launchpad_v8 launch → claim (frozen ATAs thawed and re-frozen via gated_invoke) → disable gating → permissionless thaw_account.

pileks and others added 30 commits January 8, 2026 22:34
…e proposal has already passed but not been finalized yet
…AOproject/programs into pileks/met-5-optimistic-governance
@pileks pileks changed the title Pileks/met 339 private token Gated mint program May 5, 2026
@pileks pileks requested a review from metaproph3t May 5, 2026 17:23
@pileks pileks self-assigned this May 5, 2026
@pileks pileks changed the base branch from pileks/launchpad-v8 to develop May 6, 2026 16:15
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Repository Guard

  • Cargo.lock: pass
  • yarn.lock (root): pass
  • yarn.lock (sdk): pass
  • Repo guard: pass

Repository Guard

Cargo dependency pinning

  • Status: pass
  • Every programs/*/Cargo.toml dep uses =x.y.z, a path = .. workspace ref, or a git dep with a 40-char rev.

Cross-program Anchor/Solana version consistency

  • Status: pass
  • anchor-lang and anchor-spl are pinned to the version declared in repo-guard.toml across every program.

solana-program crate pin

  • Status: pass
  • Every solana-program = "=X" declaration is =1.17.14 (locked to match Cargo.lock).

Anchor.toml solana_version

  • Status: pass
  • Anchor.toml declares solana_version = "1.17.34" (local-dev install for anchor test).

Crate minimum age

  • Status: pass
  • All Cargo deps changed by this PR are at least 14 days old on crates.io.

Yarn package.json pinning

  • Status: pass
  • All package.json deps use exact versions (no ^, ~, ranges).

npm minimum age

  • Status: pass
  • All npm deps changed by this PR are at least 14 days old.

Workflow toolchain consistency

  • Status: pass
  • Every workflow declares anchor-version: 0.29.0.
  • Per-file solana-cli-version values match [toolchain.workflow_solana_cli] in repo-guard.toml.

GitHub Action SHA pinning

  • Status: pass
  • Every third-party action is pinned to a SHA in [actions.sha_allowlist].

Sensitive program / config changes

  • Status: warn
  • Review hint only (CODEOWNERS is the merge gate). Lines below match heuristics for security-sensitive changes:
  • High-sensitivity files touched: Anchor.toml, Cargo.lock
  • Anchor.toml:12 Hardcoded Solana address literal; Anchor [programs.*] entry change -> +gated_mint = "GaTEjZy6eMdHg2BcL8dk3iE78jkJ9sPtyw1q2tMNi8PA"
  • programs/gated_mint/src/constants.rs:5 Hardcoded Solana address literal -> + pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
  • programs/gated_mint/src/constants.rs:6 Hardcoded Solana address literal -> + pubkey!("FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq"),
  • programs/gated_mint/src/constants.rs:7 Hardcoded Solana address literal -> + pubkey!("moonDJUoHteKkGATejA5bdJVwJ6V6Dg74gyqyJTx73n"),
  • programs/gated_mint/src/constants.rs:8 Hardcoded Solana address literal -> + pubkey!("VLTX1ishMBbcX3rdBWGssxawAo1Q2X2qxYFYqiGodVg"),
  • programs/gated_mint/src/constants.rs:9 Hardcoded Solana address literal -> + pubkey!("WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx"),
  • programs/gated_mint/src/constants.rs:10 Hardcoded Solana address literal -> + pubkey!("gvnr27cVeyW3AVf3acL7VCJ5WjGAphytnsgcK1feHyH"),
  • programs/gated_mint/src/constants.rs:11 Hardcoded Solana address literal -> + pubkey!("cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"),
  • programs/gated_mint/src/error.rs:3 #[error_code] enum modification -> +#[error_code]
  • programs/gated_mint/src/instructions/gated_invoke.rs:95 Program ID constant or variable change -> + program_id: ctx.accounts.target_program.key(),
  • programs/gated_mint/src/lib.rs:29 declare_id! literal change; Hardcoded Solana address literal -> +declare_id!("GaTEjZy6eMdHg2BcL8dk3iE78jkJ9sPtyw1q2tMNi8PA");
  • sdk/src/constants.ts:63 Hardcoded Solana address literal -> + "GaTEjZy6eMdHg2BcL8dk3iE78jkJ9sPtyw1q2tMNi8PA",
  • tests/integration/gatedLaunchpadV8.test.ts:46 Hardcoded Solana address literal -> + new PublicKey("4mPQ4VuvvtYL3CeMPt14Uj1CLpBWcVdJoLoTH9ea4Kod"),
  • tests/integration/gatedLaunchpadV8.test.ts:351 Hardcoded Solana address literal -> + new PublicKey("cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"),
  • tests/integration/gatedLaunchpadV8.test.ts:355 Hardcoded Solana address literal -> + new PublicKey("cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"),

Overall status: pass

Lockfile freshness (Cargo.lock + yarn.lock) is checked by the workflow directly and cannot be bypassed. The sensitive-diff section is a review hint - CODEOWNERS handles the actual merge gate.

@metapileks metapileks merged commit f0aabc7 into develop Jun 10, 2026
4 checks passed
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.

2 participants