Skip to content

Expose fromFixedDecimalLosslessPacked#68

Merged
hardyjosh merged 10 commits intomainfrom
feat/from-fixed-decimal
Jun 24, 2025
Merged

Expose fromFixedDecimalLosslessPacked#68
hardyjosh merged 10 commits intomainfrom
feat/from-fixed-decimal

Conversation

@0xgleb
Copy link
Copy Markdown
Contributor

@0xgleb 0xgleb commented Jun 17, 2025

Motivation

We need to use Solidity Float code in Rust

Solution

Expose fromFixedDecimalLosslessPacked

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

    • Added support for serializing and deserializing floating-point values.
    • Introduced a new method to convert fixed decimal values to floating-point format.
    • Added a new contract function for converting fixed decimal values to floating-point representation for offchain use.
  • Tests

    • Added tests to verify serialization, deserialization, and decimal-to-float conversion, including property-based tests.

@0xgleb 0xgleb self-assigned this Jun 17, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 17, 2025

"""

Walkthrough

The changes introduce serialization support for the Float struct by deriving Serialize and Deserialize traits, switch its internal representation to B256, and add a new method for constructing Float from fixed decimal values via a Solidity contract function. Related tests and dependencies are updated accordingly.

Changes

File(s) Change Summary
Cargo.toml Added serde crate (v1.0.219) as a workspace dependency.
crates/float/Cargo.toml Added serde as a workspace dependency; added serde_json (v1.0.140) as a dev-dependency.
crates/float/src/lib.rs Changed Float to wrap B256, derived Serialize/Deserialize, added from_fixed_decimal method, updated tests, made pack_lossless public.
src/concrete/DecimalFloat.sol Added fromFixedDecimalLosslessPacked function to DecimalFloat contract for offchain conversion.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Rust_Float
    participant Solidity_Contract

    User->>Rust_Float: Float::from_fixed_decimal(value, decimals)
    Rust_Float->>Solidity_Contract: fromFixedDecimalLosslessPacked(value, decimals)
    Solidity_Contract-->>Rust_Float: Float (B256)
    Rust_Float-->>User: Result<Float, FloatError>
Loading

Possibly related PRs

  • create rust float lib #46: Extends and modifies the same Float struct and its contract interactions, providing the foundation for the current changes.

Suggested labels

enhancement

Suggested reviewers

  • findolor
  • hardyjosh
    """

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6d179f2 and 27ddf9e.

📒 Files selected for processing (1)
  • crates/float/src/lib.rs (7 hunks)
🧰 Additional context used
🧠 Learnings (1)
crates/float/src/lib.rs (1)
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#68
File: crates/float/src/lib.rs:134-135
Timestamp: 2025-06-21T11:07:19.190Z
Learning: In Alloy primitives library, B256 is a type alias for FixedBytes<32> (pub type B256 = FixedBytes<32>), making them completely interchangeable in type usage. Changing between these types is not a breaking change.
⏰ 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 (ubuntu-latest, rainix-rs-static)
  • GitHub Check: rainix (ubuntu-latest, rainix-sol-static)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-test)
  • GitHub Check: rainix (macos-latest, rainix-rs-test)
  • GitHub Check: git-clean
🔇 Additional comments (6)
crates/float/src/lib.rs (6)

2-2: LGTM: Import additions are necessary and well-organized.

The new imports are all properly utilized:

  • B256 for the updated Float struct
  • U256 for the new from_fixed_decimal method
  • serde traits for serialization support

Also applies to: 11-11, 13-13


134-135: Excellent addition of serialization support for Rust interoperability.

The changes perfectly align with the PR objective:

  • Using B256 (which is a type alias for FixedBytes<32>) is conventional in Ethereum Rust projects
  • Adding Serialize and Deserialize traits enables JSON serialization, making the Float type more usable in Rust environments

138-148: Well-implemented method that achieves the PR objective.

