Skip to content

[N-04] Core Math Audit#363

Merged
ericnordelo merged 17 commits into
release-v1.3from
fix/core-math-N-04
Jun 12, 2026
Merged

[N-04] Core Math Audit#363
ericnordelo merged 17 commits into
release-v1.3from
fix/core-math-N-04

Conversation

@ericnordelo

@ericnordelo ericnordelo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Rationale: inlined median! macro + precompiled wrapper functions

Approach. We benchmarked eight median implementations with sui move test -s csv
(deterministic gas; inputs spanning 100–5000 elements; ascending, reverse-sorted, and
duplicate-heavy patterns), measuring both execution gas and compiled bytecode per call site.

What the benchmarks showed

  • Pivot caching dominates: reading vec[pivot_index] on every comparison was the single
    largest cost; caching it in a local cut the u64 selection ~79%. An index-vector quickselect
    variant only looked competitive because it incidentally did this — compared fairly, plain
    value-based quickselect wins at every width.
  • Widening is the macro's bottleneck: a generic median! that converts to u256 and
    delegates to one function pays the widening on every narrow-width call. Move macros cannot
    dispatch on $Int to width-specific functions (type errors at expansion), so the only way to
    run selection at native width through one generic entry is to inline the whole algorithm in
    the macro and let expansion monomorphize it.
  • Cloning via dereference: *vec copies the whole vector in one instruction (~1 gas/KB) vs
    map_ref!'s per-element loop — worth ~20% end-to-end on its own.

Constraints that shaped the design

A public macro expands in the caller's module, so it may only reference public symbols — it
cannot use private helper macros or the module's private error constant. The empty-input abort
is therefore routed through median_u8, which validates before expanding the macro, preserving
the canonical EMedianOfEmptyVector everywhere. Inlining also removes the need for any engine
function, so every public entry takes an immutable reference — nothing is consumed or mutated.

The trade-off, and why wrappers exist

Each median! call site adds ~750–870 B of compiled bytecode (comparable to the existing
quick_sort! at ~750 B), which counts against Sui's package-size cap. The
median_u8median_u256 wrappers precompile the same expansion once in the library, costing
call sites only a regular function call — measured at identical gas to within a few units.
Users pick per call site; the docs explain the trade-off.

Results

vs the previous implementation (n=1001, normalized gas):

Path Before After Δ
median! u64 91.5k 6.9k −92%
median! u128 95.5k 7.9k −92%
median! u256 103.5k 46.3k −55%
median! u64, sorted input (n=5001) 120.6k 8.0k −93%

Validated by 775 tests including randomized cross-checks against a sorted reference, oracle-free
property tests, and an external consumer package proving cross-package macro expansion and
abort-code behavior.

One notable issue surfaced and fixed along the way: with the algorithm inlined, ~120 macro call
sites in our own test suite exceeded the Move VM's 10 MB package arena
(PACKAGE_ARENA_LIMIT_REACHED) — behavioral coverage now runs through the wrappers, with a
compact per-width macro section (the same guidance downstream test suites should follow).

Summary by CodeRabbit

  • New Features

    • Introduced precompiled vector median wrapper functions for types u8, u16, u32, u64, u128, and u256 with optimized library-level bytecode compilation.
    • Updated median_u256 to accept non-mutating references for improved efficiency.
  • Documentation

    • Enhanced vector documentation with median wrapper function details and performance trade-off information.

0xNeshi and others added 10 commits May 28, 2026 15:30
* feat: add rate limiter implementation

* docs: document invariants

* fix: enforce missing invariants

* test: add more tests

* feat: cooldown supports capacity/used

* ref: assume monotonic Clock

* fix: new_bucket accepts initial tokens (remove new_bucket_with_tokens)

* ref: track cooldown_end instead of last_used

* fix: cooldown used increases by 1 on consume

* ref: use 'available' design instead of 'used'

* ref: inline roll_window

* test: add cooldown_reconfigure_rearms_when_drained_and_deadline_elapsed

* docs: mention operator's responsibility for cooldown_ms

* ref: rename q to steps_to_full in bucket_accrue

* docs: update invariants

* fix: remove capacity + refill_amount assertion in assert_bucket_config

* docs: add missing / update docs

* feat: add variety of errors

* docs: add missing / update docs

* test: remove invariant class mentions

* ref: apply Code Quality Checklist (openzeppelin_utils)

* test: replace cleanup with 'abort EUnreachable' in expected-failure tests

* test: use abort 0 instead of error

* feat: remove 'Ms' suffix from Error names

* docs: error docs don't reference internal variables

* docs: rephrase rate_limiter error messages without internal field names

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update README

* docs: update README

* docs: align invariants.md to be sharing-ready

* docs: improve wording & clarity for invariants.md

* feat: cooldown now decrements available by amount

* test: change abort 0 to 100 (avoids confusing with ERateLimited)

* test: change all destructor patterns into abortions

* docs: invariant rewording

* docs: update format for invariants.md

* docs: update format for invariants.md and add missing invariants

* docs: align invariants format

* docs: update outdated invariant references

* docs: remove rate limiter temp. artifacts

* chore: simplify changelog

* ref: convert assert macros into funs

* docs: document private funs

* test(fix): add proper teardown in happy tests

* ci: add contracts/utils to CI test job dir matrix

* test: add regression tests for bucket_accrue

* fix: bucket_accrue double spend bug

* docs: add empty line before enum variant docs

Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* Revert "docs: add empty line before enum variant docs"

This reverts commit 21a9076.

* feat: inline config validation assertions

* docs: add more info on rate limiter types in README

* docs: add clarifying comments for apparent overflow suspects

* docs: mention library being access control-agnostic

* docs: reword library to module

* feat: add initial_available to all limiter types

* ref: put capacity as first cooldown type field

* ref: use spread op instead of ignoring cooldown_ms field

* docs: show identical API for all types in README

* docs: for fixed window update wording that it resets to full capacity

* fix: reconfigure sets last_refill to now + forbid 0 initial available for cooldown

* docs: remove post-core artifact

* test: add bucket_reconfigure_to_faster_rate_discards_old_subinterval

* docs: add SAFETY before overflow-related comments

* test: verify available always returns up-to-date accrual state

* test: add missing zero-config reconfigure tests

