Skip to content

OpenZeppelin/openzeppelin-sui-payments

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Warning

This is experimental UN-AUDITED code currently under development

openzeppelin-sui-payments

Closed-loop stablecoin payments + loyalty + redemption template for Sui, built on the Permissioned Asset Standard (PAS) with role-based access control from openzeppelin/contracts-sui.

Overview

A merchant deploys this template to accept stablecoin payments, automatically mint a soulbound loyalty currency (LOYALTY) on each settlement, and let customers redeem that loyalty for goods later — all on-chain, with PAS handling the balance/policy layer.

Two settlement flows, mirroring real-world POS. The Merchant shared object is the hub: it stores open invoices, open vouchers, and settlement receipts in tables and owns both flows.

  • Invoice → Pay — merchant issues an invoice via merchant::create_invoice (cap-gated) carrying line items and the snapshotted loyalty reward; it's stored in the Merchant and surfaced by ID (off-chain QR). Customer scans, sends stablecoin via PAS through merchant::pay, earns LOYALTY balance, and a Receipt is recorded in the Merchant. For open-loop settlement with a plain (non-PAS) Coin<C>, merchant::pay_with_coin transfers the coin directly to the payout address; same loyalty + receipt outcome.
  • Voucher → Redeem — customer locks LOYALTY balance in a voucher via merchant::create_voucher (stored in the Merchant, surfaced by ID for the QR); merchant scans + merchant::redeems, the balance burns, and a Receipt is recorded.

Both invoices and vouchers carry the same Item type (variant_id + quantity + snapshot unit_price), so the on-chain accounting is symmetric. Receipts use a generic Receipt<T> with a flow-specific payload — Receipt<Payment> and Receipt<Redemption> — stored in the Merchant in separate invoice_receipts / voucher_receipts tables keyed by the settling invoice/voucher ID; per-customer history is served off-chain from the InvoicePaid / VoucherRedeemed event stream.

Access control uses a single AccessControl<MERCHANT> registry with three operational roles:

  • MerchantRole — payout address, mint config, display name
  • CatalogManagerRole — listings + variants CRUD + active toggle
  • CashierRole — invoice issuance + voucher redemption

The deployer is the root holder and grants operational roles separately, so cold-storage admin keys stay out of daily POS operations.

Repository Layout

contracts/
├── payments/         # The template (8 modules + 5 test files)
└── stablecoin-mock/  # Testnet/local-only mock PAS stablecoin (for end-to-end tests)

Both packages resolve @pas/pas and @openzeppelin-move/* via MVR — no vendored deps. Builds require --build-env testnet (or mainnet) so MVR knows which network to resolve against.

Security

This project is maintained by OpenZeppelin with the goal of providing a secure and reliable starter dApp for PoS systems built on top of the Sui ecosystem.

Refer to SECURITY.md for more details.

About

Closed-loop stablecoin payments and loyalty dApp template on Sui (Permissioned Asset Standard). Reference implementation: Joe's Coffee.

Resources

License

Code of conduct

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages