Skip to content

2025 08 25 div by one#111

Merged
thedavidmeister merged 10 commits intomainfrom
2025-08-25-div-by-one
Aug 27, 2025
Merged

2025 08 25 div by one#111
thedavidmeister merged 10 commits intomainfrom
2025-08-25-div-by-one

Conversation

@thedavidmeister
Copy link
Copy Markdown
Contributor

@thedavidmeister thedavidmeister commented Aug 25, 2025

Motivation

Solution

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Summary by CodeRabbit

  • Bug Fixes

    • Improved division exponent calculation to reduce transient overflow risk in rare edge cases.
    • Adjusted overflow reporting to surface the original exponent in certain overflow paths for clearer diagnostics.
  • Tests

    • Added extensive property tests validating division by +1 and -1 across wide exponent ranges, verifying correct value, sign, and normalization.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 25, 2025

Walkthrough

Adjusts div exponent ordering to apply adjustExponent conditionally (branch on exponentA >= 0) to change transient overflow ordering and alters maximize overflow revert to report initialExponent when smaller; adds property tests exercising division by ±1 scaled across wide negative exponents at both library and implementation test levels.

Changes

Cohort / File(s) Summary
Core implementation: div & maximize
src/lib/implementation/LibDecimalFloatImplementation.sol
Changes div exponent computation to apply adjustExponent in a conditional order (if exponentA >= 0 then exp = exponentA - adjustExponent - exponentB else exp = exponentA - exponentB - adjustExponent); updates maximize overflow revert to emit initialExponent when initialExponent < exponent. No public signatures changed.
Library-level div tests
test/src/lib/LibDecimalFloat.div.t.sol
Adds testDivByOneFloat(int224 signedCoefficient, int32 exponent) and testDivByNegativeOneFloat(int224 signedCoefficient, int32 exponent) that divide by ±1×10^e for e from 0 down to -65 and assert identity/negation.
Implementation-level div tests
test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
Adds testDivBy1(int256 signedCoefficient, int256 exponent) and testDivByNegativeOneFloat(int256 signedCoefficient, int256 exponent) that iterate divisors ±1×10^e for e from 0 down to -76 and validate results via checkDiv against maximize/minus.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant Impl as LibDecimalFloatImplementation
  participant Scale as lossyScale (mul/div)
  participant Max as maximize

  Caller->>Impl: div(aCoeff,aExp, bCoeff,bExp)
  Impl->>Impl: compute adjustExponent
  alt exponentA >= 0
    Note right of Impl: exp = exponentA - adjustExponent - exponentB
  else
    Note right of Impl: exp = exponentA - exponentB - adjustExponent
  end
  Impl->>Scale: scale coefficients (lossy mul/div)
  Scale-->>Impl: scaledCoeff, scaledExp
  Impl->>Max: maximize(scaledCoeff, scaledExp)
  alt normalize success
    Max-->>Impl: normalized coeff/exp
    Impl-->>Caller: packed Float
  else overflow
    Max-->>Impl: revert ExponentOverflow(initialExponent)
    Impl-->>Caller: revert
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • hardyjosh

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 2025-08-25-div-by-one

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@thedavidmeister thedavidmeister changed the base branch from 2025-08-24-pow10 to main August 26, 2025 15:52
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c224c27 and 26c3573.

📒 Files selected for processing (3)
  • src/lib/implementation/LibDecimalFloatImplementation.sol (2 hunks)
  • test/src/lib/LibDecimalFloat.div.t.sol (1 hunks)
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#107
File: test/lib/LibDecimalFloatSlow.sol:37-45
Timestamp: 2025-08-21T18:03:40.347Z
Learning: In test/lib/LibDecimalFloatSlow.sol, the "slow" implementation is intentionally different from the production implementation to serve as an independent reference for fuzzing tests. The goal is to have two different approaches (expensive loops vs optimized jumps) that produce equivalent results, not identical implementations.
📚 Learning: 2025-08-21T18:03:40.347Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#107
File: test/lib/LibDecimalFloatSlow.sol:37-45
Timestamp: 2025-08-21T18:03:40.347Z
Learning: In test/lib/LibDecimalFloatSlow.sol, the "slow" implementation is intentionally different from the production implementation to serve as an independent reference for fuzzing tests. The goal is to have two different approaches (expensive loops vs optimized jumps) that produce equivalent results, not identical implementations.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
  • src/lib/implementation/LibDecimalFloatImplementation.sol
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
📚 Learning: 2025-06-16T13:17:28.513Z
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#58
File: src/concrete/DecimalFloat.sol:175-182
Timestamp: 2025-06-16T13:17:28.513Z
Learning: In the rainlanguage/rain.math.float codebase, there's an established naming convention where functions accepting a `Float` type parameter consistently use `float` as the parameter name, even though it shadows the type name. This pattern is used throughout `LibDecimalFloat.sol` and should be maintained for consistency in related contracts like `DecimalFloat.sol`.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-18T13:52:43.369Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#105
File: src/lib/implementation/LibDecimalFloatImplementation.sol:248-335
Timestamp: 2025-08-18T13:52:43.369Z
Learning: The codebase has a policy of not modifying external code, such as mulDiv implementations adopted from standard libraries like OpenZeppelin, PRB Math, and Solady.

Applied to files:

  • src/lib/implementation/LibDecimalFloatImplementation.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: rainix (macos-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, test-wasm-build)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-static)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-static)
  • GitHub Check: rainix (macos-latest, rainix-sol-legal)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-test)
  • GitHub Check: git-clean
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-legal)
🔇 Additional comments (1)
src/lib/implementation/LibDecimalFloatImplementation.sol (1)

774-775: Revert now reports the input exponent: verify downstream expectations

Changing ExponentOverflow to carry initialExponent instead of the computed exponent improves debuggability. It is, however, a user-visible ABI change in revert data. If any tests or external tooling assert on the revert payload, they’ll need to be updated.

Consider adding (or updating) a targeted test that exercises this revert and asserts the second argument equals the input exponent. If no such path is reachable via maximize (it generally shouldn’t be), a small harness calling withTargetExponent to force an overflow would suffice.

Comment thread src/lib/implementation/LibDecimalFloatImplementation.sol Outdated
Comment thread test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
Comment thread test/src/lib/LibDecimalFloat.div.t.sol Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
test/src/lib/LibDecimalFloat.div.t.sol (1)

44-55: Strengthen the property: divide by numeric 1 must be an identity (assert numeric equality).

This test currently only checks for non-reverts. Add an explicit equality assertion using the implementation’s numeric comparator to catch silent representation/regression bugs. Per earlier learnings, compare numerical equivalence (unpacked parts via Implementation.eq), not raw packing equality.

Apply this diff to add the assertion while keeping the function pure (use language-level assert):

-    function testDivByOneFloat(int224 signedCoefficient, int32 exponent) external pure {
-        exponent = int32(bound(exponent, int256(type(int32).min) + 65, int256(type(int32).max)));
-        Float float = LibDecimalFloat.packLossless(signedCoefficient, exponent);
-        int256 one = 1;
-        for (int256 oneExponent = 0; oneExponent >= -65; --oneExponent) {
-            LibDecimalFloat.div(float, LibDecimalFloat.packLossless(one, oneExponent));
-            if (oneExponent == -65) {
-                break;
-            }
-            one *= 10;
-        }
-    }
+    function testDivByOneFloat(int224 signedCoefficient, int32 exponent) external pure {
+        exponent = int32(bound(exponent, int256(type(int32).min) + 65, int256(type(int32).max)));
+        Float float = LibDecimalFloat.packLossless(signedCoefficient, exponent);
+        (int256 aC, int256 aE) = float.unpack();
+        int256 one = 1;
+        for (int256 oneExponent = 0; oneExponent >= -65; --oneExponent) {
+            Float divisor = LibDecimalFloat.packLossless(one, oneExponent); // exactly numeric 1
+            Float q = LibDecimalFloat.div(float, divisor);
+            (int256 qC, int256 qE) = q.unpack();
+            // Pure-safe assertion: identity must hold numerically.
+            assert(LibDecimalFloatImplementation.eq(aC, aE, qC, qE));
+            if (oneExponent == -65) break; // Avoid computing 10**66
+            one *= 10;
+        }
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 26c3573 and 64f24ff.

📒 Files selected for processing (1)
  • test/src/lib/LibDecimalFloat.div.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#107
File: test/lib/LibDecimalFloatSlow.sol:37-45
Timestamp: 2025-08-21T18:03:40.347Z
Learning: In test/lib/LibDecimalFloatSlow.sol, the "slow" implementation is intentionally different from the production implementation to serve as an independent reference for fuzzing tests. The goal is to have two different approaches (expensive loops vs optimized jumps) that produce equivalent results, not identical implementations.
📚 Learning: 2025-08-21T18:03:40.347Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#107
File: test/lib/LibDecimalFloatSlow.sol:37-45
Timestamp: 2025-08-21T18:03:40.347Z
Learning: In test/lib/LibDecimalFloatSlow.sol, the "slow" implementation is intentionally different from the production implementation to serve as an independent reference for fuzzing tests. The goal is to have two different approaches (expensive loops vs optimized jumps) that produce equivalent results, not identical implementations.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-06-16T13:17:28.513Z
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#58
File: src/concrete/DecimalFloat.sol:175-182
Timestamp: 2025-06-16T13:17:28.513Z
Learning: In the rainlanguage/rain.math.float codebase, there's an established naming convention where functions accepting a `Float` type parameter consistently use `float` as the parameter name, even though it shadows the type name. This pattern is used throughout `LibDecimalFloat.sol` and should be maintained for consistency in related contracts like `DecimalFloat.sol`.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-test)
  • GitHub Check: rainix (ubuntu-latest, test-wasm-build)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-static)
  • GitHub Check: rainix (macos-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-static)
  • GitHub Check: rainix (macos-latest, rainix-sol-legal)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-legal)
  • GitHub Check: git-clean

Comment thread test/src/lib/LibDecimalFloat.div.t.sol
Comment thread test/src/lib/LibDecimalFloat.div.t.sol
thedavidmeister and others added 3 commits August 26, 2025 20:48
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol (2)

103-117: Good property; simplify loop to avoid sentinel break (same as prior suggestion).

The +/-1 invariants look solid. Minor readability win: skip the multiply on the last iteration instead of breaking mid-loop. Behavior is unchanged and still guards against 10^77.

         for (int256 oneExponent = 0; oneExponent >= -76; --oneExponent) {
             checkDiv(signedCoefficient, exponent, one, oneExponent, expectedCoefficient, expectedExponent);
-            if (oneExponent == -76) {
-                break;
-            }
-            one *= 10;
+            // Avoid overflowing `one` to 10^77 on the next iteration.
+            if (oneExponent > -76) {
+                one *= 10;
+            }
         }

119-134: Negative-one coverage is great; mirror the loop cleanup here.

Same optional loop tweak as above; avoids the break and the unused multiply on the last iteration.

         for (int256 oneExponent = 0; oneExponent >= -76; --oneExponent) {
             checkDiv(signedCoefficient, exponent, negativeOne, oneExponent, expectedCoefficient, expectedExponent);
-            if (oneExponent == -76) {
-                break;
-            }
-            negativeOne *= 10;
+            // Keep `negativeOne` at -10^k but avoid 10^77 on the next iteration.
+            if (oneExponent > -76) {
+                negativeOne *= 10;
+            }
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3b1ab83 and 18c7886.

📒 Files selected for processing (2)
  • test/src/lib/LibDecimalFloat.div.t.sol (1 hunks)
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-08-21T18:03:40.347Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#107
File: test/lib/LibDecimalFloatSlow.sol:37-45
Timestamp: 2025-08-21T18:03:40.347Z
Learning: In test/lib/LibDecimalFloatSlow.sol, the "slow" implementation is intentionally different from the production implementation to serve as an independent reference for fuzzing tests. The goal is to have two different approaches (expensive loops vs optimized jumps) that produce equivalent results, not identical implementations.

Applied to files:

  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-11T14:32:50.439Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#96
File: test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol:15-29
Timestamp: 2025-08-11T14:32:50.439Z
Learning: In test code for the rain.math.float repository, redundant checks may be intentionally kept for clarity and documentation purposes, even when they could be simplified. The maintainer (thedavidmeister) prefers explicit assertions in test code to make the test's intent clear to future readers, prioritizing readability over conciseness.

Applied to files:

  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-14T16:56:28.978Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#99
File: src/lib/implementation/LibDecimalFloatImplementation.sol:574-581
Timestamp: 2025-08-14T16:56:28.978Z
Learning: In the rainlanguage/rain.math.float repository, maintainer thedavidmeister avoids using `&&` operators in gas-critical paths because they involve jumps in Solidity due to short-circuit evaluation, preferring approaches like mul-then-div overflow probes that avoid conditional jump overhead.

Applied to files:

  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-06-16T13:17:28.513Z
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#58
File: src/concrete/DecimalFloat.sol:175-182
Timestamp: 2025-06-16T13:17:28.513Z
Learning: In the rainlanguage/rain.math.float codebase, there's an established naming convention where functions accepting a `Float` type parameter consistently use `float` as the parameter name, even though it shadows the type name. This pattern is used throughout `LibDecimalFloat.sol` and should be maintained for consistency in related contracts like `DecimalFloat.sol`.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-26T16:50:11.077Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#111
File: test/src/lib/LibDecimalFloat.div.t.sol:48-51
Timestamp: 2025-08-26T16:50:11.077Z
Learning: In LibDecimalFloat, packLossless internally asserts that the packing operation is lossless, so there's no need to manually check the lossless flag when using packLossless instead of packLossy.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-07-24T04:32:14.171Z
Learnt from: rouzwelt
PR: rainlanguage/rain.math.float#83
File: src/concrete/DecimalFloat.sol:248-251
Timestamp: 2025-07-24T04:32:14.171Z
Learning: In the rainlanguage/rain.math.float project, functions in DecimalFloat.sol that return tuples from LibDecimalFloat calls must unpack the tuple into local variables before returning them (rather than returning directly) to maintain compatibility with Slither static analysis checks.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-14T16:32:05.932Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#99
File: src/lib/implementation/LibDecimalFloatImplementation.sol:309-325
Timestamp: 2025-08-14T16:32:05.932Z
Learning: In the rainlanguage/rain.math.float repository, maintainer thedavidmeister prefers to keep assembly-based overflow checks inline for gas optimization rather than extracting them into helper functions, even when it results in code duplication.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-07-17T02:38:44.698Z
Learnt from: rouzwelt
PR: rainlanguage/rain.math.float#76
File: test_js/float.test.ts:9-32
Timestamp: 2025-07-17T02:38:44.698Z
Learning: In the rainlanguage/rain.math.float repository, the user rouzwelt accepts non-null assertions in test files because tests should throw and fail immediately when something goes wrong, making it clear where the issue occurred.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
🪛 GitHub Actions: Rainix CI
test/src/lib/LibDecimalFloat.div.t.sol

[error] 1-1: forge test -vvv failed: LibDecimalFloatDivTest.testDivByNegativeOneFloat resulted in ExponentOverflow during division by -1 float. Counterexample calldata/args are shown in the logs.

Comment thread test/src/lib/LibDecimalFloat.div.t.sol
Comment thread test/src/lib/LibDecimalFloat.div.t.sol
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (5)
test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol (2)

110-116: Simplify loop: avoid sentinel break (guard the multiply instead).

Same behavior, clearer flow; prevents the extra multiply on the last iteration.

-            if (oneExponent == -76) {
-                break;
-            }
-            one *= 10;
+            if (oneExponent > -76) {
+                one *= 10;
+            }

127-133: Same loop cleanup for -1 path.

-            if (oneExponent == -76) {
-                break;
-            }
-            negativeOne *= 10;
+            if (oneExponent > -76) {
+                negativeOne *= 10;
+            }
test/src/lib/LibDecimalFloat.div.t.sol (3)

44-46: Tighten upper bound to avoid int32 exponent overflow at oneExponent = -65.

Use type(int32).max - 65 (consistent with the -1 test).

-        exponent = int32(bound(exponent, int256(type(int32).min) + 65, int256(type(int32).max)));
+        exponent = int32(bound(exponent, int256(type(int32).min) + 65, int256(type(int32).max) - 65));

51-55: Remove sentinel break; guard the multiply.

-            if (oneExponent == -65) {
-                break;
-            }
-            one *= 10;
+            if (oneExponent > -65) {
+                one *= 10;
+            }

65-69: Mirror the same loop style for the -1 test.

-            if (oneExponent == -65) {
-                break;
-            }
-            negativeOne *= 10;
+            if (oneExponent > -65) {
+                negativeOne *= 10;
+            }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 18c7886 and 63310e4.

📒 Files selected for processing (2)
  • test/src/lib/LibDecimalFloat.div.t.sol (1 hunks)
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-08-21T18:03:40.347Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#107
File: test/lib/LibDecimalFloatSlow.sol:37-45
Timestamp: 2025-08-21T18:03:40.347Z
Learning: In test/lib/LibDecimalFloatSlow.sol, the "slow" implementation is intentionally different from the production implementation to serve as an independent reference for fuzzing tests. The goal is to have two different approaches (expensive loops vs optimized jumps) that produce equivalent results, not identical implementations.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
📚 Learning: 2025-06-16T13:17:28.513Z
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#58
File: src/concrete/DecimalFloat.sol:175-182
Timestamp: 2025-06-16T13:17:28.513Z
Learning: In the rainlanguage/rain.math.float codebase, there's an established naming convention where functions accepting a `Float` type parameter consistently use `float` as the parameter name, even though it shadows the type name. This pattern is used throughout `LibDecimalFloat.sol` and should be maintained for consistency in related contracts like `DecimalFloat.sol`.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-26T16:50:11.113Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#111
File: test/src/lib/LibDecimalFloat.div.t.sol:48-51
Timestamp: 2025-08-26T16:50:11.113Z
Learning: In LibDecimalFloat, packLossless internally asserts that the packing operation is lossless, so there's no need to manually check the lossless flag when using packLossless instead of packLossy.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-07-24T04:32:14.171Z
Learnt from: rouzwelt
PR: rainlanguage/rain.math.float#83
File: src/concrete/DecimalFloat.sol:248-251
Timestamp: 2025-07-24T04:32:14.171Z
Learning: In the rainlanguage/rain.math.float project, functions in DecimalFloat.sol that return tuples from LibDecimalFloat calls must unpack the tuple into local variables before returning them (rather than returning directly) to maintain compatibility with Slither static analysis checks.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-14T16:56:28.978Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#99
File: src/lib/implementation/LibDecimalFloatImplementation.sol:574-581
Timestamp: 2025-08-14T16:56:28.978Z
Learning: In the rainlanguage/rain.math.float repository, maintainer thedavidmeister avoids using `&&` operators in gas-critical paths because they involve jumps in Solidity due to short-circuit evaluation, preferring approaches like mul-then-div overflow probes that avoid conditional jump overhead.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
📚 Learning: 2025-08-11T14:32:50.439Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#96
File: test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol:15-29
Timestamp: 2025-08-11T14:32:50.439Z
Learning: In test code for the rain.math.float repository, redundant checks may be intentionally kept for clarity and documentation purposes, even when they could be simplified. The maintainer (thedavidmeister) prefers explicit assertions in test code to make the test's intent clear to future readers, prioritizing readability over conciseness.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
📚 Learning: 2025-08-14T16:32:05.932Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#99
File: src/lib/implementation/LibDecimalFloatImplementation.sol:309-325
Timestamp: 2025-08-14T16:32:05.932Z
Learning: In the rainlanguage/rain.math.float repository, maintainer thedavidmeister prefers to keep assembly-based overflow checks inline for gas optimization rather than extracting them into helper functions, even when it results in code duplication.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-07-17T02:38:44.698Z
Learnt from: rouzwelt
PR: rainlanguage/rain.math.float#76
File: test_js/float.test.ts:9-32
Timestamp: 2025-07-17T02:38:44.698Z
Learning: In the rainlanguage/rain.math.float repository, the user rouzwelt accepts non-null assertions in test files because tests should throw and fail immediately when something goes wrong, making it clear where the issue occurred.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
📚 Learning: 2025-08-11T14:30:48.562Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#96
File: test/src/lib/LibDecimalFloat.ceil.t.sol:43-50
Timestamp: 2025-08-11T14:30:48.562Z
Learning: When reviewing Solidity test files using Forge, verify the actual mutability of helper functions like `bound()` before suggesting changes to function mutability specifiers, as Forge implements many test utilities as pure functions.

Applied to files:

  • test/src/lib/LibDecimalFloat.div.t.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: git-clean
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-legal)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, test-wasm-build)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-static)
  • GitHub Check: rainix (macos-latest, rainix-sol-legal)
  • GitHub Check: rainix (macos-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-static)

Comment thread test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
Comment thread test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (3)
test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol (3)

105-106: Clamp upper bound to prevent exponent overflow when subtracting −76.

Use max - 76 so exponentA - exponentB can’t overflow when oneExponent reaches -76.

-        exponent = bound(exponent, type(int256).min + 76, type(int256).max);
+        exponent = bound(exponent, type(int256).min + 76, type(int256).max - 76);

119-121: Mirror the +1 bound fix for the −1 path.

Same overflow risk; apply the symmetric ±76 headroom.

-        exponent = bound(exponent, type(int256).min + 76, type(int256).max);
+        exponent = bound(exponent, type(int256).min + 76, type(int256).max - 76);

109-116: Add a clarifying guard comment for the break.

Small readability nit: the break is solely to avoid overflowing one to 10^77 on the next iteration; make that explicit.

         for (int256 oneExponent = 0; oneExponent >= -76; --oneExponent) {
             checkDiv(signedCoefficient, exponent, one, oneExponent, expectedCoefficient, expectedExponent);
-            if (oneExponent == -76) {
-                break;
-            }
+            // Avoid overflowing `one` to 10^77 on the next iteration.
+            if (oneExponent == -76) break;
             one *= 10;
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 63310e4 and 4540187.

📒 Files selected for processing (1)
  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-21T18:03:40.347Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#107
File: test/lib/LibDecimalFloatSlow.sol:37-45
Timestamp: 2025-08-21T18:03:40.347Z
Learning: In test/lib/LibDecimalFloatSlow.sol, the "slow" implementation is intentionally different from the production implementation to serve as an independent reference for fuzzing tests. The goal is to have two different approaches (expensive loops vs optimized jumps) that produce equivalent results, not identical implementations.

Applied to files:

  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
📚 Learning: 2025-08-11T14:32:50.439Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#96
File: test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol:15-29
Timestamp: 2025-08-11T14:32:50.439Z
Learning: In test code for the rain.math.float repository, redundant checks may be intentionally kept for clarity and documentation purposes, even when they could be simplified. The maintainer (thedavidmeister) prefers explicit assertions in test code to make the test's intent clear to future readers, prioritizing readability over conciseness.

Applied to files:

  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
📚 Learning: 2025-08-14T16:56:28.978Z
Learnt from: thedavidmeister
PR: rainlanguage/rain.math.float#99
File: src/lib/implementation/LibDecimalFloatImplementation.sol:574-581
Timestamp: 2025-08-14T16:56:28.978Z
Learning: In the rainlanguage/rain.math.float repository, maintainer thedavidmeister avoids using `&&` operators in gas-critical paths because they involve jumps in Solidity due to short-circuit evaluation, preferring approaches like mul-then-div overflow probes that avoid conditional jump overhead.

Applied to files:

  • test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: rainix (ubuntu-latest, test-wasm-build)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-static)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-static)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-test)
  • GitHub Check: rainix (macos-latest, rainix-rs-test)
  • GitHub Check: rainix (macos-latest, rainix-sol-legal)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-legal)
  • GitHub Check: git-clean

Comment thread test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
Comment thread test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
Comment thread test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol
@thedavidmeister thedavidmeister merged commit b56a2b8 into main Aug 27, 2025
10 checks passed
@github-actions
Copy link
Copy Markdown

@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment:

S/M/L PR Classification Guidelines:

This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed.

Small (S)

Characteristics:

  • Simple bug fixes, typos, or minor refactoring
  • Single-purpose changes affecting 1-2 files
  • Documentation updates
  • Configuration tweaks
  • Changes that require minimal context to review

Review Effort: Would have taken 5-10 minutes

Examples:

  • Fix typo in variable name
  • Update README with new instructions
  • Adjust configuration values
  • Simple one-line bug fixes
  • Import statement cleanup

Medium (M)

Characteristics:

  • Feature additions or enhancements
  • Refactoring that touches multiple files but maintains existing behavior
  • Breaking changes with backward compatibility
  • Changes requiring some domain knowledge to review

Review Effort: Would have taken 15-30 minutes

Examples:

  • Add new feature or component
  • Refactor common utility functions
  • Update dependencies with minor breaking changes
  • Add new component with tests
  • Performance optimizations
  • More complex bug fixes

Large (L)

Characteristics:

  • Major feature implementations
  • Breaking changes or API redesigns
  • Complex refactoring across multiple modules
  • New architectural patterns or significant design changes
  • Changes requiring deep context and multiple review rounds

Review Effort: Would have taken 45+ minutes

Examples:

  • Complete new feature with frontend/backend changes
  • Protocol upgrades or breaking changes
  • Major architectural refactoring
  • Framework or technology upgrades

Additional Factors to Consider

When deciding between sizes, also consider:

  • Test coverage impact: More comprehensive test changes lean toward larger classification
  • Risk level: Changes to critical systems bump up a size category
  • Team familiarity: Novel patterns or technologies increase complexity

Notes:

  • the assessment must be for the totality of the PR, that means comparing the base branch to the last commit of the PR
  • the assessment output must be exactly one of: S, M or L (single-line comment) in format of: SIZE={S/M/L}
  • do not include any additional text, only the size classification
  • your assessment comment must not include tips or additional sections
  • do NOT tag me or anyone else on your comment

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 27, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the full diff for the PR to assess the totality of changes
git diff --stat HEAD~1 HEAD

# Get detailed diff to understand complexity
git diff HEAD~1 HEAD --name-only

# Count total lines changed
git diff --numstat HEAD~1 HEAD

# Look at the specific changes in the implementation file
git diff HEAD~1 HEAD src/lib/implementation/LibDecimalFloatImplementation.sol

# Look at the test file changes
git diff HEAD~1 HEAD test/src/lib/LibDecimalFloat.div.t.sol
git diff HEAD~1 HEAD test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol

Length of output: 1452


🏁 Script executed:

#!/bin/bash
# Check current branch and git log to understand the PR structure
git branch -a
git log --oneline -10

# Get the PR diff using the branch comparison
git diff main..HEAD --stat

# Get file names that changed
git diff main..HEAD --name-only

# Get numerical stats for changes
git diff --numstat main..HEAD

# Look at the specific implementation changes
git diff main..HEAD src/lib/implementation/LibDecimalFloatImplementation.sol

# Look at the test changes
git diff main..HEAD test/src/lib/LibDecimalFloat.div.t.sol
git diff main..HEAD test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol

Length of output: 21949


SIZE=M

@coderabbitai coderabbitai Bot mentioned this pull request Aug 27, 2025
4 tasks
This was referenced Sep 3, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Sep 23, 2025
4 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Feb 5, 2026
4 tasks
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.

1 participant