* test: add try_consume_with_zero_amount for all limiter types

* test: add try_consume_of_available_aborts_when_drained

* docs: note that try_consume(0) aborts after available() == 0

* docs: note RateLimiter enum is not upgrade-compatible

Adding variants or fields to a deployed public enum would break BCS
deserialization for integrator objects that already stored the prior
shape. Document this constraint at the module level.

* test: add edge case test cases

* docs: remove llm artifacts

* ref: reorder fileds in new_cooldown

* test: remove Pub.local.toml

* ref: in reconfigure_fixed_window move let now into match

* ref: in reconfigure_bucket move let now into match

* docs: remove mention of reconfigure_cooldown clamping available to 0

* fix: align cooldown clamp behavior on reconfigure

* fix: try_consume updates state only on success

* docs: align

* ref: fixedwindow now shares bucket's internal logic

* ref: update capacity prior to accrual on reconfigure_bucket

* docs: add comment

* Revert "docs: add comment"

This reverts commit ecb0145.

* Revert "ref: update capacity prior to accrual on reconfigure_bucket"

This reverts commit b545b6d.

* ref: Rate Limiter: Reconfiguration via Rich `new_*` Functions (#326)

* impl

* simplify further

* fix: expose last_refill_ms for bucket

* tests: add missing

* docs: update utils README

* docs: fix new_cooldown accepted combos

* feat: project bucket-shaped anchor getters

`last_refill_ms` and `window_start_ms` now take `&Clock` and return the
anchor advanced by every whole interval elapsed since the last commit,
so the snapshot `(anchor, available(clock))` is internally coherent.
`cooldown_end_ms` stays a plain getter — a cooldown deadline does not
evolve with time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: error numbering

* fix: error messages no longer reference private fields

* docs: move EBucketAnchorInFuture comment next to the error

* add spec

* update spec

* tests: add missing invariant tests

* feat: add is_type discriminator getters

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>
* add separate quick_sort implementations for each type

* remove duplicated qsort implementations

* add in-place qsort implementation

* add partition function

* rewrite qsort without recursion

* convert quick_sort to macro

* add comprehensive test cases for qsort

* update qsort documentation

* add review fixes

* remove --trace flag from testing pipeline

* Revert "remove --trace flag from testing pipeline"

This reverts commit 9bf7065.

* split macro module

* inline partition macro

* add median implementation

* add more edge case test cases

* fix fmt

* remove quick_sort duplicate

* feat: add median

* docs: update PR

* Route median through u256 workhorse fun (#325)

* fix: fmt

* fix: apply CR comments

* test: add missing test

* fix: macro

* feat: use quickselect

* feat: improve CHANGELOG

* feat: apply review updates

* feat: update comment

---------

Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
@ericnordelo ericnordelo requested a review from bidzyyys as a code owner June 10, 2026 11:06
Copilot AI review requested due to automatic review settings June 10, 2026 11:06
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3012c095-6839-4bf6-84b9-2bf92dd1943f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/core-math-N-04

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.90%. Comparing base (dc216cb) to head (6442ba3).
⚠️ Report is 1 commits behind head on release-v1.3.

Files with missing lines Patch % Lines
math/core/sources/vector.move 0.00% 29 Missing ⚠️

❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@               Coverage Diff                @@
##           release-v1.3     #363      +/-   ##
================================================
+ Coverage         78.42%   78.90%   +0.47%     
================================================
  Files                23       23              
  Lines              1789     1782       -7     
  Branches            656      640      -16     
================================================
+ Hits               1403     1406       +3     
+ Misses              351      341      -10     
  Partials             35       35              
Flag Coverage Δ
contracts/access 65.40% <0.00%> (ø)
contracts/utils 44.09% <0.00%> (ø)
math/fixed_point 56.59% <0.00%> (+0.93%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements the “[N-04] Core Math Audit” changes by inlining the median! selection algorithm (for gas efficiency) and introducing precompiled, per-width median_u8median_u256 wrappers (to avoid repeated bytecode bloat at call sites). It also expands property-based test coverage around quicksort/median and updates documentation and CI to a newer Sui CLI version.

Changes:

  • Reworked vector::median! to inline native-width quickselect (incl. pivot caching + vector copy via deref) and added median_u8median_u256 wrapper functions.
  • Expanded macro and wrapper test coverage with additional randomized/property tests.
  • Updated documentation and CI configuration (Sui CLI version bump, API docs updates).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
README.md Bumps required Sui CLI version (needs link fix).
.github/workflows/test.yml Updates CI SUI_VERSION to 1.72.5.
math/core/sources/vector.move Inlines median! algorithm and adds median_u8median_u256 wrappers; expands docs.
math/core/tests/macros/median.move Refactors tests to exercise wrappers heavily; adds macro-vs-wrapper cross-checks and additional properties.
math/core/tests/macros/quick_sort.move Adds randomized property test for sort correctness + permutation preservation.
math/core/README.md Updates public API documentation for vector ops (needs macro ! notation fix).
CHANGELOG.md Tweaks unreleased changelog entry for median (should mention new wrappers).
math/core/sources/internal/macros.move Renames MAX_LOG_10MAX_LOG10 and updates log10 helper docs.
math/core/sources/u8.move Adds BIT_WIDTH constant docstring.
math/core/sources/u16.move Adds BIT_WIDTH constant docstring.
math/core/sources/u32.move Adds BIT_WIDTH constant docstring.
math/core/sources/u64.move Adds BIT_WIDTH constant docstring.
math/core/sources/u128.move Adds BIT_WIDTH constant docstring.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
Comment thread math/core/README.md Outdated
Comment thread CHANGELOG.md
Comment thread math/core/sources/vector.move Outdated
Comment thread math/core/sources/vector.move Outdated
Comment thread math/core/sources/vector.move
Comment thread math/core/sources/vector.move
@ericnordelo ericnordelo requested a review from 0xNeshi June 10, 2026 11:49
Copilot AI review requested due to automatic review settings June 12, 2026 09:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread math/core/tests/macros/quick_sort.move
Comment thread math/core/tests/macros/median.move
Comment thread math/core/sources/vector.move
bidzyyys and others added 2 commits June 12, 2026 12:33
…#365)

Post-review follow-ups on the N-04 median work plus a doc-quality sweep of
math/core (move-quality checklist):

- vector: document #### Parameters / #### Returns on the median_u8..median_u256
  wrappers (previously only #### Aborts).
- median tests: add median_u128_even_length_rounding_modes and extend
  median_u128_basics with the 0 & MAX overflow boundary (BTT gap fill).
- macros: add /// docs to EDivideByZero/EZeroModulus and the TEN_POW_* consts;
  fix spurious-bullet continuations in several #### Returns/#### Aborts blocks;
  add #### Generics to inv_mod/mul_mod, #### Aborts to mul_mod/mul_div_inner/
  inv_mod_extended_impl, and name EZeroModulus in inv_mod's #### Aborts.
- u512: add /// docs to the four error constants, HALF_BITS/HALF_MASK, and the
  hi/lo struct fields.
- decimal_scaling: tag example fences as ```move, promote the "Truncation
  Behavior" header to ####, and convert scale_amount's #### Examples to a
  fenced move block.
- decimal_scaling tests: rename "Test Helpers" section to "Test-Only Helpers".

All 753 tests pass with --lint --warnings-are-errors; prettier clean.
Copilot AI review requested due to automatic review settings June 12, 2026 10:39

@bidzyyys bidzyyys left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ericnordelo ericnordelo merged commit a7053f4 into release-v1.3 Jun 12, 2026
15 of 16 checks passed
@ericnordelo ericnordelo deleted the fix/core-math-N-04 branch June 12, 2026 10:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

v.pop_back();
};

let mut sorted = v;
// values directly. This anchors the widening cross-check chain (u8..u128 are compared
// upward, ending at u256), so the whole web rests on a reference that is not quickselect.
if (v.is_empty()) v.push_back(a);
let mut sorted = v;
Comment on lines +295 to +303
// An empty vector has no median. The check delegates to `median_u8`, whose own emptiness
// assertion raises the module's canonical `EMedianOfEmptyVector`: a public macro expands in
// the caller's module, where this module's private error constant is not visible, so the
// abort must come from a public function. Inside `median_u8`, that assertion runs before
// the code inlined from this macro, so the call below always aborts at runtime and can
// never recurse.
if (vec.is_empty()) {
median_u8(&vector[], rounding_mode);
};
0xNeshi added a commit that referenced this pull request Jun 16, 2026
* feat: add assertion (#335)

* feat: update comments (#336)

* [N-03] Access Control Audit (#337)

* feat: update comments

* feat: apply updates

* feat: update bag references

* feat: rename param

* feat: apply review updates

* feat: rollback renmae

* [N-05] Access Control Audit (#338)

* feat: update delay logic

* feat: improve doc comments

* feat: improve events

* feat: apply review updates

* [N-01] Access Control Audit (#339)

* feat: update delay logic

* feat: improve doc comments

* feat: improve events

* feat: apply review update

* feat: apply review updates

* Fix N-04 (Code and Documentation Improvements) (#332)

* Fix N-03 (introduce ELogResultUnrepresentable for UD30x9 log functions) (#341)

* fix: `N-02` exact powers of 10 for `log10` (#344)

* Fix N-02 (exact powers of 10 for log10)

* Apply minor suggestion

* fix: `N-01` raw_log2 precision comment (#333)

* Fix N-01 (Internal Precision Comment Overstates raw_log2 Error Bound)

* Fix raw_log2 precision wording

* feat: add reports (#351)

* feat: update changelog (#353)

* feat: update published information (#355)

* feat: Implement Rate Limiter module (#315)

* feat: add rate limiter implementation

* docs: document invariants

* fix: enforce missing invariants

* test: add more tests

* feat: cooldown supports capacity/used

* ref: assume monotonic Clock

* fix: new_bucket accepts initial tokens (remove new_bucket_with_tokens)

* ref: track cooldown_end instead of last_used

* fix: cooldown used increases by 1 on consume

* ref: use 'available' design instead of 'used'

* ref: inline roll_window

* test: add cooldown_reconfigure_rearms_when_drained_and_deadline_elapsed

* docs: mention operator's responsibility for cooldown_ms

* ref: rename q to steps_to_full in bucket_accrue

* docs: update invariants

* fix: remove capacity + refill_amount assertion in assert_bucket_config

* docs: add missing / update docs

* feat: add variety of errors

* docs: add missing / update docs

* test: remove invariant class mentions

* ref: apply Code Quality Checklist (openzeppelin_utils)

* test: replace cleanup with 'abort EUnreachable' in expected-failure tests

* test: use abort 0 instead of error

* feat: remove 'Ms' suffix from Error names

* docs: error docs don't reference internal variables

* docs: rephrase rate_limiter error messages without internal field names

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update README

* docs: update README

* docs: align invariants.md to be sharing-ready

* docs: improve wording & clarity for invariants.md

* feat: cooldown now decrements available by amount

* test: change abort 0 to 100 (avoids confusing with ERateLimited)

* test: change all destructor patterns into abortions

* docs: invariant rewording

* docs: update format for invariants.md

* docs: update format for invariants.md and add missing invariants

* docs: align invariants format

* docs: update outdated invariant references

* docs: remove rate limiter temp. artifacts

* chore: simplify changelog

* ref: convert assert macros into funs

* docs: document private funs

* test(fix): add proper teardown in happy tests

* ci: add contracts/utils to CI test job dir matrix

* test: add regression tests for bucket_accrue

* fix: bucket_accrue double spend bug

* docs: add empty line before enum variant docs

Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* Revert "docs: add empty line before enum variant docs"

This reverts commit 21a9076.

* feat: inline config validation assertions

* docs: add more info on rate limiter types in README

* docs: add clarifying comments for apparent overflow suspects

* docs: mention library being access control-agnostic

* docs: reword library to module

* feat: add initial_available to all limiter types

* ref: put capacity as first cooldown type field

* ref: use spread op instead of ignoring cooldown_ms field

* docs: show identical API for all types in README

* docs: for fixed window update wording that it resets to full capacity

* fix: reconfigure sets last_refill to now + forbid 0 initial available for cooldown

* docs: remove post-core artifact

* test: add bucket_reconfigure_to_faster_rate_discards_old_subinterval

* docs: add SAFETY before overflow-related comments

* test: verify available always returns up-to-date accrual state

* test: add missing zero-config reconfigure tests

* test: add try_consume_with_zero_amount for all limiter types

* test: add try_consume_of_available_aborts_when_drained

* docs: note that try_consume(0) aborts after available() == 0

* docs: note RateLimiter enum is not upgrade-compatible

Adding variants or fields to a deployed public enum would break BCS
deserialization for integrator objects that already stored the prior
shape. Document this constraint at the module level.

* test: add edge case test cases

* docs: remove llm artifacts

* ref: reorder fileds in new_cooldown

* test: remove Pub.local.toml

* ref: in reconfigure_fixed_window move let now into match

* ref: in reconfigure_bucket move let now into match

* docs: remove mention of reconfigure_cooldown clamping available to 0

* fix: align cooldown clamp behavior on reconfigure

* fix: try_consume updates state only on success

* docs: align

* ref: fixedwindow now shares bucket's internal logic

* ref: update capacity prior to accrual on reconfigure_bucket

* docs: add comment

* Revert "docs: add comment"

This reverts commit ecb0145.

* Revert "ref: update capacity prior to accrual on reconfigure_bucket"

This reverts commit b545b6d.

* ref: Rate Limiter: Reconfiguration via Rich `new_*` Functions (#326)

* impl

* simplify further

* fix: expose last_refill_ms for bucket

* tests: add missing

* docs: update utils README

* docs: fix new_cooldown accepted combos

* feat: project bucket-shaped anchor getters

`last_refill_ms` and `window_start_ms` now take `&Clock` and return the
anchor advanced by every whole interval elapsed since the last commit,
so the snapshot `(anchor, available(clock))` is internally coherent.
`cooldown_end_ms` stays a plain getter — a cooldown deadline does not
evolve with time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: error numbering

* fix: error messages no longer reference private fields

* docs: move EBucketAnchorInFuture comment next to the error

* add spec

* update spec

* tests: add missing invariant tests

* feat: add is_type discriminator getters

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* tests: fix formatting in rate limiter tests (#334)

* feat: [N-01]: try_consume now returns false on amount = 0 (#342)

* feat: try_consume returns false on amount = 0

* test: update

* docs: update readme

* docs: [N-02]: warn against preserving bucket anchor across a rate change (#350)

* docs: warn against preserving bucket anchor across a rate change

Accrual applies the current rate over the entire span since the anchor,
so carrying an old last_refill_ms anchor while changing refill_amount or
refill_interval_ms re-prices elapsed time at the new rate and mints
tokens instantly. Document this constraint in the new_bucket parameter
doc and the module-level Reconfiguration section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: update readme

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: clarify rate limiter error, available summary, and window seeding (#347)

- EWrongVariant: describe variant-typed getter mismatch instead of the
  removed in-place reconfigure API
- available: correct "available capacity" to available units (headroom)
  and list all three projections (accrual, window reset, cooldown release)
- new_fixed_window: flag that a backdated anchor discards the seeded
  initial_available once a full window has elapsed

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: document deliberate absence of events in rate limiter (#348)

Add an Observability section to the rate_limiter module doc block
explaining that the module emits no events by design (the limiter has
no stable identity of its own) and that emitting events for rate-limit
hits, cooldown arming, and reconfiguration is the integrator's
responsibility at their own entry functions.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: abort with ECooldownDeadlineOverflow on cooldown deadline overflow (#349)

* ref: [N-03]: reorder declaration fields for buckets (#343)

* ref: reorder declaration fields for buckets

* align field ordering

* feat: add median implementation  (#362)

* feat: add median implementation (#135)

* add separate quick_sort implementations for each type

* remove duplicated qsort implementations

* add in-place qsort implementation

* add partition function

* rewrite qsort without recursion

* convert quick_sort to macro

* add comprehensive test cases for qsort

* update qsort documentation

* add review fixes

* remove --trace flag from testing pipeline

* Revert "remove --trace flag from testing pipeline"

This reverts commit 9bf7065.

* split macro module

* inline partition macro

* add median implementation

* add more edge case test cases

* fix fmt

* remove quick_sort duplicate

* feat: add median

* docs: update PR

* Route median through u256 workhorse fun (#325)

* fix: fmt

* fix: apply CR comments

* test: add missing test

* fix: macro

* feat: use quickselect

* feat: improve CHANGELOG

* feat: apply review updates

* feat: update comment

---------

Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>

* docs: add ! to macros and update import format

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: update median PR in changelog

* chore: add ! to median macro mention

* docs: add missing ; after rounding imports in examples

---------

Co-authored-by: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com>
Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* [N-01] Core Math Audit (#357)

* feat: Implement Rate Limiter module (#315)

* feat: add rate limiter implementation

* docs: document invariants

* fix: enforce missing invariants

* test: add more tests

* feat: cooldown supports capacity/used

* ref: assume monotonic Clock

* fix: new_bucket accepts initial tokens (remove new_bucket_with_tokens)

* ref: track cooldown_end instead of last_used

* fix: cooldown used increases by 1 on consume

* ref: use 'available' design instead of 'used'

* ref: inline roll_window

* test: add cooldown_reconfigure_rearms_when_drained_and_deadline_elapsed

* docs: mention operator's responsibility for cooldown_ms

* ref: rename q to steps_to_full in bucket_accrue

* docs: update invariants

* fix: remove capacity + refill_amount assertion in assert_bucket_config

* docs: add missing / update docs

* feat: add variety of errors

* docs: add missing / update docs

* test: remove invariant class mentions

* ref: apply Code Quality Checklist (openzeppelin_utils)

* test: replace cleanup with 'abort EUnreachable' in expected-failure tests

* test: use abort 0 instead of error

* feat: remove 'Ms' suffix from Error names

* docs: error docs don't reference internal variables

* docs: rephrase rate_limiter error messages without internal field names

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update README

* docs: update README

* docs: align invariants.md to be sharing-ready

* docs: improve wording & clarity for invariants.md

* feat: cooldown now decrements available by amount

* test: change abort 0 to 100 (avoids confusing with ERateLimited)

* test: change all destructor patterns into abortions

* docs: invariant rewording

* docs: update format for invariants.md

* docs: update format for invariants.md and add missing invariants

* docs: align invariants format

* docs: update outdated invariant references

* docs: remove rate limiter temp. artifacts

* chore: simplify changelog

* ref: convert assert macros into funs

* docs: document private funs

* test(fix): add proper teardown in happy tests

* ci: add contracts/utils to CI test job dir matrix

* test: add regression tests for bucket_accrue

* fix: bucket_accrue double spend bug

* docs: add empty line before enum variant docs

Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* Revert "docs: add empty line before enum variant docs"

This reverts commit 21a9076.

* feat: inline config validation assertions

* docs: add more info on rate limiter types in README

* docs: add clarifying comments for apparent overflow suspects

* docs: mention library being access control-agnostic

* docs: reword library to module

* feat: add initial_available to all limiter types

* ref: put capacity as first cooldown type field

* ref: use spread op instead of ignoring cooldown_ms field

* docs: show identical API for all types in README

* docs: for fixed window update wording that it resets to full capacity

* fix: reconfigure sets last_refill to now + forbid 0 initial available for cooldown

* docs: remove post-core artifact

* test: add bucket_reconfigure_to_faster_rate_discards_old_subinterval

* docs: add SAFETY before overflow-related comments

* test: verify available always returns up-to-date accrual state

* test: add missing zero-config reconfigure tests

* test: add try_consume_with_zero_amount for all limiter types

* test: add try_consume_of_available_aborts_when_drained

* docs: note that try_consume(0) aborts after available() == 0

* docs: note RateLimiter enum is not upgrade-compatible

Adding variants or fields to a deployed public enum would break BCS
deserialization for integrator objects that already stored the prior
shape. Document this constraint at the module level.

* test: add edge case test cases

* docs: remove llm artifacts

* ref: reorder fileds in new_cooldown

* test: remove Pub.local.toml

* ref: in reconfigure_fixed_window move let now into match

* ref: in reconfigure_bucket move let now into match

* docs: remove mention of reconfigure_cooldown clamping available to 0

* fix: align cooldown clamp behavior on reconfigure

* fix: try_consume updates state only on success

* docs: align

* ref: fixedwindow now shares bucket's internal logic

* ref: update capacity prior to accrual on reconfigure_bucket

* docs: add comment

* Revert "docs: add comment"

This reverts commit ecb0145.

* Revert "ref: update capacity prior to accrual on reconfigure_bucket"

This reverts commit b545b6d.

* ref: Rate Limiter: Reconfiguration via Rich `new_*` Functions (#326)

* impl

* simplify further

* fix: expose last_refill_ms for bucket

* tests: add missing

* docs: update utils README

* docs: fix new_cooldown accepted combos

* feat: project bucket-shaped anchor getters

`last_refill_ms` and `window_start_ms` now take `&Clock` and return the
anchor advanced by every whole interval elapsed since the last commit,
so the snapshot `(anchor, available(clock))` is internally coherent.
`cooldown_end_ms` stays a plain getter — a cooldown deadline does not
evolve with time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: error numbering

* fix: error messages no longer reference private fields

* docs: move EBucketAnchorInFuture comment next to the error

* add spec

* update spec

* tests: add missing invariant tests

* feat: add is_type discriminator getters

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* tests: fix formatting in rate limiter tests (#334)

* feat: add median implementation (#135)

* add separate quick_sort implementations for each type

* remove duplicated qsort implementations

* add in-place qsort implementation

* add partition function

* rewrite qsort without recursion

* convert quick_sort to macro

* add comprehensive test cases for qsort

* update qsort documentation

* add review fixes

* remove --trace flag from testing pipeline

* Revert "remove --trace flag from testing pipeline"

This reverts commit 9bf7065.

* split macro module

* inline partition macro

* add median implementation

* add more edge case test cases

* fix fmt

* remove quick_sort duplicate

* feat: add median

* docs: update PR

* Route median through u256 workhorse fun (#325)

* fix: fmt

* fix: apply CR comments

* test: add missing test

* fix: macro

* feat: use quickselect

* feat: improve CHANGELOG

* feat: apply review updates

* feat: update comment

---------

Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>

* feat: update check

* feat: update version

---------

Co-authored-by: Nenad <nenad.misic@openzeppelin.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>
Co-authored-by: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com>
Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>

* [N-02] Core Math Audit (#359)

* feat: Implement Rate Limiter module (#315)

* feat: add rate limiter implementation

* docs: document invariants

* fix: enforce missing invariants

* test: add more tests

* feat: cooldown supports capacity/used

* ref: assume monotonic Clock

* fix: new_bucket accepts initial tokens (remove new_bucket_with_tokens)

* ref: track cooldown_end instead of last_used

* fix: cooldown used increases by 1 on consume

* ref: use 'available' design instead of 'used'

* ref: inline roll_window

* test: add cooldown_reconfigure_rearms_when_drained_and_deadline_elapsed

* docs: mention operator's responsibility for cooldown_ms

* ref: rename q to steps_to_full in bucket_accrue

* docs: update invariants

* fix: remove capacity + refill_amount assertion in assert_bucket_config

* docs: add missing / update docs

* feat: add variety of errors

* docs: add missing / update docs

* test: remove invariant class mentions

* ref: apply Code Quality Checklist (openzeppelin_utils)

* test: replace cleanup with 'abort EUnreachable' in expected-failure tests

* test: use abort 0 instead of error

* feat: remove 'Ms' suffix from Error names

* docs: error docs don't reference internal variables

* docs: rephrase rate_limiter error messages without internal field names

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update README

* docs: update README

* docs: align invariants.md to be sharing-ready

* docs: improve wording & clarity for invariants.md

* feat: cooldown now decrements available by amount

* test: change abort 0 to 100 (avoids confusing with ERateLimited)

* test: change all destructor patterns into abortions

* docs: invariant rewording

* docs: update format for invariants.md

* docs: update format for invariants.md and add missing invariants

* docs: align invariants format

* docs: update outdated invariant references

* docs: remove rate limiter temp. artifacts

* chore: simplify changelog

* ref: convert assert macros into funs

* docs: document private funs

* test(fix): add proper teardown in happy tests

* ci: add contracts/utils to CI test job dir matrix

* test: add regression tests for bucket_accrue

* fix: bucket_accrue double spend bug

* docs: add empty line before enum variant docs

Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* Revert "docs: add empty line before enum variant docs"

This reverts commit 21a9076.

* feat: inline config validation assertions

* docs: add more info on rate limiter types in README

* docs: add clarifying comments for apparent overflow suspects

* docs: mention library being access control-agnostic

* docs: reword library to module

* feat: add initial_available to all limiter types

* ref: put capacity as first cooldown type field

* ref: use spread op instead of ignoring cooldown_ms field

* docs: show identical API for all types in README

* docs: for fixed window update wording that it resets to full capacity

* fix: reconfigure sets last_refill to now + forbid 0 initial available for cooldown

* docs: remove post-core artifact

* test: add bucket_reconfigure_to_faster_rate_discards_old_subinterval

* docs: add SAFETY before overflow-related comments

* test: verify available always returns up-to-date accrual state

* test: add missing zero-config reconfigure tests

* test: add try_consume_with_zero_amount for all limiter types

* test: add try_consume_of_available_aborts_when_drained

* docs: note that try_consume(0) aborts after available() == 0

* docs: note RateLimiter enum is not upgrade-compatible

Adding variants or fields to a deployed public enum would break BCS
deserialization for integrator objects that already stored the prior
shape. Document this constraint at the module level.

* test: add edge case test cases

* docs: remove llm artifacts

* ref: reorder fileds in new_cooldown

* test: remove Pub.local.toml

* ref: in reconfigure_fixed_window move let now into match

* ref: in reconfigure_bucket move let now into match

* docs: remove mention of reconfigure_cooldown clamping available to 0

* fix: align cooldown clamp behavior on reconfigure

* fix: try_consume updates state only on success

* docs: align

* ref: fixedwindow now shares bucket's internal logic

* ref: update capacity prior to accrual on reconfigure_bucket

* docs: add comment

* Revert "docs: add comment"

This reverts commit ecb0145.

* Revert "ref: update capacity prior to accrual on reconfigure_bucket"

This reverts commit b545b6d.

* ref: Rate Limiter: Reconfiguration via Rich `new_*` Functions (#326)

* impl

* simplify further

* fix: expose last_refill_ms for bucket

* tests: add missing

* docs: update utils README

* docs: fix new_cooldown accepted combos

* feat: project bucket-shaped anchor getters

`last_refill_ms` and `window_start_ms` now take `&Clock` and return the
anchor advanced by every whole interval elapsed since the last commit,
so the snapshot `(anchor, available(clock))` is internally coherent.
`cooldown_end_ms` stays a plain getter — a cooldown deadline does not
evolve with time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: error numbering

* fix: error messages no longer reference private fields

* docs: move EBucketAnchorInFuture comment next to the error

* add spec

* update spec

* tests: add missing invariant tests

* feat: add is_type discriminator getters

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* tests: fix formatting in rate limiter tests (#334)

* feat: add median implementation (#135)

* add separate quick_sort implementations for each type

* remove duplicated qsort implementations

* add in-place qsort implementation

* add partition function

* rewrite qsort without recursion

* convert quick_sort to macro

* add comprehensive test cases for qsort

* update qsort documentation

* add review fixes

* remove --trace flag from testing pipeline

* Revert "remove --trace flag from testing pipeline"

This reverts commit 9bf7065.

* split macro module

* inline partition macro

* add median implementation

* add more edge case test cases

* fix fmt

* remove quick_sort duplicate

* feat: add median

* docs: update PR

* Route median through u256 workhorse fun (#325)

* fix: fmt

* fix: apply CR comments

* test: add missing test

* fix: macro

* feat: use quickselect

* feat: improve CHANGELOG

* feat: apply review updates

* feat: update comment

---------

Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>

* feat: update check

* feat: update version

* feat: bump version

* feat: apply improvements

---------

Co-authored-by: Nenad <nenad.misic@openzeppelin.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>
Co-authored-by: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com>
Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>

* [N-03] Math Core Audit (#360)

* feat: Implement Rate Limiter module (#315)

* feat: add rate limiter implementation

* docs: document invariants

* fix: enforce missing invariants

* test: add more tests

* feat: cooldown supports capacity/used

* ref: assume monotonic Clock

* fix: new_bucket accepts initial tokens (remove new_bucket_with_tokens)

* ref: track cooldown_end instead of last_used

* fix: cooldown used increases by 1 on consume

* ref: use 'available' design instead of 'used'

* ref: inline roll_window

* test: add cooldown_reconfigure_rearms_when_drained_and_deadline_elapsed

* docs: mention operator's responsibility for cooldown_ms

* ref: rename q to steps_to_full in bucket_accrue

* docs: update invariants

* fix: remove capacity + refill_amount assertion in assert_bucket_config

* docs: add missing / update docs

* feat: add variety of errors

* docs: add missing / update docs

* test: remove invariant class mentions

* ref: apply Code Quality Checklist (openzeppelin_utils)

* test: replace cleanup with 'abort EUnreachable' in expected-failure tests

* test: use abort 0 instead of error

* feat: remove 'Ms' suffix from Error names

* docs: error docs don't reference internal variables

* docs: rephrase rate_limiter error messages without internal field names

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update README

* docs: update README

* docs: align invariants.md to be sharing-ready

* docs: improve wording & clarity for invariants.md

* feat: cooldown now decrements available by amount

* test: change abort 0 to 100 (avoids confusing with ERateLimited)

* test: change all destructor patterns into abortions

* docs: invariant rewording

* docs: update format for invariants.md

* docs: update format for invariants.md and add missing invariants

* docs: align invariants format

* docs: update outdated invariant references

* docs: remove rate limiter temp. artifacts

* chore: simplify changelog

* ref: convert assert macros into funs

* docs: document private funs

* test(fix): add proper teardown in happy tests

* ci: add contracts/utils to CI test job dir matrix

* test: add regression tests for bucket_accrue

* fix: bucket_accrue double spend bug

* docs: add empty line before enum variant docs

Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* Revert "docs: add empty line before enum variant docs"

This reverts commit 21a9076.

* feat: inline config validation assertions

* docs: add more info on rate limiter types in README

* docs: add clarifying comments for apparent overflow suspects

* docs: mention library being access control-agnostic

* docs: reword library to module

* feat: add initial_available to all limiter types

* ref: put capacity as first cooldown type field

* ref: use spread op instead of ignoring cooldown_ms field

* docs: show identical API for all types in README

* docs: for fixed window update wording that it resets to full capacity

* fix: reconfigure sets last_refill to now + forbid 0 initial available for cooldown

* docs: remove post-core artifact

* test: add bucket_reconfigure_to_faster_rate_discards_old_subinterval

* docs: add SAFETY before overflow-related comments

* test: verify available always returns up-to-date accrual state

* test: add missing zero-config reconfigure tests

* test: add try_consume_with_zero_amount for all limiter types

* test: add try_consume_of_available_aborts_when_drained

* docs: note that try_consume(0) aborts after available() == 0

* docs: note RateLimiter enum is not upgrade-compatible

Adding variants or fields to a deployed public enum would break BCS
deserialization for integrator objects that already stored the prior
shape. Document this constraint at the module level.

* test: add edge case test cases

* docs: remove llm artifacts

* ref: reorder fileds in new_cooldown

* test: remove Pub.local.toml

* ref: in reconfigure_fixed_window move let now into match

* ref: in reconfigure_bucket move let now into match

* docs: remove mention of reconfigure_cooldown clamping available to 0

* fix: align cooldown clamp behavior on reconfigure

* fix: try_consume updates state only on success

* docs: align

* ref: fixedwindow now shares bucket's internal logic

* ref: update capacity prior to accrual on reconfigure_bucket

* docs: add comment

* Revert "docs: add comment"

This reverts commit ecb0145.

* Revert "ref: update capacity prior to accrual on reconfigure_bucket"

This reverts commit b545b6d.

* ref: Rate Limiter: Reconfiguration via Rich `new_*` Functions (#326)

* impl

* simplify further

* fix: expose last_refill_ms for bucket

* tests: add missing

* docs: update utils README

* docs: fix new_cooldown accepted combos

* feat: project bucket-shaped anchor getters

`last_refill_ms` and `window_start_ms` now take `&Clock` and return the
anchor advanced by every whole interval elapsed since the last commit,
so the snapshot `(anchor, available(clock))` is internally coherent.
`cooldown_end_ms` stays a plain getter — a cooldown deadline does not
evolve with time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: error numbering

* fix: error messages no longer reference private fields

* docs: move EBucketAnchorInFuture comment next to the error

* add spec

* update spec

* tests: add missing invariant tests

* feat: add is_type discriminator getters

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* tests: fix formatting in rate limiter tests (#334)

* feat: add median implementation (#135)

* add separate quick_sort implementations for each type

* remove duplicated qsort implementations

* add in-place qsort implementation

* add partition function

* rewrite qsort without recursion

* convert quick_sort to macro

* add comprehensive test cases for qsort

* update qsort documentation

* add review fixes

* remove --trace flag from testing pipeline

* Revert "remove --trace flag from testing pipeline"

This reverts commit 9bf7065.

* split macro module

* inline partition macro

* add median implementation

* add more edge case test cases

* fix fmt

* remove quick_sort duplicate

* feat: add median

* docs: update PR

* Route median through u256 workhorse fun (#325)

* fix: fmt

* fix: apply CR comments

* test: add missing test

* fix: macro

* feat: use quickselect

* feat: improve CHANGELOG

* feat: apply review updates

* feat: update comment

---------

Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>

* feat: update check

* feat: update version

* feat: bump version

* feat: apply improvements

* feat: improvements

---------

Co-authored-by: Nenad <nenad.misic@openzeppelin.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>
Co-authored-by: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com>
Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>

* docs: add Rate limiter examples (#361)

* docs: merge faucet examples into one

* docs: add staking_vault example

* docs: add base mage_duel example

* docs: update mage_duel example

* docs: delete metadata_cap in rare_coin

* docs: apply move-quality skill

* docs: fix mage_duel wrong duel assertion

* docs: fix typo in utils/README

* docs: remove ENotOpponent error from mage_duel

* docs: move example tests to separate modules

* docs: increase test coverage

* docs: remove traces

* docs: add missing test docs for examples

* docs: fmt

* docs: make unaudited examples warnings visible at top of sections

* docs: use full gh URLs to examples

* docs: change title 'rate_limiter at a Glance' to 'Rate Limiter at a Glance'

* docs: remove operator notes

* Update contracts/utils/README.md

Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>

* docs: add exapmles ref in contracts/README

* docs: fix mage_duel module docs

* docs: remove mention of "compiling" examples

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* docs: remove mentions of "compiling" when mentioning examples

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* test: add test_only attribute to example test modules

* test: take shared faucet in the test tx where it's actually needed

* test: Add missing comment dots + remove redundant imports

* docs: use release-v1.3 as the branch to point example URLs

---------

Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: add rate limiter audit report (#364)

* [N-04] Core Math Audit (#363)

* feat: Implement Rate Limiter module (#315)

* feat: add rate limiter implementation

* docs: document invariants

* fix: enforce missing invariants

* test: add more tests

* feat: cooldown supports capacity/used

* ref: assume monotonic Clock

* fix: new_bucket accepts initial tokens (remove new_bucket_with_tokens)

* ref: track cooldown_end instead of last_used

* fix: cooldown used increases by 1 on consume

* ref: use 'available' design instead of 'used'

* ref: inline roll_window

* test: add cooldown_reconfigure_rearms_when_drained_and_deadline_elapsed

* docs: mention operator's responsibility for cooldown_ms

* ref: rename q to steps_to_full in bucket_accrue

* docs: update invariants

* fix: remove capacity + refill_amount assertion in assert_bucket_config

* docs: add missing / update docs

* feat: add variety of errors

* docs: add missing / update docs

* test: remove invariant class mentions

* ref: apply Code Quality Checklist (openzeppelin_utils)

* test: replace cleanup with 'abort EUnreachable' in expected-failure tests

* test: use abort 0 instead of error

* feat: remove 'Ms' suffix from Error names

* docs: error docs don't reference internal variables

* docs: rephrase rate_limiter error messages without internal field names

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update README

* docs: update README

* docs: align invariants.md to be sharing-ready

* docs: improve wording & clarity for invariants.md

* feat: cooldown now decrements available by amount

* test: change abort 0 to 100 (avoids confusing with ERateLimited)

* test: change all destructor patterns into abortions

* docs: invariant rewording

* docs: update format for invariants.md

* docs: update format for invariants.md and add missing invariants

* docs: align invariants format

* docs: update outdated invariant references

* docs: remove rate limiter temp. artifacts

* chore: simplify changelog

* ref: convert assert macros into funs

* docs: document private funs

* test(fix): add proper teardown in happy tests

* ci: add contracts/utils to CI test job dir matrix

* test: add regression tests for bucket_accrue

* fix: bucket_accrue double spend bug

* docs: add empty line before enum variant docs

Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* Revert "docs: add empty line before enum variant docs"

This reverts commit 21a9076.

* feat: inline config validation assertions

* docs: add more info on rate limiter types in README

* docs: add clarifying comments for apparent overflow suspects

* docs: mention library being access control-agnostic

* docs: reword library to module

* feat: add initial_available to all limiter types

* ref: put capacity as first cooldown type field

* ref: use spread op instead of ignoring cooldown_ms field

* docs: show identical API for all types in README

* docs: for fixed window update wording that it resets to full capacity

* fix: reconfigure sets last_refill to now + forbid 0 initial available for cooldown

* docs: remove post-core artifact

* test: add bucket_reconfigure_to_faster_rate_discards_old_subinterval

* docs: add SAFETY before overflow-related comments

* test: verify available always returns up-to-date accrual state

* test: add missing zero-config reconfigure tests

* test: add try_consume_with_zero_amount for all limiter types

* test: add try_consume_of_available_aborts_when_drained

* docs: note that try_consume(0) aborts after available() == 0

* docs: note RateLimiter enum is not upgrade-compatible

Adding variants or fields to a deployed public enum would break BCS
deserialization for integrator objects that already stored the prior
shape. Document this constraint at the module level.

* test: add edge case test cases

* docs: remove llm artifacts

* ref: reorder fileds in new_cooldown

* test: remove Pub.local.toml

* ref: in reconfigure_fixed_window move let now into match

* ref: in reconfigure_bucket move let now into match

* docs: remove mention of reconfigure_cooldown clamping available to 0

* fix: align cooldown clamp behavior on reconfigure

* fix: try_consume updates state only on success

* docs: align

* ref: fixedwindow now shares bucket's internal logic

* ref: update capacity prior to accrual on reconfigure_bucket

* docs: add comment

* Revert "docs: add comment"

This reverts commit ecb0145.

* Revert "ref: update capacity prior to accrual on reconfigure_bucket"

This reverts commit b545b6d.

* ref: Rate Limiter: Reconfiguration via Rich `new_*` Functions (#326)

* impl

* simplify further

* fix: expose last_refill_ms for bucket

* tests: add missing

* docs: update utils README

* docs: fix new_cooldown accepted combos

* feat: project bucket-shaped anchor getters

`last_refill_ms` and `window_start_ms` now take `&Clock` and return the
anchor advanced by every whole interval elapsed since the last commit,
so the snapshot `(anchor, available(clock))` is internally coherent.
`cooldown_end_ms` stays a plain getter — a cooldown deadline does not
evolve with time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: error numbering

* fix: error messages no longer reference private fields

* docs: move EBucketAnchorInFuture comment next to the error

* add spec

* update spec

* tests: add missing invariant tests

* feat: add is_type discriminator getters

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>

* tests: fix formatting in rate limiter tests (#334)

* feat: add median implementation (#135)

* add separate quick_sort implementations for each type

* remove duplicated qsort implementations

* add in-place qsort implementation

* add partition function

* rewrite qsort without recursion

* convert quick_sort to macro

* add comprehensive test cases for qsort

* update qsort documentation

* add review fixes

* remove --trace flag from testing pipeline

* Revert "remove --trace flag from testing pipeline"

This reverts commit 9bf7065.

* split macro module

* inline partition macro

* add median implementation

* add more edge case test cases

* fix fmt

* remove quick_sort duplicate

* feat: add median

* docs: update PR

* Route median through u256 workhorse fun (#325)

* fix: fmt

* fix: apply CR comments

* test: add missing test

* fix: macro

* feat: use quickselect

* feat: improve CHANGELOG

* feat: apply review updates

* feat: update comment

---------

Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>

* feat: update check

* feat: update version

* feat: bump version

* feat: apply improvements

* feat: improvements

* feat: improve median impl

* docs: math/core doc-quality pass + median wrapper docs and u128 tests (#365)

Post-review follow-ups on the N-04 median work plus a doc-quality sweep of
math/core (move-quality checklist):

- vector: document #### Parameters / #### Returns on the median_u8..median_u256
  wrappers (previously only #### Aborts).
- median tests: add median_u128_even_length_rounding_modes and extend
  median_u128_basics with the 0 & MAX overflow boundary (BTT gap fill).
- macros: add /// docs to EDivideByZero/EZeroModulus and the TEN_POW_* consts;
  fix spurious-bullet continuations in several #### Returns/#### Aborts blocks;
  add #### Generics to inv_mod/mul_mod, #### Aborts to mul_mod/mul_div_inner/
  inv_mod_extended_impl, and name EZeroModulus in inv_mod's #### Aborts.
- u512: add /// docs to the four error constants, HALF_BITS/HALF_MASK, and the
  hi/lo struct fields.
- decimal_scaling: tag example fences as ```move, promote the "Truncation
  Behavior" header to ####, and convert scale_amount's #### Examples to a
  fenced move block.
- decimal_scaling tests: rename "Test Helpers" section to "Test-Only Helpers".

All 753 tests pass with --lint --warnings-are-errors; prettier clean.

---------

Co-authored-by: Nenad <nenad.misic@openzeppelin.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>
Co-authored-by: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com>
Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>

* feat: add Published info (#369)

* feat: add Published info (#371)

* chore: Add core math diff audit report (#372)

* chore: add core math diff audit report

* chore: update name and commit range

* chore: update changelog for release v1.3 (#373)

* docs: update docs' URLs (#387)

* docs: use relative paths for example links in README

* docs: link to specific examples in rate_limiter mod docs

* docs: change tree to block in gh urls

* remove .skills

---------

Co-authored-by: Eric Nordelo <eric.nordelo39@gmail.com>
Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Daniel Bigos <daniel.bigos96@gmail.com>
Co-authored-by: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com>
Co-authored-by: Daniel Bigos <daniel.bigos@openzeppelin.com>
Co-authored-by: Daniel Bigos <daniel.bigos@icloud.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants