diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index c4191820..ef1337c7 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -95,6 +95,13 @@ Prefer explicit, typed storage keys (positional `*Key` structs) for dynamic fields over ad-hoc primitive keys - they document intent and prevent key collisions across features in the same object. +## Asset custody & balances + +For fungible-asset custody, prefer Sui **Address Balances** - an account-level balance +model that eliminates coin selection, merges deposits automatically, and enables +stateless transaction construction and direct gas payment. See the +[Sui asset-custody docs](https://docs.sui.io/onchain-finance/asset-custody/address-balances/). + ## Upgrade safety This is a library: downstream packages depend on published bytecode that cannot diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7632965e..baba4b2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,6 +55,19 @@ same rules: Examples are the integration-facing source of truth for AI agents and downstream integrators, the same way doc-comments are the source of truth for the generated API reference. +- When you add or change a public capability, make it discoverable. Surface it + as a keyword in the Highlights cell of its group catalog README (the top-level + `README.md` for its domain group) and make sure it is findable in the package's + own `README.md`. The catalog cell is a teaser and the package README plus + generated docs carry the detail, but the two must stay consistent - keep every + advertised keyword backed by a real, named function in the README, and never + advertise what the code does not expose. A capability that appears in neither is + invisible to integrators and AI agents. +- When you make a notable (user-facing) change to a package, record it in + [`CHANGELOG.md`](./CHANGELOG.md) under `## Unreleased`, grouped by package + (`### openzeppelin_`) and change type (`#### Added` / `Changed` / + `Fixed` / ...), following [Keep a Changelog](https://keepachangelog.com/), and + reference the PR number. - When you add a new package, give it a `README.md` whose `## Learn More` section matches its siblings - including the `llms.txt` discovery bullet, using the absolute diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index 11e12b57..3858e71c 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -12,6 +12,8 @@ These conventions target **Move 2024** (module label syntax, receiver syntax, `#[error(code = N)]`, macros). Every package in this repo declares `edition = "2024"`. +Based on the [Sui dev cheat sheet](https://docs.sui.io/getting-started/dev-cheat-sheet). + ## Naming - **Error constants**: `EPascalCase`, declared with `#[error(code = N)]`, type @@ -192,7 +194,7 @@ Examples of required rewrites: ## Collections & object size - Objects max 250 KB - transactions abort if exceeded -- Use `vector` / `VecSet` / `VecMap` only for bounded collections ≤ 1000 items +- Use `vector` / `VecSet` / `VecMap` / `PriorityQueue` only for bounded collections ≤ 1000 items - Use `Table` / `Bag` / `ObjectBag` / `ObjectTable` / `LinkedTable` for large or unbounded collections - Never put ever-growing vectors inside objects diff --git a/contracts/README.md b/contracts/README.md index 04a52780..e1f09ffa 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -10,8 +10,8 @@ OpenZeppelin building blocks for Sui smart contracts development. | Package | MVR | Move package | Docs | Highlights | |---------|----------|--------------|------|-----------| -| [`allowance/`](allowance/) | [`@openzeppelin-move/allowance`](https://www.moveregistry.com/package/@openzeppelin-move/allowance) | `openzeppelin_allowance` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/allowance) | Capability-keyed, multi-coin spending allowances: an owner funds a shared vault and grants capped, optionally expiring, revocable spend rights that delegates draw on demand. See [`allowance/examples/spend_vault/`](allowance/examples/spend_vault) for integration examples. | -| [`access/`](access/) | [`@openzeppelin-move/access`](https://www.moveregistry.com/package/@openzeppelin-move/access) | `openzeppelin_access` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/access) | Transfer policies that wrap privileged capabilities and guard ownership handoffs (two-step approvals and time-locked transfers). See [`access/examples/`](access/examples) for integration examples. | +| [`allowance/`](allowance/) | [`@openzeppelin-move/allowance`](https://www.moveregistry.com/package/@openzeppelin-move/allowance) | `openzeppelin_allowance` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/allowance) | Capability-keyed, multi-coin spending allowances: an owner funds a shared vault and grants capped, optionally expiring, revocable spend rights that delegates draw on demand, with on-chain queryable allowance state. See [`allowance/examples/spend_vault/`](allowance/examples/spend_vault) for integration examples. | +| [`access/`](access/) | [`@openzeppelin-move/access`](https://www.moveregistry.com/package/@openzeppelin-move/access) | `openzeppelin_access` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/access) | Role-based access control, plus transfer policies that guard ownership handoffs (two-step approvals and time-locked transfers). See [`access/examples/`](access/examples) for integration examples. | | [`finance/`](finance/) | [`@openzeppelin-move/finance`](https://www.moveregistry.com/package/@openzeppelin-move/finance) | `openzeppelin_finance` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/finance) | Vesting wallet that locks a coin for a beneficiary and releases it on a schedule, with a built-in linear (and stepped/tranche) curve and a curve-agnostic core for custom schedules. See [`finance/examples/vesting_wallet/`](finance/examples/vesting_wallet) for integration examples. | -| [`timelock/`](timelock/) | [`@openzeppelin-move/timelock`](https://www.moveregistry.com/package/@openzeppelin-move/timelock) | `openzeppelin_timelock` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/timelock) | A delayed-operation controller (a Sui-native `TimelockController`): schedule a privileged operation, enforce a mandatory on-chain delay, then execute it - with typed on-chain params and a structural canonical-timelock binding via `OperationCap`. See [`timelock/examples/timelock/`](timelock/examples/timelock) for integration examples. | +| [`timelock/`](timelock/) | [`@openzeppelin-move/timelock`](https://www.moveregistry.com/package/@openzeppelin-move/timelock) | `openzeppelin_timelock` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/timelock) | A delayed-operation controller (a Sui-native `TimelockController`): schedule a privileged operation, enforce a mandatory on-chain delay, then execute it - with typed on-chain params, operation dependency chaining, optional permissionless execution, and a structural canonical-timelock binding via `OperationCap`. See [`timelock/examples/timelock/`](timelock/examples/timelock) for integration examples. | | [`utils/`](utils/) | [`@openzeppelin-move/utils`](https://www.moveregistry.com/package/@openzeppelin-move/utils) | `openzeppelin_utils` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/utils) | Embeddable primitives for everyday module logic, starting with a unified rate-limiter (token bucket, fixed window, cooldown). See [`utils/examples/rate_limiter/`](utils/examples/rate_limiter) for integration examples. | diff --git a/contracts/allowance/README.md b/contracts/allowance/README.md index 8bd05217..fe1d8c22 100644 --- a/contracts/allowance/README.md +++ b/contracts/allowance/README.md @@ -47,8 +47,9 @@ One shared `Vault` holds N coin types at once. Funds are not a struct field: eac 1. **Create and fund** - `new` returns the `Vault` and its `OwnerCap` by value; `deposit` (or a raw address-balance top-up) funds the pool; `share` makes the vault usable. Compose all of this in one PTB before `share`. 2. **Grant** - `mint_cap` returns a bare `SpenderCap`; `set_allowance` creates or overwrites the `(cap, coin)` budget. `0` suspends (keeps the cap), `u64::MAX` means unlimited / no expiry, and an optional CAS guard makes read-then-write races safe. 3. **Spend** - the cap holder calls `spend` for exactly `amount`, receiving a `Balance` to route onward. Spending is cap-gated, never sender-gated. -4. **Manage** - the owner raises, lowers, or suspends a live grant in place with `set_allowance` (the cap object is never invalidated), ends one coin with `revoke`, or kills an entire cap with `revoke_all`. A spender can self-revoke with `renounce`. -5. **Exit and teardown** - the owner withdraws funds at any time with `withdraw` / `withdraw_all`, then `destroy`s the drained vault. Owner exit is never blocked by spender state. +4. **Inspect** - read allowance state on-chain without mutating: `allowance` (the configured budget), `spendable_now` (an advisory upper bound on what a spend may allow right now, after expiry and the pool balance - not a guarantee, since the pool can be short at spend time under same-checkpoint contention; see [Security Notes](#security-notes)), `expiry`, `contains`, and `balance_value` (the pooled balance of a coin type). +5. **Manage** - the owner raises, lowers, or suspends a live grant in place with `set_allowance` (the cap object is never invalidated), ends one coin with `revoke`, or kills an entire cap with `revoke_all`. A spender can self-revoke with `renounce`. +6. **Exit and teardown** - the owner withdraws funds at any time with `withdraw` / `withdraw_all`, then `destroy`s the drained vault. Owner exit is never blocked by spender state. ### Usage diff --git a/contracts/timelock/README.md b/contracts/timelock/README.md index ddd4f95f..c5d75f28 100644 --- a/contracts/timelock/README.md +++ b/contracts/timelock/README.md @@ -15,7 +15,7 @@ openzeppelin_timelock = { r.mvr = "@openzeppelin-move/timelock" } | Module | Summary | |--------|---------| -| `timelock` | Hash-keyed operation timelock: a shared `Timelock` with typed on-chain params, `OperationCap`-bound entries (structural canonical-timelock binding), typed `ExecutionTicket` execution, a configurable delay + expiry window, and self-administered configuration. | +| `timelock` | Hash-keyed operation timelock: a shared `Timelock` with typed on-chain params, `OperationCap`-bound entries (structural canonical-timelock binding), typed `ExecutionTicket` execution, predecessor-based operation chaining, optional permissionless (open-executor) execution, a configurable delay + expiry window, and self-administered configuration. | --- diff --git a/llms.txt b/llms.txt index 478a2367..95af872b 100644 --- a/llms.txt +++ b/llms.txt @@ -9,7 +9,9 @@ follow the links to the sources of truth. ## Start here +- [README.md](https://raw.githubusercontent.com/OpenZeppelin/contracts-sui/main/README.md): overview, install, and the pinned Sui CLI version - [ARCHITECTURE.md](https://raw.githubusercontent.com/OpenZeppelin/contracts-sui/main/ARCHITECTURE.md): why the library is shaped this way and how to compose it +- [STYLEGUIDE.md](https://raw.githubusercontent.com/OpenZeppelin/contracts-sui/main/STYLEGUIDE.md): the Sui/Move coding conventions used in this repo, built on the [Sui dev cheat sheet](https://docs.sui.io/getting-started/dev-cheat-sheet) - [contracts/](https://raw.githubusercontent.com/OpenZeppelin/contracts-sui/main/contracts/README.md) and [math/](https://raw.githubusercontent.com/OpenZeppelin/contracts-sui/main/math/README.md): the package catalogs - browse for the available packages, their MVR slugs, paths, and docs diff --git a/math/README.md b/math/README.md index 57422869..207115fa 100644 --- a/math/README.md +++ b/math/README.md @@ -8,5 +8,5 @@ Math primitives for Sui DeFi, implemented as pure functions (no on-chain storage | Package | MVR | Move package | Docs | Highlights | |---------|----------|--------------|------|-----------| -| [`core/`](core/) | [`@openzeppelin-move/integer-math`](https://www.moveregistry.com/package/@openzeppelin-move/integer-math) | `openzeppelin_math` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/math) | Overflow-safe unsigned integer arithmetic with configurable rounding. See [`core/examples/`](core/examples) for integration examples. | -| [`fixed_point/`](fixed_point/) | [`@openzeppelin-move/fixed-point-math`](https://www.moveregistry.com/package/@openzeppelin-move/fixed-point-math) | `openzeppelin_fp_math` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/fixed-point) | Fixed-point decimal types (`UD30x9`, `SD29x9`) with 9 decimals; arithmetic and comparison ops, the standard-normal CDF (`cdf`), plus bitwise helpers on `UD30x9`. See [`fixed_point/examples/`](fixed_point/examples) for integration examples. | +| [`core/`](core/) | [`@openzeppelin-move/integer-math`](https://www.moveregistry.com/package/@openzeppelin-move/integer-math) | `openzeppelin_math` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/math) | Overflow-safe unsigned integer arithmetic with configurable rounding, decimal scaling, and vector utilities. See [`core/examples/`](core/examples) for integration examples. | +| [`fixed_point/`](fixed_point/) | [`@openzeppelin-move/fixed-point-math`](https://www.moveregistry.com/package/@openzeppelin-move/fixed-point-math) | `openzeppelin_fp_math` | [docs](https://docs.openzeppelin.com/contracts-sui/1.x/fixed-point) | Fixed-point decimal types (`UD30x9`, `SD29x9`) with 9 decimals: arithmetic, rounding, comparison, conversions/casts, logarithms, and standard-normal Gaussian functions; plus bitwise helpers on `UD30x9`. See [`fixed_point/examples/`](fixed_point/examples) for integration examples. | diff --git a/math/fixed_point/README.md b/math/fixed_point/README.md index db37bfae..327b7f07 100644 --- a/math/fixed_point/README.md +++ b/math/fixed_point/README.md @@ -17,6 +17,8 @@ openzeppelin_fp_math = { r.mvr = "@openzeppelin-move/fixed-point-math" } ## Operations - Arithmetic: `add`, `sub`, `mul`, `mul_trunc`, `mul_away`, `div`, `div_trunc`, `div_away`, `pow`, `unchecked_add`, `unchecked_sub`, `mod`, `sqrt` +- Rounding: `ceil`, `floor` (round to whole units) +- `SD29x9` also exposes sign and truncated-remainder helpers: `abs`, `negate`, `rem` - Logarithms: `log2`, `ln`, `log10` - Distributions: `cdf` (standard-normal CDF `Φ`), `pdf` (standard-normal PDF `φ`), `inverse_cdf` (standard-normal quantile `Φ⁻¹`) - Comparison: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `is_zero`