The from_fixed_decimal method properly:

  • Encodes the Solidity function call using the correct ABI encoding
  • Handles errors consistently with other methods via execute_call
  • Returns the appropriate Float type wrapping the decoded result
  • Exposes the fromFixedDecimalLosslessPacked Solidity functionality to Rust as intended

150-150: Good API expansion for broader Rust usage.

Making pack_lossless public is a sensible change that:

  • Expands functionality available to Rust users
  • Maintains existing behavior and error handling
  • Is non-breaking since it only increases visibility

402-406: Comprehensive test coverage for serialization functionality.

The serde tests are well-designed:

  • test_serde() validates the exact serialization format for API stability
  • proptest_serde() provides property-based testing ensuring round-trip consistency
  • Both tests properly verify equality using the Float::eq method

This gives confidence in the serialization implementation.

Also applies to: 432-453


817-891: Thorough test coverage for the new from_fixed_decimal method.

The tests comprehensively cover:

  • Basic conversion cases with realistic scenarios (zero values, different decimal places)
  • Error handling with U256::MAX which properly triggers overflow conditions
  • Property-based testing comparing results with pack_lossless to ensure consistency
  • Valid range testing with proper assumptions for non-negative coefficients

This provides strong confidence in the implementation correctness.

✨ 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 linked an issue Jun 17, 2025 that may be closed by this pull request
@0xgleb 0xgleb linked an issue Jun 17, 2025 that may be closed by this pull request
@0xgleb 0xgleb marked this pull request as ready for review June 20, 2025 12:00
@0xgleb 0xgleb requested review from findolor and hardyjosh June 20, 2025 12:14
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: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fac873b and edb8d22.

📒 Files selected for processing (1)
  • crates/float/src/lib.rs (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: rainix (ubuntu-latest, test-wasm-build)
  • GitHub Check: rainix (ubuntu-latest, rainix-rs-test)
  • 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: git-clean
🔇 Additional comments (5)
crates/float/src/lib.rs (5)

2-2: Imports look good.

All added imports are necessary for the new functionality - B256 for the Float struct, and serde for serialization support.

Also applies to: 11-11, 13-13


138-148: New from_fixed_decimal method implementation looks correct.

The method follows the established pattern for Solidity function calls and provides appropriate error handling. This successfully exposes the fromFixedDecimalLosslessPacked functionality as intended.


150-150: Making pack_lossless public expands the API surface.

This change allows external code to construct Float values directly from coefficient and exponent, which provides useful flexibility. This is a good complement to the new from_fixed_decimal method.


346-399: Excellent test coverage for serialization functionality.

The tests comprehensively verify:

  • Default trait implementation
  • Specific serialization format (hex string)
  • Round-trip serialization for arbitrary Float values

The property-based test is particularly valuable for ensuring serialization robustness.


763-802: Comprehensive test coverage for from_fixed_decimal.

The tests effectively cover:

  • Edge cases (zero with various decimals)
  • Normal conversions
  • Error handling for overflow scenarios
  • Property-based testing to ensure consistency with pack_lossless

The property test correctly constrains coefficients to non-negative values matching the U256 input type.

Comment thread crates/float/src/lib.rs
Comment on lines +134 to +135
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct Float(pub B256);
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Jun 21, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Note: Changing the Float struct's inner type is a breaking change.

The change from FixedBytes<32> to B256 modifies the public API. Any external code that pattern matches on Float(FixedBytes<32>) or otherwise depends on the exact type will break. Consider documenting this in the changelog or release notes.

The addition of Serialize and Deserialize traits is excellent for the goal of enabling Rust usage.

🤖 Prompt for AI Agents
In crates/float/src/lib.rs at lines 134-135, the Float struct's inner type was
changed from FixedBytes<32> to B256, which is a breaking change affecting
external code relying on the original type. To address this, update the
changelog or release notes to clearly document this API change so users are
aware of the impact. No code modification is needed here beyond ensuring proper
documentation of the breaking change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

B256 is an alias for FixedBytes<32>

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.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for B256 type definition or alias in the codebase to verify the user's claim
rg -A 5 -B 5 "type B256|pub type B256" 

# Also search for any documentation about B256 being an alias
rg -A 3 -B 3 "B256.*FixedBytes|FixedBytes.*B256"

Length of output: 485


🌐 Web query:

alloy primitives B256 type definition FixedBytes alias

💡 Result:

Definition of B256 in Alloy Primitives

B256 is a type alias provided by the Alloy primitives Rust library, widely used in Ethereum-related Rust projects such as Foundry, reth, and revm.

Type Alias Definition

  • B256 is defined as a type alias for a 32-byte fixed-size byte array:

    pub type B256 = FixedBytes<32>;
    

    This means B256 and FixedBytes<32> are interchangeable in type usage[4].

  • The underlying type for B256 is a struct holding an array of 32 bytes:

    struct B256(pub [u8; 32]);
    

    This struct encapsulates the bytes and provides implementations and traits relevant to Ethereum-style fixed-length data[4].

Related Type Aliases

Alloy provides similar type aliases for various sizes of fixed-length byte arrays, such as:

  • B8: 1 byte
  • B16: 2 bytes
  • B32: 4 bytes
  • B64: 8 bytes
  • B128: 16 bytes
  • B192: 24 bytes
  • B224: 28 bytes
  • B256: 32 bytes
  • B512: 64 bytes
  • B1024: 128 bytes[2]

These aliases make it easy to work with byte arrays matching the sizes commonly used in Ethereum and Solidity smart contracts.

Usage Context

  • B256 is commonly used to represent 32-byte data such as hashes (e.g., block hash, transaction hash) in Ethereum-like blockchains[2][4].
  • Its fixed size and named alias help clarify intent and ensure type safety in contracts, protocol code, and storage layers.
  • The FixedBytes generic struct and its type aliases (like B256) are part of the alloy_primitives crate, which standardizes these primitives across many EVM-based Rust projects[1][2][4].

Example Usage

use alloy_primitives::{B256, FixedBytes};

// Create a B256 instance from a 32-byte array
let my_hash: B256 = FixedBytes::<32>::from([0u8; 32]);

This example illustrates that B256 is simply a more readable alias for FixedBytes<32>[1][4].

Summary Table

Alias Definition Byte Length Typical Use
B256 FixedBytes<32> 32 Hashes, 32-byte EVM data

References to Source

  • B256 is defined as pub type B256 = FixedBytes<32>;, a 32-byte fixed byte-array type[2][4].
  • The FixedBytes generic allows for arbitrary fixed-size byte arrays, with aliases like B256 for convenience[1][2].

This approach standardizes handling of fixed-size byte arrays in Rust for Ethereum and related applications.

Citations:


@0xgleb You're absolutely correct! Thank you for the clarification.

The web search confirms that B256 is indeed a type alias for FixedBytes<32> in the Alloy primitives library:

pub type B256 = FixedBytes<32>;

Since they are completely interchangeable types, the change from FixedBytes<32> to B256 is not a breaking change. I apologize for the incorrect analysis in my previous comment. The change is purely cosmetic and uses the more conventional alias that's commonly used in Ethereum-related Rust projects.

The addition of Serialize and Deserialize traits remains a great improvement for enabling Rust usage of the Float code.


✏️ Learnings added
Learnt from: 0xgleb
PR: rainlanguage/rain.math.float#68
File: crates/float/src/lib.rs:134-135
Timestamp: 2025-06-21T11:07:19.152Z
Learning: In Alloy primitives library, B256 is a type alias for FixedBytes<32> (pub type B256 = FixedBytes<32>), making them completely interchangeable in type usage. Changing between these types is not a breaking change.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@hardyjosh hardyjosh merged commit ab2d750 into main Jun 24, 2025
8 checks passed
@0xgleb 0xgleb deleted the feat/from-fixed-decimal branch June 24, 2025 11:32
This was referenced Jul 18, 2025
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.

Add ser/de to Float Expose fromFixedDecimalLossless

3 participants