Skip to content

create rust float lib#46

Merged
thedavidmeister merged 29 commits intomainfrom
feat/float-lib
Jun 13, 2025
Merged

create rust float lib#46
thedavidmeister merged 29 commits intomainfrom
feat/float-lib

Conversation

@0xgleb
Copy link
Contributor

@0xgleb 0xgleb commented Jun 8, 2025

Motivation

We need to be able to work with Float values in Rust but don't want to duplicate the logic

Solution

Use revm to deploy DecimalFloat contract and use the isolated environment to provide bindings to its methods. This PR starts with parse, format, add, and sub.

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

  • New Features

    • Introduced a Rust library for decimal floating-point arithmetic, providing parsing, formatting, addition, and subtraction of custom float types via an embedded EVM and Solidity contract.
    • Added workspace configuration for Rust projects, including a new crate and regression testing support.
    • Added a task to build the workspace for WebAssembly targets.
    • Added Visual Studio Code settings for Solidity development.
    • Added a new external function in the Solidity decimal float contract to enable offchain packing of floats from coefficient and exponent.
  • Chores

    • Enhanced GitHub Actions workflows with concurrency controls, expanded platform testing, and improved environment setup.
    • Updated .gitignore to exclude .direnv and target directories.
    • Introduced environment and configuration files for development tooling, including .envrc for environment management.
    • Modified flake configuration to include a new WebAssembly build task and updated development shells.
  • Documentation

    • Fixed a typographical error in a Solidity contract comment.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 8, 2025

Walkthrough

This set of changes introduces new configuration and source files for a Rust/Solidity project, enhances CI workflows, and updates development environment settings. It adds a Rust crate interfacing with a Solidity contract via an in-memory EVM, expands GitHub Actions workflows with concurrency and platform matrix improvements, and introduces .envrc, .gitignore, VSCode settings, and Nix flake enhancements. It also adds a new external function in the Solidity DecimalFloat contract and fixes a documentation typo.

Changes

File(s) Change Summary
.envrc New file to enforce nix-direnv version 3.0.6, source its script with SHA256 verification, watch flake.lock and flake.nix for changes, and activate the Nix flake with verbose output and trace enabled.
.gitignore Added .direnv and target to ignored files/directories.
.vscode/settings.json New VSCode settings file specifying Solidity compiler version "v0.8.25+commit.b61c2a91" and formatter "forge".
Cargo.toml New Rust workspace manifest defining workspace members, dependency resolver version 2, package metadata, and dependencies including alloy, revm, thiserror, and proptest.
crates/float/Cargo.toml, crates/float/proptest-regressions/lib.txt New crate manifest for rain-math-float with conditional dependencies for wasm and non-wasm targets; added proptest regression seeds file documenting failing test cases for consistent regression testing.
crates/float/src/lib.rs New Rust module implementing Float struct interfacing with a Solidity DecimalFloat contract in an in-memory EVM; provides float parsing, formatting, addition, subtraction, error handling, and comprehensive tests.
.github/workflows/git-clean.yaml, .github/workflows/rainix.yaml Enhanced CI workflows with concurrency control keyed by Git ref (excluding main branch), expanded matrix to include macOS for Rust tests, increased Nix cache GC size, added preparatory Nix develop step for Rust tasks, and removed obsolete comments.
src/lib/LibDecimalFloat.sol Fixed a typographical error in documentation comment ("WTBC" corrected to "WBTC").
flake.nix Extended flake outputs to add a test-wasm-build package running a wasm build task; customized default devShell to include this package and inherit shellHook and inputs from existing devShell.
src/concrete/DecimalFloat.sol Added new external pure function packLossless(int224 coefficient, int32 exponent) returns (Float) exposing LibDecimalFloat.packLossless for offchain use.

Sequence Diagram(s)

sequenceDiagram
    participant RustClient as Rust Calculator
    participant EVM as In-Memory EVM
    participant Contract as DecimalFloat Solidity Contract

    RustClient->>EVM: Deploy DecimalFloat bytecode at fixed address
    RustClient->>EVM: Encode call (parse/format/add/sub) and send calldata
    EVM->>Contract: Execute contract method with calldata
    Contract-->>EVM: Return result or error (ABI encoded)
    EVM-->>RustClient: Return execution result (success or revert)
    RustClient->>RustClient: Decode output or map error selector
Loading
sequenceDiagram
    participant GitHubActions
    participant Workflow as rainix.yaml Workflow
    participant Matrix as Job Matrix (Ubuntu/macOS)
    participant Nix as Nix Shell

    GitHubActions->>Workflow: Trigger workflow on push/pull_request
    Workflow->>Workflow: Apply concurrency control (keyed by ref)
    Workflow->>Nix: Run `nix develop -c rainix-sol-prelude`
    Workflow->>Matrix: Run matrix jobs (rainix-rs-test on Ubuntu/macOS, others on Ubuntu)
    Matrix->>Nix: Run test/build commands per job
Loading
sequenceDiagram
    participant DevEnv as Developer Environment
    participant Direnv as .envrc
    participant Nix as Nix Flake

    DevEnv->>Direnv: Load .envrc
    Direnv->>Direnv: Check nix-direnv version, source script if needed
    Direnv->>Direnv: Watch flake.lock and flake.nix for changes
    Direnv->>Nix: Activate flake with verbose and trace options
Loading

Possibly related PRs

  • format #26: Adds Solidity library functions and tests for decimal float formatting, complementing the Rust EVM interface for decimal floats introduced here.
  • 2025 04 15 pack #28: Modifies Solidity LibDecimalFloat packing/unpacking logic with expanded coefficient and exponent bit widths, directly related to the Rust interface changes in this PR.
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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.

@0xgleb 0xgleb self-assigned this Jun 11, 2025
@0xgleb 0xgleb marked this pull request as ready for review June 11, 2025 08:47
Copy link
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: 10

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b506dd2 and 507419a.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • flake.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • .cargo/config.toml (1 hunks)
  • .envrc (1 hunks)
  • .github/workflows/git-clean.yaml (2 hunks)
  • .github/workflows/rainix.yaml (2 hunks)
  • .gitignore (1 hunks)
  • .vscode/settings.json (1 hunks)
  • Cargo.toml (1 hunks)
  • crates/float/Cargo.toml (1 hunks)
  • crates/float/proptest-regressions/lib.txt (1 hunks)
  • crates/float/src/lib.rs (1 hunks)
  • src/lib/LibDecimalFloat.sol (1 hunks)
🧰 Additional context used
🪛 LanguageTool
crates/float/proptest-regressions/lib.txt

[uncategorized] ~2-~2: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ... in the past. It is # automatically read and these particular cases re-run before an...

(COMMA_COMPOUND_SENTENCE_2)

🔇 Additional comments (21)
src/lib/LibDecimalFloat.sol (1)

74-74: Doc typo fixed correctly
Correction from "WTBC" to "WBTC" in the inline comment improves clarity.

.vscode/settings.json (1)

2-3: VSCode Solidity settings align with contract version
Using remote compiler v0.8.25 and Forge formatter matches the codebase.

.cargo/config.toml (1)

1-3: Set wasm32 Rust flags for getrandom
Configuration enables rand crate on wasm32-unknown-unknown by setting getrandom_backend="wasm_js", matching crate feature requirements.

.github/workflows/git-clean.yaml (2)

4-7: Add concurrency control
Introducing concurrency with branch-specific groups and cancellation of stale runs helps reduce duplicate workflows. Configuration aligns with rainix.yaml updates.


38-38: Verify workspace cleanliness
Re-running git diff --exit-code after formatting and pointer generation ensures the workspace is clean.

crates/float/Cargo.toml (3)

6-10: Workspace dependencies look correct
Dependencies (alloy, revm, thiserror) are properly referenced as workspace members.


11-13: Verify WebAssembly getrandom features
Using features ["js", "js-sys"] seems appropriate for wasm32-unknown-unknown. Please confirm this aligns with your .cargo/config.toml getrandom_backend setting.


14-16: Dev-dependency setup is correct
proptest.workspace = true ensures consistent versioning for property-based tests across the workspace.

crates/float/proptest-regressions/lib.txt (1)

7-7: Seed entry format looks correct
The regression seed is present and properly formatted for re-running failure cases.

.envrc (3)

1-5: Environment bootstrap logic is sound
Version check and sourcing of nix-direnv at 3.0.6 with the specified hash ensures reproducible setups.


7-9: Automatic reload triggers are correct
Watching flake.lock and flake.nix will refresh the environment on flake changes.


10-10: Flake activation command is valid
use flake . --verbose --show-trace provides the intended verbose and trace-enabled Nix environment.

Cargo.toml (3)

1-4: Workspace configuration is accurate
Defining members = ["crates/*"] and resolver = "2" aligns with multi-crate management and Cargo's latest resolver.


5-10: Workspace package metadata is defined
Edition, version, license, and homepage are set appropriately for the workspace.


11-16: Workspace dependencies align with member crates
Versions for alloy, revm, thiserror, and proptest match the crate-level requirements.

.github/workflows/rainix.yaml (5)

4-7: Concurrency settings are well configured
Using github.ref to key concurrency and cancel in-progress runs for non-main branches optimizes CI usage.


13-15: Verify YAML syntax for matrix.task
Ensure the inline list under matrix.task is correctly parsed as an array by GitHub Actions.


39-39: Add preparatory Nix step
Running nix develop -c rainix-sol-prelude before matrix tasks sets up required environment hooks.


45-46: Confirm empty DEPLOY_BROADCAST and DEPLOY_VERIFIER usage
Setting these to "" may override defaults. Verify this matches intended deployment logic.


51-51: Dynamic task execution is correct
run: nix develop -c ${{ matrix.task }} will execute each task variant in the matrix as desired.

crates/float/src/lib.rs (1)

244-252:

Details

❓ Verification inconclusive

Investigate commented-out test case.

There's a commented-out test case for parsing large numbers with many decimals. The comment suggests uncertainty about expected behavior. This should be clarified and either:

  1. Fixed if it's a bug, or
  2. Documented with the actual limits

Would you like me to help investigate the precision limits of the DecimalFloat contract?


Investigate and document DecimalFloat precision bounds

The commented-out test in crates/float/src/lib.rs (lines 244–252) indicates that parsing
"1341234234625468391.1341234234625468391"
succeeds instead of returning an error. Please:

  • Determine and document the maximum supported integer magnitude and decimal precision for DecimalFloat::parse.
  • If this behavior is unintended, restore the test and assert that an error is returned for inputs beyond those limits.
  • If it’s expected, update the crate’s documentation to specify these bounds and remove or adapt the commented test case accordingly.

Comment on lines 1 to 5
[package]
name = "rain-math-float"
version.workspace = true
edition.workspace = true

Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Ensure crate metadata includes licensing and repository details
The manifest inherits version and edition from the workspace but omits license, repository, and description. Explicitly declaring these fields is recommended for crates.io publishing.

🤖 Prompt for AI Agents
In crates/float/Cargo.toml at lines 1 to 5, add explicit fields for license,
repository, and description to the [package] section. This involves specifying
the license type (e.g., "MIT OR Apache-2.0"), the URL of the repository, and a
brief description of the crate to ensure proper metadata for crates.io
publishing.

@0xgleb 0xgleb mentioned this pull request Jun 11, 2025
4 tasks
Copy link
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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4b59fa and 9d19c9e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • Cargo.toml (1 hunks)
  • crates/float/proptest-regressions/lib.txt (1 hunks)
  • crates/float/src/lib.rs (1 hunks)
  • src/concrete/DecimalFloat.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
crates/float/proptest-regressions/lib.txt (1)
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#46
File: crates/float/proptest-regressions/lib.txt:1-3
Timestamp: 2025-06-11T09:03:20.771Z
Learning: The file `crates/float/proptest-regressions/lib.txt` is automatically generated by proptest and should not be manually edited.
crates/float/src/lib.rs (1)
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#46
File: crates/float/src/lib.rs:112-153
Timestamp: 2025-06-11T09:07:00.591Z
Learning: Alloy generates helpers to decode full ABI-encoded error payloads, but it doesn’t generate utilities to map raw 4-byte error selectors to error types; manual mapping is required when a contract returns only the selector.
🪛 LanguageTool
crates/float/proptest-regressions/lib.txt

