Skip to content

token-fundraiser: no teardown for a failed campaign (vault + fundraiser rent stranded) #725

Description

@MarkFeder

Summary

The token-fundraiser example has no teardown path for a failed campaign (one that expires without meeting its target). This affects both implementations:

Details

The program exposes four instructions — initialize, contribute, check_contributions (the anchor checker), and refund — and only tears down accounts on the success path:

  • Success: check_contributions requires vault.amount >= amount_to_raise, transfers the full vault.amount to the maker, and closes the vault + fundraiser. Any tokens sent directly into the vault are swept to the maker here, so nothing is stranded on this path.
  • Failure: once a campaign expires under target, contributors call refund, which returns each contributor's recorded amount and closes only that contributor's record. There is no instruction that closes the vault or the fundraiser account, so:
    • the vault ATA and fundraiser PDA are left behind with their rent unrecovered, and
    • any tokens transferred directly into the vault (not via contribute, so not part of any recorded contribution) stay permanently locked.

This gap is inherited from the reference implementation — the anchor version has the same four instructions and no failed-campaign teardown — so it is not specific to the pinocchio port.

Why not just gate on the vault balance

Switching check_contributions back to releasing based on the raw vault balance is not the fix: because anyone can transfer into a standard ATA, that would let a stranger force-release a campaign that never met its target (and block legitimate refunds). That is a more serious issue than stranded rent, so both implementations intentionally gate release on the recorded total.

Proposed follow-up

Add a maker-callable teardown instruction for a failed campaign — allowed once the duration has elapsed and the target was not met — that sweeps any remaining vault balance back to the maker and closes the vault + fundraiser accounts, recovering their rent. To keep the examples in parity, this should be applied to both the anchor and pinocchio implementations together rather than diverging one.

Context

Raised during review of #708: #708 (comment)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions