Developer overview
blast_presale is a standalone Sui Move package for presales. It mints a new coin’s full supply, takes commitments in a quote coin, settles, and migrates the liquidity into a full-range Cetus or Bluefin pool. A sale overflows by default, filling every wallet at one rate, or holds commitments to its raise, first come, first served, under a hard cap. It shares the Blast ACL and partner registry with Blast’s bonding-curve launchpad, but no sale state or launch logic.
The participant and team pages call migration launch.
Every step is a public Move call, and most are permissionless: anyone can settle, migrate, claim for a participant, collect fees, or cancel a stalled sale. This guide shows how to build those calls from your own app, keeper, or indexer.
Source and references
Section titled “Source and references”- Source:
sui/presaleinblast-v2-contracts. Source and tests are authoritative; this site explains them. - Integrator reference generated from source:
llms/presale.txt. It lists every public function, type, event, and abort code, and is written to be handed to an AI agent. - Design records: ADR 0099 and its amendments in the decision index.
Modules
Section titled “Modules”| Module | Role |
|---|---|
blast_presale |
The Presale object: creation, commitments, settlement, claims, cancellation. |
cetus, bluefin |
Venue adapters: create a sale for that venue, migrate it, collect its fees. |
presale_vault |
The Vault that holds a migrated sale’s LP position, or a team’s own locked position, and splits its fees. |
holder_rewards |
Merkle reward rounds funded from a vault’s holder share. |
fee_policy |
Blast’s fee rates and payout destination. |
creation_policy |
Allowlists checked at creation: quote types, migrators, partners. |
blast_presale_domain |
Presale roles used with the shared Blast ACL. |
package_admin |
Holds the dependency-only UpgradeCap. |
venue_config |
The shared VenueConfig: Cetus pool-creation caps and each sale’s pool tier. |
bps, merkle_tree, migration_math |
Helpers. |
Objects
Section titled “Objects”| Object | Ownership | Purpose |
|---|---|---|
Presale<SaleToken, Quote> |
Shared, one per sale | Holds commitments, the minted supply, and the terms until migration or refund. key only, so it must be shared in the transaction that creates it. |
PresaleCap |
Owned by the creator | Claims migration residuals; can be destroyed after a cancellation. Cannot change terms or move funds. |
Vault<Meme, Quote> |
Shared, one per migrated sale or locked position | Holds the Bluefin position or the Cetus LP-burn proof, residuals, and the holder-reward share. |
Round<Meme, Quote> |
Shared, one per reward round | A published holder-reward Merkle root and its budget. |
Vesting<T> |
Shared, one per vested payout | An irrevocable linear schedule from the external blast_fun_vesting package. |
FeePolicy, CreationPolicy, VenueConfig, PackageAdmin |
Shared singletons | Created once at deployment. Administration uses the existing shared Blast ACL. |
The venue modules and the vault call the sale coin Meme. It is the same type as SaleToken.
Lifecycle
Section titled “Lifecycle”Creation runs in one transaction: a venue’s new returns a PresaleInitializer, setters record the terms, and finalize returns the Pending sale and its PresaleCap. See Create a sale.
Pending → Open → Funded → MigratedOpen → Cancelled (settle, total below the raise)Funded → Cancelled (cancel_unlaunched, from the LP deadline)| State | Allows |
|---|---|
Pending |
Exists only inside the creation transaction, between finalize and share: Blast’s set_protocol_fees, then share. |
Open |
Before start_ms: Blast’s set_protocol_fees. Commits from start_ms until end_ms. settle from end_ms, or earlier once the raise is full under a hard cap that closes the sale when filled. |
Funded |
Migration at any time. cancel_unlaunched from end_ms + liquidity_window_ms, where end_ms is the close after an early close. |
Migrated |
claim for tokens plus overflow refund. |
Cancelled |
claim for a full refund. destroy_cap. |
Once the liquidity deadline passes, migration and cancellation race, and whichever lands first wins.
Authority
Section titled “Authority”Blast operators use a blast_acl::AdminCap granted the required presale role. In the same transaction, blast_acl::sign_in<Role>(acl, admin_cap) returns an AdminWitness<Role>; pass it by reference to the admin call. Roles come from blast_presale_domain, and a role from another package does not authorize presale calls.
| Role | Can |
|---|---|
FeeAdmin |
Set new-sale rates, change a sale’s rates before start_ms, change vault LP-fee rates, and accept or remove partners for new sales. |
TreasuryAdmin |
Change the fee destination. |
ListingAdmin |
Allow or disallow quote types for new sales and vaults. |
AdapterAdmin |
Allow or disallow migrator witnesses for new sales and vaults. |
RewardsAdmin |
Publish holder-reward rounds and settle their optional gas reserves. |
UpgradeAdmin |
Authorize and commit dependency-only upgrades. |
The creator’s PresaleCap separately claims migration residuals and can be destroyed after a cancellation. It grants no admin role.
Nobody can pause a sale, move commitments, or change its windows, recipients, eligibility, or fee split. The package’s UpgradeCap is sealed for dependency-only upgrades, so presale logic never changes.
Other migrators
Section titled “Other migrators”blast_presale::new, finalize, and migrate are public, so a module in another package can be a migrator with its own sealed witness once Blast’s CreationPolicy allows it, for example a partner’s vendor package under sui/vendors. Its sales follow every sale rule here, but a vendor sale has no Blast vault: no Blast LP fees, no holder-reward rounds, and no residual claims. The newer built-in Aftermath adapter in source creates a vault; see Aftermath (source preview).
The Aftermath DAO-pool vendor follows the same initializer flow: its own new returns the PresaleInitializer, the blast_presale setters configure it, and its own finalize sets a treasury-only fee split, finalizes the sale, binds the Aftermath pool creation, sends the PresaleCap to the partner treasury, and returns the sale for share. Both calls need the vendor’s own AdminCap. The route is documented in llms/presale.txt.
Conventions
Section titled “Conventions”- Rates are basis points out of 10,000, built with
bps::new(value). - Times are Unix milliseconds read from the shared
Clockat0x6. - Amounts are atomic units of each coin.
- Rounding uses largest-remainder apportionment: every atomic unit of supply, raise, and fees lands in exactly one share.
- Errors are Move clever errors that name the module and constant. See Errors.
License
Section titled “License”First-party contract code is under the Business Source License 1.1. Read it before reusing the source.