Packages

Sale

The example code snippets used in this guide are experimental and have not been audited. They simply help exemplify usage of the OpenZeppelin Sui Package.

The openzeppelin_sale package runs a fixed-price token sale (presale / IDO) against a fixed, pre-deposited inventory. The issuer funds the sale with a Balance<SaleCoin> up front; buyers pay a PaymentCoin during a time window and each receives a non-transferable Receipt. After the window the sale resolves one of two ways: finalize (success - buyers claim their tokens, the issuer withdraws proceeds) or cancel (failure - buyers recover their payment from an escrow vault). Use it for capped public rounds, anti-whale public rounds, and compliance-gated strategic rounds.

Pricing is not baked in. The sale is generic over a witness-gated curve that computes each buyer's allocation; a built-in fixed-rate curve (allocation = paid * rate) covers the common case, and the seam is open for custom curves. The sale never holds a TreasuryCap - it only ever routes the inventory and payments deposited into it.

This is the prefunded flavor (prefunded_sale), which draws from a fixed inventory and never mints. A future minting flavor (holding a TreasuryCap<SaleCoin>) is a separate type sharing the same Receipt and lifecycle, and is out of scope for this package.

Usage

There are two ways to pull the package into your project. Pick whichever fits how much you want to own the code.

Git dependency

Add the dependency in Move.toml, pinned to a git revision:

[dependencies]
openzeppelin_sale = { git = "https://github.com/OpenZeppelin/contracts-sui.git", subdir = "contracts/sale", rev = "v1.5.0" }

The sale's vesting path depends on openzeppelin_finance; Move resolves it transitively, so you do not need to add it yourself unless you also use it directly.

Copy the source

Alternatively, copy the module sources under contracts/sale/sources/ directly into your package's sources/ (renaming the module addresses to your own package). You then fully own the code - free to trim, fork, or swap the pricing curve - at the cost of tracking upstream fixes yourself. If you keep the optional vesting path, copy the openzeppelin_finance vesting sources alongside it.

Import

Once the package is available, import the modules you need:

use openzeppelin_sale::prefunded_sale;
use openzeppelin_sale::fixed_rate_curve;

Modules

The guide covers all five modules of the package. Most integrators touch only prefunded_sale and fixed_rate_curve; the other three are supporting types you will see in signatures:

ModuleWhat it is
prefunded_saleThe sale itself: setup, purchase, close, and redeem. Also home to the Phase lifecycle enum. Start here.
fixed_rate_curveThe built-in pricing curve, allocation = paid * rate, fixed for the whole sale. Most sales use this.
refund_vaultA generic refundable escrow over Balance<P>. Every sale is paired with one; on cancel it pays buyers back individually. Usable standalone.
allowlistA typed compliance slot (AllowlistAdmin + single-use AllowEntry). Ships no KYC logic - you wire your own scheme against these types.
receiptThe non-transferable, buyer-bound claim ticket minted by purchase and consumed by claim / refund.

Choosing a sale shape

A fixed-price sale is configured along four orthogonal, independent axes: a required hard cap (maximum raise), an optional soft cap (minimum raise to finalize), an optional per-buyer cap, and an optional allowlist (compliance gating). The three shapes they typically combine into:

ShapeKYCSoft capPer-buyer capTypical use
Public roundnononoOpen public sale, first-come-first-served
Capped public roundnooptionalyesAnti-whale public sale
Strategic roundyesyesyesCompliance-gated raise

This primitive is not a bonding curve, LBP, auction (Dutch / English / sealed-bid), or fair launch - those have different mechanics and belong in separate standards.

Next steps

  • Prefunded Sale for the full module guide: lifecycle, pricing, compliance, vesting, key concepts, and security notes.
  • Sale API reference for function signatures, events, and errors across all modules.
  • Finance for the vesting wallet behind claim_into_vesting.
  • Access for role-based authorization to hold the SaleAdminCap and AllowlistAdmin in a recoverable container.