Sol.College

Full lesson

susu-monorepo

Open-source Solana primitive for rotating savings circles (ROSCAs). Dynamic-collateral curve, audit-target, no fees / no yield / no company keys.

What it does

From the project README:

Every assertion in the hero above is one click from its verifier. If a link 404s, the markdown-link-check workflow blocks the merge.
Original
tantshirt/susu-monorepo
SuperStack fork
Blockchains/susu-monorepo @ 0995354
Stars
0
Last push (original)
2026-07-16
Languages
TypeScript, JavaScript, Rust, Shell, HTML, CSS
Detected stack
@solana/kitAnchorNext.jsweb3.js
Categories
DeFi
Licence
MIT

Architecture

237 source files. By extension: .ts ×108, .tsx ×69, .rs ×59, .js ×1.

Top-level directorySource files
apps115
sdk61
programs35
examples12
crates11
(root)1
scripts1
tests1

On-chain programs: programs/susu

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/susu-monorepo/. 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.

tantshirt/susu-monorepo · programs/susu/src/instructions/withdraw_collateral.rs L61–84 @ 0995354 · MIT · original
    require!(        amount == posted,        SusuError::ContributionAmountMismatch    );     let decimals = ctx.accounts.mint.decimals;    let creator = group.creator;    let gid = group.group_id.to_le_bytes();    let bump_val = group.bump;    let seed_slice: &[&[u8]] = &[        GROUP_SEED,        creator.as_ref(),        &gid,        &[bump_val],    ];    let signer: &[&[&[u8]]] = &[seed_slice];     #[rustfmt::skip]    token::transfer_checked(        CpiContext::new_with_signer(            ctx.accounts.token_program.key(),            TransferChecked {                from: ctx.accounts.vault.to_account_info(),                mint: ctx.accounts.mint.to_account_info(),
  1. Line 61 require!(: An explicit validation that aborts the instruction with an error.
  2. Line 69 let bump_val = group.bump;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 79 token::transfer_checked(: A checked token transfer, which also verifies the mint and decimals.
  4. Line 79 token::transfer_checked(: An SPL token transfer through the Token Program.
  5. Line 80 CpiContext::new_with_signer(: Makes a CPI signed by a PDA. The signer seeds prove the program controls that address.
tantshirt/susu-monorepo · programs/susu/src/instructions/top_up_collateral.rs L61–84 @ 0995354 · MIT · original
     let member_position = &mut ctx.accounts.member_position;    let new_total = member_position        .collateral_posted        .checked_add(amount)        .ok_or(SusuError::CurveOverflow)?;    if new_total < new_required {        return err!(SusuError::InsufficientCollateral);    }     if amount > 0 {        let cpi_accounts = Transfer {            from: ctx.accounts.member_token_account.to_account_info(),            to: ctx.accounts.vault.to_account_info(),            authority: ctx.accounts.member.to_account_info(),        };        let cpi_ctx = CpiContext::new(ctx.accounts.token_program.key(), cpi_accounts);        token::transfer(cpi_ctx, amount)?; // member -> vault (collateral)    }     member_position.collateral_posted = new_total;     msg!(        "collateral_topped_up: member={} additional={} new_total={}",
  1. Line 65 .checked_add(amount): Uses checked arithmetic so overflow fails instead of wrapping.
  2. Line 68 return err!(SusuError::InsufficientCollateral);: An explicit validation that aborts the instruction with an error.
  3. Line 77 let cpi_ctx = CpiContext::new(ctx.accounts.token_program.key(), cpi_accounts);: Makes a cross-program invocation into another program.
  4. Line 78 token::transfer(cpi_ctx, amount)?; // member -> vault (collateral): An SPL token transfer through the Token Program.
  5. Line 83 msg!(: Logs to the program log, which is visible in explorers and the test output.
tantshirt/susu-monorepo · programs/susu/src/instructions/post_collateral.rs L97–120 @ 0995354 · MIT · original
        ctx.accounts.group.contribution_amount,        ctx.accounts.mint.decimals,    )?;     let new_total = mp        .collateral_posted        .checked_add(amount)        .ok_or(SusuError::CurveOverflow)?;    require!(new_total >= required, SusuError::InsufficientCollateral);     let decimals = ctx.accounts.mint.decimals;    if amount > 0 {        #[rustfmt::skip]        token::transfer_checked(            CpiContext::new(                ctx.accounts.token_program.key(),                TransferChecked {                    from: ctx.accounts.member_token_account.to_account_info(),                    mint: ctx.accounts.mint.to_account_info(),                    to: ctx.accounts.vault.to_account_info(),                    authority: ctx.accounts.member.to_account_info(),                },            ),            amount,
  1. Line 103 .checked_add(amount): Uses checked arithmetic so overflow fails instead of wrapping.
  2. Line 105 require!(new_total >= required, SusuError::InsufficientCollateral);: An explicit validation that aborts the instruction with an error.
  3. Line 110 token::transfer_checked(: A checked token transfer, which also verifies the mint and decimals.
  4. Line 110 token::transfer_checked(: An SPL token transfer through the Token Program.
  5. Line 111 CpiContext::new(: Makes a cross-program invocation into another program.
tantshirt/susu-monorepo · programs/susu/src/instructions/claim_payout.rs L73–96 @ 0995354 · MIT · original
        rotation_index,    )?;    assert_rotation_closed(ctx.accounts.clock.unix_timestamp, close_timestamp)?;    verify_rotation_funded(        ctx.accounts.group.key(),        group,        rotation_index,        ctx.remaining_accounts,    )?;     let amount = calculate_payout_amount(group.n, group.contribution_amount)?;    let decimals = ctx.accounts.mint.decimals;    let creator = group.creator;    let gid = group.group_id.to_le_bytes();    let bump_val = group.bump;    let seed_slice: &[&[u8]] = &[GROUP_SEED, creator.as_ref(), &gid, &[bump_val]];    let signer: &[&[&[u8]]] = &[seed_slice];     #[rustfmt::skip]    token::transfer_checked(        CpiContext::new_with_signer(            ctx.accounts.token_program.key(),            TransferChecked {                from: ctx.accounts.vault.to_account_info(),
  1. Line 75 assert_rotation_closed(ctx.accounts.clock.unix_timestamp, close_timestamp)?;: Reads on-chain time from the Clock sysvar.
  2. Line 87 let bump_val = group.bump;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 92 token::transfer_checked(: A checked token transfer, which also verifies the mint and decimals.
  4. Line 92 token::transfer_checked(: An SPL token transfer through the Token Program.
  5. Line 93 CpiContext::new_with_signer(: Makes a CPI signed by a PDA. The signer seeds prove the program controls that address.

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.

DirectoryCommandRuns
.npm run testfind tests/atdd -name '*.static.red.test.mjs' -print0 | xargs -0 node --test
sdk/tsnpm run buildtsc -p tsconfig.json
sdk/tsnpm run testvitest run
examples/with-token-extensionsnpm run starttsx src/index.ts
examples/with-token-extensionsnpm run buildtsc -p tsconfig.json
examples/with-token-extensionsnpm run testvitest run --exclude dist/**
examples/with-privynpm run starttsx src/index.ts
examples/with-privynpm run buildtsc -p tsconfig.json
examples/with-privynpm run testvitest run tests --exclude dist/**
examples/with-squadsnpm run startpnpm --filter @susu/sdk build && tsx src/index.ts
examples/with-squadsnpm run buildpnpm --filter @susu/sdk build && tsc -p tsconfig.json
examples/with-squadsnpm run testpnpm --filter @susu/sdk build && vitest run --dir tests
apps/referencenpm run devnext dev
apps/referencenpm run startnext start
apps/referencenpm run buildnext build
apps/referencenpm run linteslint

What you could build from it