| Attack Vector | Protection | Status |
|---|---|---|
| Account Data Matching Substituting fake accounts to bypass checks |
All accounts validated via Anchor constraints โ seeds, bump, token::mint, token::authority. No raw unchecked deserialization. | PASS |
| Arbitrary CPI Calling malicious programs via user-supplied IDs |
All CPIs target token_program validated by Anchor's Interface<TokenInterface>. No user-supplied program IDs. | PASS |
| Authority Transfer Inability to rotate admin/owner keys |
Two-step transfer_ownership + accept_ownership pattern with pending_owner. Prevents accidental or malicious transfers. | PASS |
| Bump Seed Canonicalization Using non-canonical bumps to create rogue PDAs |
All PDAs use Anchor seeds + bump constraints which enforce canonical bumps automatically. | PASS |
| Closing Accounts Improperly closed accounts being reinitialized |
abandon_ghost uses Anchor's close = signer โ handles lamport transfer, data zeroing, and closed discriminator automatically. | PASS |
| Duplicate Mutable Accounts Passing same account twice to mutate unexpectedly |
No instructions accept two mutable accounts of the same type where duplication could cause harm. | PASS |
| Insecure Initialization Frontrunning program setup to seize control |
initialize_ghost uses PDA seeds tied to signer.key() โ one ghost per wallet, deterministic, cannot be frontrun. | PASS |
| Missing Signer Check Executing privileged operations without authorization |
All privileged operations require Signer<'info>. Owner operations validated via constraint = ghost.owner == signer.key(). | PASS |
| Missing Ownership Check Accepting accounts owned by wrong program |
All accounts use Anchor's Account<'info, T> or InterfaceAccount<'info, T> which validate program ownership automatically. | PASS |
| Overflow / Underflow Integer arithmetic exceeding type bounds |
All arithmetic uses checked_mul, checked_div, checked_sub, saturating_sub. Fee calculation uses unwrap_or(0) as safe fallback. | PASS |
| PDA Sharing Same PDA used across different authority domains |
Distinct PDA seeds: ghost ["ghost", owner], vault ["vault", owner], stake ["stake_vault", owner]. No overlap. | PASS |
| Type Cosplay Misrepresenting one account type as another |
Anchor's 8-byte discriminator on Account<'info, GhostAccount> prevents type confusion during deserialization. | PASS |
| Unsafe Rust Memory-unsafe code bypassing Rust's guarantees |
Zero unsafe blocks in the entire program. No raw pointer dereferences or mutable statics. | PASS |
| Scenario | What Happens | Assets Safe? |
|---|---|---|
| Website goes down | Use any Solana wallet + CLI tool to interact with the program directly. Your vault, ghost, and beneficiaries are all on-chain and unchanged. | YES |
| Executor bot goes offline | Your ghost stays in its current state (alive/awakened). No assets move. Anyone can run an executor or trigger execution manually when they come back online. | YES |
| Ghost Protocol team disappears | The on-chain program continues to run indefinitely. All functions remain callable by anyone. The program is deployed and immutable unless the upgrade authority acts. | YES |
| You lose access to your wallet | If you set up guardian wallets, they can withdraw your vault assets. Without guardians, assets remain locked in the vault โ same as losing any crypto wallet. | DEPENDS |
| Solana network goes down | No transactions can be processed on any Solana dApp. Once the network resumes, your ghost, vault, and all on-chain state are exactly as you left them. Nothing is lost. | YES |
solana config set --url https://api.mainnet-beta.solana.com
const { PublicKey } = require("@solana/web3.js");
const PROGRAM = new PublicKey("3Es13GXc4qwttE6uSgAAfi1zvBD3qzLkZpY21KfT3sZ3");
const WALLET = new PublicKey("YOUR_WALLET_ADDRESS");
const [ghostPda] = PublicKey.findProgramAddressSync(
[Buffer.from("ghost"), WALLET.toBytes()], PROGRAM
);
const [vaultPda] = PublicKey.findProgramAddressSync(
[Buffer.from("vault"), WALLET.toBytes()], PROGRAM
);
console.log("Ghost:", ghostPda.toBase58());
console.log("Vault:", vaultPda.toBase58());
spl-token accounts --owner VAULT_PDA_ADDRESS
withdraw_from_vault โ pull assets from vault (owner only, ghost must be alive)
abandon_ghost โ close ghost, burn 50% stake, return 50% + vault assets
check_silence โ awaken an overdue ghost (permissionless, earns 5% bounty)
execute_legacy โ mark ghost as executed after grace period (permissionless)
execute_transfer โ distribute assets to beneficiaries (permissionless)
All instructions can be called via Anchor CLI, @solana/web3.js, or any
Solana-compatible tool. The program ID and account layouts are public.