Skip to content
 
 

Repository files navigation

k256 pWrap

CI

pWrap is the k256-maintained fork of the Solana Program Token Wrap implementation. It converts an existing SPL Token or Token-2022 mint into a deterministic wrapped representation backed by on-chain escrow.

Deployment identity

Item Value
pWrap program ID pWrapnbzNPTx9aZPAp3gpxAUrs3H4QQ1GHWMPMbDba2
Devnet Live; slot 484920383; authority G1kdS4CCCKZFKzupAm9N5ZLMvx5bgfzpUx9xkmt1KxYR
Mainnet Live; slot 440055335; authority EDJwdLWCgUdFMdcxqXNYjvB9EvF6qkAwcwYdwzjgU4TC
Testnet Not deployed
ProgramData, each cluster DJ7bADfr6LxWQsyzRGJXRwieXB4CmkRioTLpMoPvMhW1
Deployed ELF 436,360 bytes; SHA-256 fb64746885e19cd5a8a1f4f40c8a6dfff8183cc3d8e30b40a120a1d4dee7eb49
K256 fork https://github.com/quiknode-labs/token-wrap
Upstream https://github.com/solana-program/token-wrap
Upstream baseline 81adb66daa1405eb1568af8b74f5c30924655bd6
IDL idl.json

pWrapnbzNPTx9aZPAp3gpxAUrs3H4QQ1GHWMPMbDba2 is the permanent address on both deployed clusters. The matching program-account keypair was used once per cluster for the initial deployment. Every later upgrade targets the literal public address and never replaces it. Program and ProgramData accounts are cluster-local even though their deterministic addresses are the same.

The Devnet program deployment is recorded in DEVNET_DEPLOYMENT.md. The Mainnet deployment is recorded in MAINNET_DEPLOYMENT.md. No K256 Mainnet asset mapping was initialized. Deployment nevertheless makes the permissionless CreateMint instruction available to third parties; the program has no on-chain asset allowlist or global pause.

The upstream TwRapQCDhWkZRrDaHfZGuHxkZ91gHDRkyuzNqeU5MgR address is not used by pWrap. Changing the program ID changes every program-derived wrapped mint, authority, backpointer, canonical pointer, and escrow address.

The program-account and upgrade-authority keypairs are operator key material. They must stay outside this public repository. The program-account keypair is retained as durable identity material, but it cannot recreate a closed program; it is not the fee payer or upgrade authority and is not used for upgrades.

Permanent deployed identities

All Rust, IDL, JavaScript, CLI, and PDA derivations remain pinned to the pWrap address above. The supported lifecycle is the completed initial deployment on each live cluster followed only by upgrades of that same address. A replacement program ID is not a pWrap upgrade.

The program must remain upgradeable, so neither deployment with --final nor removal of the upgrade authority is allowed. Any solana program close operation targeting the pWrap Program or ProgramData accounts is forbidden. CloseStuckEscrow is unrelated: it can close only a zero-balance token escrow ATA after validating the documented stuck-escrow conditions; it cannot close the program.

The upgradeable loader does not provide a permission that allows upgrades while cryptographically forbidding closure. A raw upgrade-authority signer can technically upgrade, rotate, finalize, or close the program. Until that authority is transferred to a governance controller that enforces a narrower policy, “never close” is a key-custody and operator invariant. Authority loss makes future upgrades impossible; compromise exposes the program-controlled escrow and issuance logic.

Provenance and security status

This fork deliberately starts from the latest upstream main, not the older released program snapshot:

  • latest upstream program release: program@v1.0.0 at 4e4e1d0 (2025-09-11);
  • latest audit listed by upstream: Runtime Verification at 228dc97 (2025-10-30);
  • fork baseline: 81adb66 (2026-08-17).

Upstream added SetCanonicalPointer and upgraded core Solana dependencies after the latest listed audit. The pWrap program-ID change also produces a distinct binary. The historical audits are useful lineage, not an audit of the current pWrap binary. Mainnet deployment does not make the binary audited and does not authorize K256 support for any Mainnet asset.

The latest Runtime Verification report leaves acknowledged findings around freeze-authority coordination, loss of an underlying confidential auditor policy, transparent wrap amounts, and partial metadata synchronization. pWrap also remains permissionless and upgradeable. The current existing-asset plan does not claim those general risks are fixed.

Protocol model