[uncategorized] ~2-~2: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ... in the past. It is # automatically read and these particular cases re-run before an...

(COMMA_COMPOUND_SENTENCE_2)

🔇 Additional comments (2)
crates/float/proptest-regressions/lib.txt (1)

1-9: Generated by proptest – no manual edits.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~2-~2: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ... in the past. It is # automatically read and these particular cases re-run before an...

(COMMA_COMPOUND_SENTENCE_2)

crates/float/src/lib.rs (1)

257-264: Clarify expected behaviour for invalid decimals

The test asserts that "1.2.3" parses as "1.2". If this lenient parse is intentional, add a doc comment in parse() and an explanatory // note here; if not, tighten validation and expect an error.

Comment on lines 221 to 238
prop_compose! {
fn reasonable_float()(
int_part in -10i128.pow(18)..10i128.pow(18),
decimal_places in 0u8..18u8,
decimal_part in 0u128..10u128.pow(18u32)
) -> Float {
let mut calculator = Calculator::new().unwrap();

let num_str = if decimal_places == 0 {
format!("{int_part}")
} else {
let decimal_str = format!("{decimal_part:0width$}", width = decimal_places as usize);
format!("{int_part}.{decimal_str}")
};

calculator.parse(num_str).unwrap()
}
}
Copy link
Contributor

@coderabbitai coderabbitai bot Jun 13, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

decimal_part range can overrun decimal_places

decimal_part is always drawn from 0..10^18, even when decimal_places is, say, 2.
For decimal_places = 2 this can yield "123456""1.123456" (6 decimals).
Either limit decimal_part to 10^decimal_places or truncate/pad intentionally.

🤖 Prompt for AI Agents
In crates/float/src/lib.rs between lines 221 and 238, the decimal_part range is
fixed to 0..10^18 regardless of decimal_places, which can cause the generated
decimal part to have more digits than decimal_places. To fix this, adjust the
decimal_part range dynamically to 0..10^decimal_places so that the number of
decimal digits matches decimal_places exactly, or alternatively truncate or pad
decimal_part to ensure it has the correct length corresponding to
decimal_places.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See the format! expression on line 232

Copy link
Contributor

Choose a reason for hiding this comment

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

@0xgleb
I did look at that format! call:

let decimal_str = format!("{decimal_part:0width$}", width = decimal_places as usize);

The width in a Rust format specifier is a minimum width, not a maximum.
If the decimal_part already has more than decimal_places digits, the formatter leaves it intact—it never truncates:

decimal_places = 2   // width = 2
decimal_part   = 123456
format!("{decimal_part:02}") -> "123456"   // 6 digits remain, no truncation

So with the current property generator we can still get numbers like "1.123456" when we intended only two decimal places. The earlier comment was pointing out that edge case.

Two easy fixes:

  1. Draw decimal_part from 0 .. 10u128.pow(decimal_places as u32) so the value never has too many digits.
  2. Keep the wide range but explicitly truncate/pad:
    let decimal_str = format!("{decimal_part:0width$}", width = decimal_places as usize)
        .chars()
        .take(decimal_places as usize)
        .collect::<String>();

Either way guarantees that the generated decimal strings respect decimal_places. Let me know if you’d like a patch for this.

Copy link
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: 5

♻️ Duplicate comments (2)
crates/float/src/lib.rs (1)

221-233: Duplicate of earlier comment: decimal string generator can emit more decimals than intended because the formatter only sets a minimum width.

Cargo.toml (1)

6-6: 🧹 Nitpick (assertive)

Declare rust-version to lock the MSRV
Add rust-version = "1.78" under [workspace.package] so downstream crates and CI know the minimum supported toolchain.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d19c9e and 0007e78.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • Cargo.toml (1 hunks)
  • crates/float/Cargo.toml (1 hunks)
  • crates/float/src/lib.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
crates/float/src/lib.rs (1)
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#46
File: crates/float/src/lib.rs:112-153
Timestamp: 2025-06-11T09:07:00.591Z
Learning: Alloy generates helpers to decode full ABI-encoded error payloads, but it doesn’t generate utilities to map raw 4-byte error selectors to error types; manual mapping is required when a contract returns only the selector.
🔇 Additional comments (3)
Cargo.toml (3)

1-4: Workspace configuration is correctly set
Using members = ["crates/*"] with resolver version 2 enables workspace-level dependency management and modern Cargo features.


8-8: Verify SPDX license identifier
Ensure that "CAL-1.0" is a recognized SPDX expression to prevent crates.io publishing errors.


11-17: Pinned workspace dependencies look solid
The specified versions and feature flags for alloy and revm align with your EVM integration requirements, and thiserror = "2.0.12" is up-to-date.

Comment on lines 154 to 156
pub fn parse(&mut self, str: String) -> Result<Float, CalculatorError> {
let calldata = DecimalFloat::parseCall { str }.abi_encode();

Copy link
Contributor

@coderabbitai coderabbitai bot Jun 13, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Accept &str instead of String to avoid needless allocation

parse only reads the input; taking ownership forces every caller to allocate a new String.

-pub fn parse(&mut self, str: String) -> Result<Float, CalculatorError> {
+pub fn parse(&mut self, s: &str) -> Result<Float, CalculatorError> {
     let calldata = DecimalFloat::parseCall { str }.abi_encode();

(You can keep the ABI encode call by passing s.to_owned() inside the struct literal.)
Small win, but this method sits on the hot-path.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In crates/float/src/lib.rs around lines 154 to 156, the parse function currently
takes ownership of a String, causing unnecessary allocations. Change the
function signature to accept a &str instead of String, and inside the function,
pass s.to_owned() when constructing the struct for the ABI encode call to
maintain functionality without forcing callers to allocate a new String.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

parseCall takes a String, so allocation is needed regardless

Copy link
Contributor

Choose a reason for hiding this comment

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

@0xgleb Good point—because parseCall’s generated ABI struct owns a String, the contract invocation needs the allocation no matter what. The question is just where that allocation happens:

• Current signature (String)
– Zero-cost when the caller already has an owned String.
– Forces callers holding an &str to allocate up-front via .to_string().

• Suggested signature (&str)
– Avoids the up-front allocation for &str callers, but incurs one inside parse (s.to_owned()).
– Adds a clone if the caller already has a String.

If we want the best of both worlds, a common Rust idiom is to accept an impl Into<String> (or more explicitly S: Into<String>):

pub fn parse<S: Into<String>>(&mut self, s: S) -> Result<Float, CalculatorError> {
    let calldata = DecimalFloat::parseCall { str: s.into() }.abi_encode();}

• Callers with String pass it by value—no extra clone.
• Callers with &str (or &String) pass it and pay exactly one allocation.
• The generic adds negligible monomorphisation overhead for a hot path like this.

Totally fine to keep the current API if the extra generic isn’t worth it to you; just wanted to surface the trade-off.

Copy link
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: 1

♻️ Duplicate comments (3)
crates/float/Cargo.toml (1)

1-7: Add missing crate metadata (description & repository).

The manifest still lacks a description and repository field. These are strongly recommended for crates.io publication and were pointed out in an earlier review.

 [package]
 name = "rain-math-float"
 version.workspace = true
 edition.workspace = true
 license.workspace = true
 homepage.workspace = true
+description = "Rust bindings that run the DecimalFloat Solidity library inside an in-memory EVM."
+repository  = "https://github.com/rainlanguage/rain.math.float"
crates/float/src/lib.rs (2)

154-156: Accept any Into<String> to avoid unnecessary caller allocations.

A generic signature keeps zero-cost for String callers while sparing &str callers an extra .to_string() outside the API.

-pub fn parse(str: String) -> Result<Self, FloatError> {
-    let calldata = DecimalFloat::parseCall { str }.abi_encode();
+pub fn parse<S: Into<String>>(s: S) -> Result<Self, FloatError> {
+    let calldata = DecimalFloat::parseCall { str: s.into() }.abi_encode();

228-236: Generator can emit more decimals than requested.

format!("{decimal_part:0width$}") sets a minimum width, not a cap.
If decimal_part already has > decimal_places digits the string is left intact (e.g. width = 2, value = 123456 → "123456").
Restrict the range or truncate to guarantee the decimal length matches decimal_places.

-decimal_part in 0u128..10u128.pow(18u32)
+decimal_part in 0u128..10u128.pow(decimal_places as u32)

(or explicitly take(decimal_places as usize) after formatting).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a7c1b7 and c298fa7.

📒 Files selected for processing (2)
  • crates/float/Cargo.toml (1 hunks)
  • crates/float/src/lib.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
crates/float/src/lib.rs (1)
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#46
File: crates/float/src/lib.rs:112-153
Timestamp: 2025-06-11T09:07:00.591Z
Learning: Alloy generates helpers to decode full ABI-encoded error payloads, but it doesn’t generate utilities to map raw 4-byte error selectors to error types; manual mapping is required when a contract returns only the selector.
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • 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 (ubuntu-latest, rainix-sol-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-static)
  • GitHub Check: rainix (macos-latest, rainix-rs-test)
  • GitHub Check: git-clean

Copy link
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: 4

♻️ Duplicate comments (2)
Cargo.toml (1)

5-9: Consider declaring rust-version for clearer MSRV signalling.

Even though Cargo doesn’t require it, adding the field prevents downstream users on older toolchains from accidentally pulling the crate and improves CI/tooling ergonomics.

crates/float/Cargo.toml (1)

1-6: 🛠️ Refactor suggestion

Add missing crate metadata (description and repository).
Even when inheriting fields from the workspace, crates published on crates.io should explicitly declare a description and repository for proper discoverability and linking.

Apply this diff:

 [package]
 name = "rain-math-float"
 version.workspace = true
 edition.workspace = true
 license.workspace = true
 homepage.workspace = true
+description.workspace = true
+repository.workspace = true
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c298fa7 and dbe108f.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • Cargo.toml (1 hunks)
  • crates/float/Cargo.toml (1 hunks)
  • crates/float/src/lib.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
crates/float/src/lib.rs (1)
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#46
File: crates/float/src/lib.rs:112-153
Timestamp: 2025-06-11T09:07:00.591Z
Learning: Alloy generates helpers to decode full ABI-encoded error payloads, but it doesn’t generate utilities to map raw 4-byte error selectors to error types; manual mapping is required when a contract returns only the selector.
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: rainix (ubuntu-latest, test-wasm-build)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-test)
  • GitHub Check: rainix (macos-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-static)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-test)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-static)
  • GitHub Check: git-clean
🔇 Additional comments (4)
crates/float/Cargo.toml (4)

8-10: Workspace dependencies are correctly declared.
Using workspace = true for alloy and thiserror cleanly inherits versions and keeps the manifest DRY.


12-19: Non-WASM revm dependency correctly disables default features.
The default-features = false flag here prevents the heavy default stack from being pulled in, aligning with workspace-level opt-out.


20-27: WASM target dependencies look good.
Default features for revm are disabled and getrandom is specified with JS bindings for proper WebAssembly support.


29-31: Development dependencies are appropriately scoped.
alloy with testing features and proptest via workspace = true ensures the crate has necessary test harnesses without extra version pinning.

@thedavidmeister thedavidmeister merged commit 3a1cdc0 into main Jun 13, 2025
8 checks passed
@0xgleb 0xgleb deleted the feat/float-lib branch June 13, 2025 18:47
@coderabbitai coderabbitai bot mentioned this pull request Jul 3, 2025
4 tasks
This was referenced Jul 22, 2025
@coderabbitai coderabbitai bot mentioned this pull request Aug 27, 2025
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.

Expose add and sub methods Expose parse and format methods Set up contract execution with revm

2 participants