Full lesson
HOLD-BACK
Holdback — keyless Solana vault for construction retention money: 95/5 split, partial defect freezes, sellable claims, permissionless release. Rust + Anchor, devnet.
What it does
From the project README:
[](https://github.com/facei7505-droid/HOLD-BACK/actions/workflows/ci.yml) [](LICENSE) [](https://explorer.solana.com/address/F3qhQqGxVpjDPndPx4KhwoAdvxbmUchQotYFe8zWxARt?cluster=devnet) [](https://www.anchor-lang.com) [](https://colosseum.org)
- Original
- facei7505-droid/HOLD-BACK
- SuperStack fork
- Blockchains/HOLD-BACK @
bce8e72 - Stars
- 0
- Last push (original)
- 2026-10-03
- Languages
- HTML, TypeScript, JavaScript, Rust, Python, Shell
- Detected stack
- Anchorweb3.js
- Categories
- DeFiInfrastructure & Tooling
- Licence
- MIT
- Homepage
- https://holdback-gamma.vercel.app
Architecture
13 source files. By extension: .js ×8, .ts ×3, .rs ×1, .py ×1.
| Top-level directory | Source files |
|---|---|
media | 4 |
tests | 3 |
app | 3 |
site | 1 |
programs | 1 |
deck | 1 |
On-chain programs: programs/holdback
Dapp: devnet deploy pending
⏳ Devnet deploy pending — goes live when the devnet wallet is topped up. This fork's own dapp is not deployed yet, so there is no program address or transaction to show. It is queued in dapp-queue.txt; once devnet SOL is available it is deployed, exercised with real devnet transactions, and this section switches to the live dapp at /dapps/hold-back/. Until then, the lesson and step-by-step guide below are complete, and you can run it locally with the commands below.
Key code, explained
Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.
programs/holdback/src/lib.rs L301–324 @ bce8e72 · MIT · original authority: authority.clone(), }; let ctx = match signer { Some(s) => CpiContext::new_with_signer(token_program.to_account_info(), accounts, s), None => CpiContext::new(token_program.to_account_info(), accounts), }; token_interface::transfer_checked(ctx, amount, decimals)} /// Token-2022 mints with fee, hook, delegate, pause or similar extensions can/// make the vault pay out less than it recorded or block a payout entirely./// Only plain mints (and metadata-only extensions) are accepted.fn check_mint_extensions(mint: &AccountInfo) -> Result<()> { if *mint.owner != anchor_spl::token_2022::ID { return Ok(()); } let data = mint.try_borrow_data()?; let state = StateWithExtensions::<MintState>::unpack(&data).map_err(|_| error!(HoldbackError::UnsafeMint))?; for ext in state.get_extension_types().map_err(|_| error!(HoldbackError::UnsafeMint))? { match ext { ExtensionType::MetadataPointer | ExtensionType::TokenMetadata => {} _ => return err!(HoldbackError::UnsafeMint), } }- Line 304
Some(s) => CpiContext::new_with_signer(token_program.to_account_info(), accounts, s),: Makes a CPI signed by a PDA. The signer seeds prove the program controls that address. - Line 305
None => CpiContext::new(token_program.to_account_info(), accounts),: Makes a cross-program invocation into another program. - Line 307
token_interface::transfer_checked(ctx, amount, decimals): A checked token transfer, which also verifies the mint and decimals. - Line 314
if *mint.owner != anchor_spl::token_2022::ID {: Targets the Token-2022 program instead of the original Token Program. - Line 322
_ => return err!(HoldbackError::UnsafeMint),: An explicit validation that aborts the instruction with an error.
app/devnet-client.js L1–24 @ bce8e72 · MIT · original// Browser client for the Holdback program on Solana devnet, signed with Phantom.// Bundled into site/devnet.js by `npm run build:site`. It exposes the same// api(path, body) shape as the in-page simulation, so the demo UI is shared.//// The connected Phantom wallet is the developer and pays every fee and rent.// The other roles (subcontractor, arbiter, funder, stranger) are throwaway// keypairs created in the browser: they hold no SOL and only co-sign.import { AnchorProvider, BN, Program } from "@coral-xyz/anchor";import { Connection, Keypair, PublicKey, SystemProgram, Transaction, VersionedTransaction, LAMPORTS_PER_SOL,} from "@solana/web3.js";import { TOKEN_2022_PROGRAM_ID, getMintLen, getAssociatedTokenAddressSync, createInitializeMint2Instruction, createAssociatedTokenAccountIdempotentInstruction, createMintToInstruction,} from "@solana/spl-token";import idl from "../target/idl/holdback.json"; const RPC = "https://api.devnet.solana.com";const PROGRAM_ID = new PublicKey(idl.address);const TP = TOKEN_2022_PROGRAM_ID;const DEC = 100; // test USDC with 2 decimals, same as the testsconst WARRANTY_SECS = 45;const ARBITER_WINDOW_SECS = 60; // after this, an unsettled defect no longer blocks releaseconst TITLE = "Turan Residences, electrical, block B";- Line 13
TOKEN_2022_PROGRAM_ID, getMintLen, getAssociatedTokenAddressSync,: Targets the Token-2022 program instead of the original Token Program. - Line 14
createInitializeMint2Instruction, createAssociatedTokenAccountIdempotentInstruction, creat: Mints new tokens. The mint authority must sign.
How to run, build and test
These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.
| Directory | Command | Runs |
|---|---|---|
. | npm run test | ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts |
. | anchor build | compile programs and generate IDLs |
. | anchor test | local validator + test suite |
. | anchor run test | npx ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts |
. | cargo build | Rust workspace build |
. | cargo test | Rust tests |
What you could build from it
- Fork the SuperStack copy and extend it within the DeFi gaps listed on the idea page.
- Learn the pattern first: Program Derived Addresses (PDAs)
- Learn the pattern first: Cross-Program Invocations (CPIs)
- Learn the pattern first: SPL Tokens: mints, accounts and transfers