pWrap keeps one deterministic relationship between an unwrapped mint and a wrapped mint for a selected token program:

  1. CreateMint creates the wrapped mint and its backpointer PDA.
  2. Wrap transfers unwrapped tokens into the escrow ATA and mints the backed wrapped amount.
  3. Unwrap burns wrapped tokens and atomically releases the same underlying amount from escrow.
  4. CloseStuckEscrow closes a zero-balance escrow whose account extensions no longer match a recreated mint.
  5. SyncMetadataToToken2022 copies supported metadata into a wrapped Token-2022 mint.
  6. SyncMetadataToSplToken copies supported metadata into the wrapped SPL Token mint's Metaplex account.
  7. SetCanonicalPointer lets an unwrapped mint authority publish its preferred Token Wrap deployment.

The wrapped mint, mint authority, backpointer, canonical pointer, and escrow addresses are program-derived. Users retain ownership of their token accounts. The wrapper controls escrow release and wrapped issuance through its deployed code, so the program upgrade authority is a real economic authority and must be governed accordingly.

Confidential Transfer policy

When the wrapped mint uses Token-2022, the default mint customizer initializes:

  • ConfidentialTransferMint with automatic account approval;
  • no confidential-transfer authority;
  • no auditor;
  • MetadataPointer controlled by the wrapped-mint authority PDA;
  • decimals and the current freeze-authority address copied once from the unwrapped mint at W creation; later U/W authority changes are not synchronized.

pWrap itself implements public wrap and unwrap. Configure-account, deposit, confidential transfer, apply-pending-balance, and withdraw are Token-2022 operations and use the relevant proof programs. Moving into or out of pWrap escrow is public; the wrapper does not make the boundary transaction confidential.

K256 tests only exact underlying mints that already exist independently of K256. K256 must not create an underlying mint for product or lifecycle testing. Official Circle test USDC on Devnet, mint 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU, is the first selected asset; its pWrap relationship and lifecycle are not yet created or proven. No official Solana Devnet USDT mint has been verified, and native SOL requires a separate canonical-WSOL decision. The permissionless program has no on-chain asset allowlist, so this is a K256 operating contract rather than a restriction on third-party invocation. See DEVNET_EXISTING_ASSET_TEST.md.

Build and test

Required toolchains are pinned in the repository:

  • Rust 1.93.1 (rust-toolchain.toml);
  • Rust nightly nightly-2026-01-22 for the repository test/lint gates (Makefile);
  • Solana CLI 4.1.0 (Cargo.toml workspace metadata and Makefile);
  • pnpm 10.15.1 (package.json).
pnpm install --frozen-lockfile
pnpm generate:clients
cargo check --workspace --all-targets --locked
make build-sbf-program
make build-sbf-program-test-metadata-owner
make build-sbf-program-test-transfer-hook
make test-program
cargo test -p spl-token-wrap-cli --bin spl-token-wrap
cargo test -p spl-token-wrap-cli --test runner
pnpm --dir clients/js test
pnpm --dir clients/js build

pnpm generate:clients regenerates idl.json and the JavaScript client from program/idl.ts. The generated client packages retain their upstream-compatible names but are marked private in this fork; no K256 package publication contract exists yet.

Unlike the upstream snapshot, the generated contract and CLI both expose SetCanonicalPointer. The JavaScript test is no longer a no-op: it verifies the pWrap identity, all seven discriminators, the instruction/account codecs, and a canonical-pointer PDA against an independent Solana CLI derivation.

CLI dry runs fail closed: a simulation error returns a nonzero exit and includes the RPC simulation logs instead of producing a success-shaped transaction result.

For Devnet operations, see DEPLOYMENT.md. For Mainnet upgrades, see MAINNET_RUNBOOK.md. The immutable deployment records are DEVNET_DEPLOYMENT.md and MAINNET_DEPLOYMENT.md.

Upstream maintenance

The local checkout uses origin for the k256 fork and upstream for the Solana Program repository. Review upstream changes before merging them; program behavior, IDL, generated clients, audits, and the pWrap address must remain one coherent release.

git fetch upstream --tags
git log --oneline --left-right main...upstream/main
git merge upstream/main

After every upstream merge, restore and verify the pWrap program ID, regenerate clients, run the full checks above, and produce a new binary hash and security review scope. Any deployment is a separately approved upgrade of the existing address on one explicitly selected cluster.

Upstream audit lineage

Auditor Date Upstream version Report
Zellic 2025-05-16 75c5529 PDF
Runtime Verification 2025-06-11 dd71fc1 PDF
Runtime Verification 2025-10-30 228dc97 PDF

License

Apache License 2.0. See LICENSE. Upstream history and attribution are preserved by the GitHub fork.

About

k256 pWrap — maintained Token Wrap program and clients

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages