Skip to content

ci: use upstream rainix-rs-static reusable#198

Merged
thedavidmeister merged 10 commits into
mainfrom
2026-05-10-use-rs-static-reusable
May 10, 2026
Merged

ci: use upstream rainix-rs-static reusable#198
thedavidmeister merged 10 commits into
mainfrom
2026-05-10-use-rs-static-reusable

Conversation

@thedavidmeister
Copy link
Copy Markdown
Contributor

@thedavidmeister thedavidmeister commented May 10, 2026

Summary

  • Drops the rainix-rs-static matrix entry from rainix.yaml.
  • Adds top-level rainix-rs-static.yaml calling rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main (introduced in ci: reusable rainix-rs-static workflow rainix#146), which runs through rainix's rust-shell — no chromium/sol/node toolchains pulled in for fmt + clippy.

Test plan

  • CI green: new rainix-rs-static workflow passes.
  • Existing Rainix CI matrix still runs rainix-rs-test on both OSes and test-wasm-build on ubuntu.

🤖 Generated with Claude Code

Summary by CodeRabbit

Chores

  • Implemented automated artifact management system with consistency checks to ensure generated artifacts remain synchronized with committed versions
  • Enhanced CI/CD pipeline workflows with improved task organization and separation
  • Updated build configuration filesystem permissions and refactored development environment setup

Tests

  • Added test coverage for artifact consistency and integrity validation

Review Change Stack

Drops the `rainix-rs-static` matrix entry from rainix.yaml — replaced
by a top-level `rainix-rs-static.yaml` calling
rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main, which
runs through rainix's `rust-shell` (no chromium/sol/node).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thedavidmeister thedavidmeister self-assigned this May 10, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 10, 2026

Warning

Rate limit exceeded

@thedavidmeister has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 35 minutes and 55 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0994525b-6f2c-4ea0-9113-782de0296d4e

📥 Commits

Reviewing files that changed from the base of the PR and between 7d6e641 and 4f43e13.

📒 Files selected for processing (9)
  • .github/workflows/copy-artifacts.yaml
  • .github/workflows/rainix.yaml
  • REUSE.toml
  • crates/float/abi/DecimalFloat.json
  • crates/float/abi/TestDecimalFloat.json
  • foundry.toml
  • script/CopyArtifacts.sol
  • script/lib/LibCopyArtifacts.sol
  • test/script/CopyArtifacts.t.sol

Walkthrough

This PR establishes a system for managing Solidity contract ABI artifacts in source control. It creates a committed TestDecimalFloat.json ABI file, updates Rust bindings to load from that file instead of environment variables, adds a Forge script and test contract to synchronize and verify artifact consistency, implements a new CI workflow to enforce sync on every push, and refactors supporting Nix and Foundry configurations.

Changes

Committed Solidity ABI Artifact Management

Layer / File(s) Summary
ABI Artifact Definition
crates/float/abi/TestDecimalFloat.json
New committed ABI artifact defining packLossless, unpack, and error signatures with compiled metadata.
Rust Bindings Configuration
crates/float/src/lib.rs
alloy::sol! macro updated to load DecimalFloat and TestDecimalFloat ABIs from CARGO_MANIFEST_DIR/abi/ instead of environment variables.
Build Configuration
foundry.toml
fs_permissions array expanded to grant read access to ./out and read-write access to ./crates/float/abi/.
Artifact Synchronization & Verification
script/CopyArtifacts.sol, test/script/CopyArtifacts.t.sol
New Forge script copies compiled artifacts from ./out to committed ./crates/float/abi/ location; test contract verifies committed artifacts match generated outputs via keccak256 hash comparison.
CI Workflows & Enforcement
.github/workflows/copy-artifacts.yaml, .github/workflows/rainix-rs-static.yaml, .github/workflows/rainix.yaml
New copy-artifacts workflow builds artifacts, runs sync script, and enforces consistency via git diff --exit-code on every push; separate rainix-rs-static workflow created; rust static analysis removed from rainix matrix.
Development Environment Configuration
flake.nix, .prettierignore
Nix flake refactored to use eachDefaultSystem, shell hooks inherited from rainix, and Prettier configured to ignore crates/float/abi/ directory.
Documentation Updates
crates/float/src/fuzz_ops.rs
Comment for fuzz test helper updated; no logic changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: moving Rust static analysis from a matrix entry to an upstream reusable workflow to avoid unnecessary toolchain pulls.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2026-05-10-use-rs-static-reusable

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

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

Decouples rust crate compilation from a live `forge build`. The rust
crate's alloy::sol! macro reads from $CARGO_MANIFEST_DIR/abi/, so
`cargo build` works standalone and the rs-static reusable runs through
rainix's rust-shell without needing foundry/solc in scope.

- script/CopyArtifacts.sol: forge script that copies
  out/<Contract>.sol/<Contract>.json into crates/float/abi/<Contract>.json.
- crates/float/src/lib.rs: alloy::sol! reads from
  $CARGO_MANIFEST_DIR/abi/<Contract>.json instead of an env var.
- flake.nix: drop the env-var exports + decimal-float-abi derivation.
  See issue for design rationale.
- foundry.toml: extend fs_permissions for ./out (read) and
  ./crates/float/abi (read-write).
- .github/workflows/copy-artifacts.yaml: regen-and-diff CI step
  asserting committed copies match freshly built ones (build-pointers
  pattern).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
thedavidmeister and others added 3 commits May 10, 2026 23:46
- .prettierignore: skip crates/float/abi/. Forge writes single-line
  JSON; prettier-rainix was reformatting committed copies to multiline,
  causing copy-artifacts.yaml diff failures (CI's freshly built copies
  are single-line and don't match the pretty-printed committed copies).
- crates/float/abi/*.json: re-seed in raw forge form.
- crates/float/src/fuzz_ops.rs: change /// to // before prop_compose!
  macro invocation; rustc warns that doc comments don't attach to
  macro-generated items.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Belt-and-suspenders alongside the copy-artifacts.yaml workflow: the
solidity test runs as part of rainix-sol-test, asserting the committed
crates/float/abi/<Contract>.json matches the live forge build output
in out/. Drift fails the suite with a hint to run CopyArtifacts.sol.

Also re-seeds the committed JSONs after a clean rebuild — solc source
unit IDs in sourceMap fields shifted relative to the previous seed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.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: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/copy-artifacts.yaml:
- Around line 12-14: Remove the unnecessary Nix configuration entries from the
workflow: delete the keep-env-derivations and keep-outputs keys under the
nix_conf block so the CI run uses default Nix behavior and avoids preserving
build outputs/environments; update the nix_conf section (the block containing
keep-env-derivations and keep-outputs) to only include required options or be
omitted entirely.
- Around line 7-9: The workflow is fetching the full git history by setting
fetch-depth: 0 on the actions/checkout step; change this to a shallow clone by
removing or replacing fetch-depth: 0 (e.g., set fetch-depth: 1 or delete the
fetch-depth key) in the checkout step that uses actions/checkout@v4 so the job
only fetches the current commit and avoids unnecessary overhead.
- Around line 28-29: The CI step named "Assert committed artifacts match freshly
built" currently runs only "git diff --exit-code"; change it so the diff is
printed before the assertion to aid debugging: run a command that first displays
the diff (e.g., "git --no-pager diff" or "git diff --name-only") and then runs
"git diff --exit-code" (or combine into one run block that prints the diff and
then asserts), so the workflow will show what changed when the assertion fails.

In @.github/workflows/rainix-rs-static.yaml:
- Line 5: Replace the mutable branch reference in the workflow invocation "uses:
rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main" with an
immutable full commit SHA; locate the line containing that exact "uses:
rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main" string and
update the tail after '@' to the repository commit SHA (e.g.,
@<full-commit-sha>) to pin the reusable workflow to a specific commit for
reproducible CI.

In `@crates/float/abi/TestDecimalFloat.json`:
- Line 1: The JSON artifact file TestDecimalFloat.json is missing a trailing
newline which breaks diffs; open the committed file
(crates/float/abi/TestDecimalFloat.json) and add a single newline character at
the end of the file, save and recommit so the artifact (containing the ABI
entries like packLossless and unpack) ends with a newline.

In `@script/CopyArtifacts.sol`:
- Around line 8-11: Add a short prerequisite note to the run() function stating
that the script expects compiled artifacts in out/ (i.e., that "forge build" has
been executed) so maintainers know to run compilation first; add this as either
a NatSpec comment above run() or an inline comment referencing run() and the
helper _copyArtifact to clarify the dependency on the out/ directory.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 75f7ad0a-8b57-4008-b672-1e6416d8007f

📥 Commits

Reviewing files that changed from the base of the PR and between fe3bcd7 and 7d6e641.

📒 Files selected for processing (12)
  • .github/workflows/copy-artifacts.yaml
  • .github/workflows/rainix-rs-static.yaml
  • .github/workflows/rainix.yaml
  • .prettierignore
  • crates/float/abi/DecimalFloat.json
  • crates/float/abi/TestDecimalFloat.json
  • crates/float/src/fuzz_ops.rs
  • crates/float/src/lib.rs
  • flake.nix
  • foundry.toml
  • script/CopyArtifacts.sol
  • test/script/CopyArtifacts.t.sol
💤 Files with no reviewable changes (1)
  • .github/workflows/rainix.yaml

Comment thread .github/workflows/copy-artifacts.yaml Outdated
Comment on lines +12 to +14
nix_conf: |
keep-env-derivations = true
keep-outputs = true
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.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider removing unnecessary Nix configuration.

The keep-env-derivations and keep-outputs settings preserve build outputs and environments, which are typically useful for debugging or inspecting build artifacts. For this CI workflow that only needs to build and verify, these settings may add overhead without benefit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/copy-artifacts.yaml around lines 12 - 14, Remove the
unnecessary Nix configuration entries from the workflow: delete the
keep-env-derivations and keep-outputs keys under the nix_conf block so the CI
run uses default Nix behavior and avoids preserving build outputs/environments;
update the nix_conf section (the block containing keep-env-derivations and
keep-outputs) to only include required options or be omitted entirely.

Comment thread .github/workflows/copy-artifacts.yaml Outdated
on: [push]
jobs:
rs-static:
uses: rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP '^\s*uses:\s*[^#\n]+@(?:main|master|[A-Za-z0-9._/-]+)$' .github/workflows

Repository: rainlanguage/rain.math.float

Length of output: 1019


🏁 Script executed:

# Check for any comments or documentation about workflow pinning strategy
find .github -name "*.md" -o -name "*.txt" -o -name "*.yaml" -o -name "*.yml" | head -20

Repository: rainlanguage/rain.math.float

Length of output: 371


🏁 Script executed:

# Look for README or documentation files that might explain the workflow strategy
find . -maxdepth 2 -name "README*" -o -name "CONTRIBUTING*" | head -10

Repository: rainlanguage/rain.math.float

Length of output: 84


🏁 Script executed:

# Check if there are any comments in workflow files about the pinning strategy
rg -A 2 "uses:.*@main" .github/workflows/ -t yaml

Repository: rainlanguage/rain.math.float

Length of output: 1097


🏁 Script executed:

# Check the README for any guidance on workflow versions
cat README.md | head -100

Repository: rainlanguage/rain.math.float

Length of output: 4414


🏁 Script executed:

# Check the actual content of the rainix-rs-static.yaml file to confirm context
cat -n .github/workflows/rainix-rs-static.yaml

Repository: rainlanguage/rain.math.float

Length of output: 235


Pin the reusable workflow to an immutable commit SHA.

Using @main makes CI behavior mutable and weakens supply-chain guarantees. Pin this reusable workflow to a full commit SHA for reproducibility and tamper resistance.

Suggested change
 jobs:
   rs-static:
-    uses: rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main
+    uses: rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@<full_commit_sha>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/rainix-rs-static.yaml at line 5, Replace the mutable
branch reference in the workflow invocation "uses:
rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main" with an
immutable full commit SHA; locate the line containing that exact "uses:
rainlanguage/rainix/.github/workflows/rainix-rs-static.yaml@main" string and
update the tail after '@' to the repository commit SHA (e.g.,
@<full-commit-sha>) to pin the reusable workflow to a specific commit for
reproducible CI.

Comment thread crates/float/abi/TestDecimalFloat.json Outdated
@@ -0,0 +1 @@
{"abi":[{"type":"function","name":"packLossless","inputs":[{"name":"coefficient","type":"int224","internalType":"int224"},{"name":"exponent","type":"int32","internalType":"int32"}],"outputs":[{"name":"","type":"bytes32","internalType":"Float"}],"stateMutability":"pure"},{"type":"function","name":"unpack","inputs":[{"name":"float","type":"bytes32","internalType":"Float"}],"outputs":[{"name":"","type":"int256","internalType":"int256"},{"name":"","type":"int256","internalType":"int256"}],"stateMutability":"pure"},{"type":"error","name":"CoefficientOverflow","inputs":[{"name":"signedCoefficient","type":"int256","internalType":"int256"},{"name":"exponent","type":"int256","internalType":"int256"}]},{"type":"error","name":"ExponentOverflow","inputs":[{"name":"signedCoefficient","type":"int256","internalType":"int256"},{"name":"exponent","type":"int256","internalType":"int256"}]}],"bytecode":{"object":"0x6080604052348015600e575f80fd5b506102848061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806371516dd914610038578063b702fecd1461008c575b5f80fd5b61007261004636600461022b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116601b0b9160e09190911d90565b604080519283526020830191909152015b60405180910390f35b61009f61009a366004610242565b6100ad565b604051908152602001610083565b5f6100be83601b0b8360030b6100c5565b9392505050565b5f805f6100d28585610124565b915091508061011c576040517f22c9f7bb00000000000000000000000000000000000000000000000000000000815260048101869052602481018590526044015b60405180910390fd5b509392505050565b5f601b83900b8314838382610188577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e100000000000000000086051561016857620186a0860595506005850194505b8586601b0b1461018357600a86059550846001019450610168565b61019e565b855f0361019e57505f9250600191506102249050565b848560030b146101fa575f8512156101be57505f92508291506102249050565b6040517fd556b1110000000000000000000000000000000000000000000000000000000081526004810183905260248101829052604401610113565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791505b9250929050565b5f6020828403121561023b575f80fd5b5035919050565b5f8060408385031215610253575f80fd5b823580601b0b8114610263575f80fd5b91506020830135600381900b8114610279575f80fd5b80915050925092905056","sourceMap":"332:770:59:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f80fd5b5060043610610034575f3560e01c806371516dd914610038578063b702fecd1461008c575b5f80fd5b61007261004636600461022b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116601b0b9160e09190911d90565b604080519283526020830191909152015b60405180910390f35b61009f61009a366004610242565b6100ad565b604051908152602001610083565b5f6100be83601b0b8360030b6100c5565b9392505050565b5f805f6100d28585610124565b915091508061011c576040517f22c9f7bb00000000000000000000000000000000000000000000000000000000815260048101869052602481018590526044015b60405180910390fd5b509392505050565b5f601b83900b8314838382610188577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e100000000000000000086051561016857620186a0860595506005850194505b8586601b0b1461018357600a86059550846001019450610168565b61019e565b855f0361019e57505f9250600191506102249050565b848560030b146101fa575f8512156101be57505f92508291506102249050565b6040517fd556b1110000000000000000000000000000000000000000000000000000000081526004810183905260248101829052604401610113565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791505b9250929050565b5f6020828403121561023b575f80fd5b5035919050565b5f8060408385031215610253575f80fd5b823580601b0b8114610263575f80fd5b91506020830135600381900b8114610279575f80fd5b80915050925092905056","sourceMap":"332:770:59:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;979:121;;;;;;:::i;:::-;19261:17:51;19363:16;;19359:2;19348:32;;19409:4;19405:16;;;;;979:121:59;;;;;396:25:145;;;452:2;437:18;;430:34;;;;369:18;979:121:59;;;;;;;;599:163;;;;;;:::i;:::-;;:::i;:::-;;;1097:25:145;;;1085:2;1070:18;599:163:59;924:204:145;599:163:59;680:5;704:51;733:11;704:51;;746:8;704:51;;:28;:51::i;:::-;697:58;599:163;-1:-1:-1;;;599:163:59:o;18451:299:51:-;18539:5;18557:7;18566:13;18583:38;18593:17;18612:8;18583:9;:38::i;:::-;18556:65;;;;18636:8;18631:95;;18667:48;;;;;;;;396:25:145;;;437:18;;;430:34;;;369:18;;18667:48:51;;;;;;;;18631:95;-1:-1:-1;18742:1:51;18451:299;-1:-1:-1;;;18451:299:51:o;15810:2402::-;15895:11;16327:46;;;;;;15991:17;16047:8;16327:46;16651:668;;16708:4;16688:17;:24;:29;16684:135;;16762:3;16741:24;;;;16799:1;16787:13;;;;16684:135;17058:17;17036;17029:46;;;17022:151;;17120:2;17099:23;;;;17144:10;;;;;17022:151;;;16651:668;;;17215:17;17236:1;17215:22;17211:94;;-1:-1:-1;3653:1:51;;-1:-1:-1;17281:4:51;;-1:-1:-1;17261:25:51;;-1:-1:-1;17261:25:51;17211:94;17529:8;17516;17510:27;;;17506:393;;17731:1;17720:8;:12;17716:85;;;-1:-1:-1;3653:1:51;;-1:-1:-1;3653:1:51;;-1:-1:-1;17756:26:51;;-1:-1:-1;17756:26:51;17716:85;17825:59;;;;;;;;396:25:145;;;437:18;;;430:34;;;369:18;;17825:59:51;226:244:145;17506:393:51;-1:-1:-1;;18046:17:51;18132:28;;18166:4;18162:19;;;18129:53;;-1:-1:-1;15810:2402:51;;;;;;:::o;14:207:145:-;100:6;153:2;141:9;132:7;128:23;124:32;121:52;;;169:1;166;159:12;121:52;-1:-1:-1;192:23:145;;14:207;-1:-1:-1;14:207:145:o;475:444::-;540:6;548;601:2;589:9;580:7;576:23;572:32;569:52;;;617:1;614;607:12;569:52;656:9;643:23;710:5;706:2;695:21;688:5;685:32;675:60;;731:1;728;721:12;675:60;754:5;-1:-1:-1;811:2:145;796:18;;783:32;857:1;846:22;;;834:35;;824:63;;883:1;880;873:12;824:63;906:7;896:17;;;475:444;;;;;:::o","linkReferences":{}},"methodIdentifiers":{"packLossless(int224,int32)":"b702fecd","unpack(bytes32)":"71516dd9"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"signedCoefficient\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"exponent\",\"type\":\"int256\"}],\"name\":\"CoefficientOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"signedCoefficient\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"exponent\",\"type\":\"int256\"}],\"name\":\"ExponentOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int224\",\"name\":\"coefficient\",\"type\":\"int224\"},{\"internalType\":\"int32\",\"name\":\"exponent\",\"type\":\"int32\"}],\"name\":\"packLossless\",\"outputs\":[{\"internalType\":\"Float\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Float\",\"name\":\"float\",\"type\":\"bytes32\"}],\"name\":\"unpack\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CoefficientOverflow(int256,int256)\":[{\"details\":\"Thrown when a coefficient overflows.\"}],\"ExponentOverflow(int256,int256)\":[{\"details\":\"Thrown when an exponent overflows.\"}]},\"kind\":\"dev\",\"methods\":{\"packLossless(int224,int32)\":{\"params\":{\"coefficient\":\"The coefficient to pack.\",\"exponent\":\"The exponent to pack.\"},\"returns\":{\"_0\":\"The packed float.\"}},\"unpack(bytes32)\":{\"params\":{\"float\":\"The float to unpack.\"},\"returns\":{\"_0\":\"coefficient The coefficient of the float.\",\"_1\":\"exponent The exponent of the float.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"packLossless(int224,int32)\":{\"notice\":\"Exposes `LibDecimalFloat.packLossless` for offchain use.\"},\"unpack(bytes32)\":{\"notice\":\"Exposes `LibDecimalFloat.unpack` for offchain use.\"}},\"notice\":\"Additional exposed functions for testing the internals of floats from downstream environments, e.g. rust.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"test/concrete/TestDecimalFloat.sol\":\"TestDecimalFloat\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"appendCBOR\":false,\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\":@openzeppelin-contracts-5.6.1/=dependencies/@openzeppelin-contracts-5.6.1/\",\":forge-std-1.16.1/=dependencies/forge-std-1.16.1/\",\":mut/=dependencies/rain-string-0.2.0/src/lib/mut/\",\":parse/=dependencies/rain-string-0.2.0/src/lib/parse/\",\":rain-datacontract-0.1.0/=dependencies/rain-datacontract-0.1.0/\",\":rain-deploy-0.1.2/=dependencies/rain-deploy-0.1.2/\",\":rain-sol-codegen-0.1.0/=dependencies/rain-sol-codegen-0.1.0/\",\":rain-solmem-0.1.3/=dependencies/rain-solmem-0.1.3/\",\":rain-string-0.2.0/=dependencies/rain-string-0.2.0/\"]},\"sources\":{\"src/error/ErrDecimalFloat.sol\":{\"keccak256\":\"0x53825ff4d1af4981100de46bd7536c611625fe7930b5c21921838cfed3a92243\",\"license\":\"LicenseRef-DCL-1.0\",\"urls\":[\"bzz-raw://961197f4c7b6d560f71f67892bfd5b64300be0f0fdb20162058938567653643e\",\"dweb:/ipfs/QmTJzmA5CEkmYrXJ2MHnfQ3wGm1Qj6xE1vNaqAqgUpEnvA\"]},\"src/lib/LibDecimalFloat.sol\":{\"keccak256\":\"0x59d2dad4b7e861ed835a79c61ae42b4b0d628f9c578f3bb3ecd7796ed530f196\",\"license\":\"LicenseRef-DCL-1.0\",\"urls\":[\"bzz-raw://e565148a37f06299de3b6bcb3385ea0336f65c6c02c9ebfbc6f227f4e56d1c03\",\"dweb:/ipfs/Qma6UNZifZc8zsf7J6B87CdCXhiCR6Zisyg9czsfaji6yY\"]},\"src/lib/implementation/LibDecimalFloatImplementation.sol\":{\"keccak256\":\"0x47d0eeb542875548689465407162a19e4a21fb4591af5bb48d5758c0d1b93634\",\"license\":\"LicenseRef-DCL-1.0\",\"urls\":[\"bzz-raw://631efb796ff17f277804f8a32df7d28630c2ae5300e7d74c37aa8ed1f86b5092\",\"dweb:/ipfs/QmSfmMGQyxKYxu8UrWDEtuCggQ9HtFJy5cbMsYLPZbcTZ7\"]},\"src/lib/table/LibLogTable.sol\":{\"keccak256\":\"0xccd2dea54cfb708c01e7e8e88c089742bbab18f5783be4632311fb4923d44c88\",\"license\":\"LicenseRef-DCL-1.0\",\"urls\":[\"bzz-raw://f45fb78c16b5d66d56ba0e78acdb0ca5d315eb05efa2cd7a81e191aabe7aec52\",\"dweb:/ipfs/QmQJ3TFFxTMu4HZ4qnjgmdmSNhGZLQRdCnSqAipEF1up1f\"]},\"test/concrete/TestDecimalFloat.sol\":{\"keccak256\":\"0x4cb7ac6a794d06ffcc482d9f0451e57de56d4b434411e70d61949634c56c36c7\",\"license\":\"LicenseRef-DCL-1.0\",\"urls\":[\"bzz-raw://c1776ad378af67be27a7c98225c58b70a33b0e6ffc4c68d69e23dcf303e8a929\",\"dweb:/ipfs/QmfK9C9g5ncMkHFvSvGFAru8bvPTY9qxTzB3KPgGAn1EyG\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.25+commit.b61c2a91"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"int256","name":"signedCoefficient","type":"int256"},{"internalType":"int256","name":"exponent","type":"int256"}],"type":"error","name":"CoefficientOverflow"},{"inputs":[{"internalType":"int256","name":"signedCoefficient","type":"int256"},{"internalType":"int256","name":"exponent","type":"int256"}],"type":"error","name":"ExponentOverflow"},{"inputs":[{"internalType":"int224","name":"coefficient","type":"int224"},{"internalType":"int32","name":"exponent","type":"int32"}],"stateMutability":"pure","type":"function","name":"packLossless","outputs":[{"internalType":"Float","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"Float","name":"float","type":"bytes32"}],"stateMutability":"pure","type":"function","name":"unpack","outputs":[{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"}]}],"devdoc":{"kind":"dev","methods":{"packLossless(int224,int32)":{"params":{"coefficient":"The coefficient to pack.","exponent":"The exponent to pack."},"returns":{"_0":"The packed float."}},"unpack(bytes32)":{"params":{"float":"The float to unpack."},"returns":{"_0":"coefficient The coefficient of the float.","_1":"exponent The exponent of the float."}}},"version":1},"userdoc":{"kind":"user","methods":{"packLossless(int224,int32)":{"notice":"Exposes `LibDecimalFloat.packLossless` for offchain use."},"unpack(bytes32)":{"notice":"Exposes `LibDecimalFloat.unpack` for offchain use."}},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.6.1/=dependencies/@openzeppelin-contracts-5.6.1/","forge-std-1.16.1/=dependencies/forge-std-1.16.1/","mut/=dependencies/rain-string-0.2.0/src/lib/mut/","parse/=dependencies/rain-string-0.2.0/src/lib/parse/","rain-datacontract-0.1.0/=dependencies/rain-datacontract-0.1.0/","rain-deploy-0.1.2/=dependencies/rain-deploy-0.1.2/","rain-sol-codegen-0.1.0/=dependencies/rain-sol-codegen-0.1.0/","rain-solmem-0.1.3/=dependencies/rain-solmem-0.1.3/","rain-string-0.2.0/=dependencies/rain-string-0.2.0/"],"optimizer":{"enabled":true,"runs":1000000},"metadata":{"bytecodeHash":"none","appendCBOR":false},"compilationTarget":{"test/concrete/TestDecimalFloat.sol":"TestDecimalFloat"},"evmVersion":"cancun","libraries":{}},"sources":{"src/error/ErrDecimalFloat.sol":{"keccak256":"0x53825ff4d1af4981100de46bd7536c611625fe7930b5c21921838cfed3a92243","urls":["bzz-raw://961197f4c7b6d560f71f67892bfd5b64300be0f0fdb20162058938567653643e","dweb:/ipfs/QmTJzmA5CEkmYrXJ2MHnfQ3wGm1Qj6xE1vNaqAqgUpEnvA"],"license":"LicenseRef-DCL-1.0"},"src/lib/LibDecimalFloat.sol":{"keccak256":"0x59d2dad4b7e861ed835a79c61ae42b4b0d628f9c578f3bb3ecd7796ed530f196","urls":["bzz-raw://e565148a37f06299de3b6bcb3385ea0336f65c6c02c9ebfbc6f227f4e56d1c03","dweb:/ipfs/Qma6UNZifZc8zsf7J6B87CdCXhiCR6Zisyg9czsfaji6yY"],"license":"LicenseRef-DCL-1.0"},"src/lib/implementation/LibDecimalFloatImplementation.sol":{"keccak256":"0x47d0eeb542875548689465407162a19e4a21fb4591af5bb48d5758c0d1b93634","urls":["bzz-raw://631efb796ff17f277804f8a32df7d28630c2ae5300e7d74c37aa8ed1f86b5092","dweb:/ipfs/QmSfmMGQyxKYxu8UrWDEtuCggQ9HtFJy5cbMsYLPZbcTZ7"],"license":"LicenseRef-DCL-1.0"},"src/lib/table/LibLogTable.sol":{"keccak256":"0xccd2dea54cfb708c01e7e8e88c089742bbab18f5783be4632311fb4923d44c88","urls":["bzz-raw://f45fb78c16b5d66d56ba0e78acdb0ca5d315eb05efa2cd7a81e191aabe7aec52","dweb:/ipfs/QmQJ3TFFxTMu4HZ4qnjgmdmSNhGZLQRdCnSqAipEF1up1f"],"license":"LicenseRef-DCL-1.0"},"test/concrete/TestDecimalFloat.sol":{"keccak256":"0x4cb7ac6a794d06ffcc482d9f0451e57de56d4b434411e70d61949634c56c36c7","urls":["bzz-raw://c1776ad378af67be27a7c98225c58b70a33b0e6ffc4c68d69e23dcf303e8a929","dweb:/ipfs/QmfK9C9g5ncMkHFvSvGFAru8bvPTY9qxTzB3KPgGAn1EyG"],"license":"LicenseRef-DCL-1.0"}},"version":1},"id":59} No newline at end of file
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify committed artifact matches build output

set -euo pipefail

# Rebuild artifacts
forge build --force

# Run the copy script
forge script script/CopyArtifacts.sol

# Check for uncommitted changes
git diff --exit-code crates/float/abi/TestDecimalFloat.json || {
  echo "ERROR: Committed artifact differs from build output"
  echo "Run: forge script script/CopyArtifacts.sol"
  echo "Then commit the updated artifact"
  exit 1
}

echo "SUCCESS: Artifact is in sync"

Repository: rainlanguage/rain.math.float

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Check if the build output file exists
echo "=== Checking for build output file ==="
if [ -f "out/TestDecimalFloat.sol/TestDecimalFloat.json" ]; then
  echo "Build output found at: out/TestDecimalFloat.sol/TestDecimalFloat.json"
  echo "File size: $(wc -c < out/TestDecimalFloat.sol/TestDecimalFloat.json) bytes"
else
  echo "Build output NOT found at: out/TestDecimalFloat.sol/TestDecimalFloat.json"
fi

# Check the committed file
echo ""
echo "=== Checking committed ABI file ==="
COMMITTED_FILE="crates/float/abi/TestDecimalFloat.json"
if [ -f "$COMMITTED_FILE" ]; then
  echo "Committed file found at: $COMMITTED_FILE"
  echo "File size: $(wc -c < $COMMITTED_FILE) bytes"
  
  # Check for trailing newline
  if [ -s "$COMMITTED_FILE" ]; then
    last_char=$(tail -c 1 "$COMMITTED_FILE" | od -An -tx1)
    echo "Last byte (hex): $last_char"
    if [ "$(tail -c 1 "$COMMITTED_FILE" | wc -l)" -eq 1 ]; then
      echo "Has trailing newline: YES"
    else
      echo "Has trailing newline: NO"
    fi
  fi
else
  echo "Committed file NOT found at: $COMMITTED_FILE"
fi

# If both files exist, compare them
echo ""
echo "=== Comparing files (first 500 chars) ==="
if [ -f "out/TestDecimalFloat.sol/TestDecimalFloat.json" ] && [ -f "$COMMITTED_FILE" ]; then
  echo "Build output (first 100 chars):"
  head -c 100 "out/TestDecimalFloat.sol/TestDecimalFloat.json"
  echo ""
  echo ""
  echo "Committed (first 100 chars):"
  head -c 100 "$COMMITTED_FILE"
  echo ""
fi

Repository: rainlanguage/rain.math.float

Length of output: 455


🏁 Script executed:

#!/bin/bash
# Check if out/ directory exists
echo "=== Checking out/ directory structure ==="
if [ -d "out" ]; then
  echo "out/ directory exists"
  echo "Contents:"
  find out -type f -name "*.json" 2>/dev/null | head -20
else
  echo "out/ directory does NOT exist"
fi

# List all directories at the root level
echo ""
echo "=== Root level directories ==="
ls -la | grep "^d"

# Check the script that's mentioned in the review
echo ""
echo "=== Checking for CopyArtifacts script ==="
if [ -f "script/CopyArtifacts.sol" ]; then
  echo "Found: script/CopyArtifacts.sol"
  head -30 "script/CopyArtifacts.sol"
else
  echo "NOT found: script/CopyArtifacts.sol"
fi

Repository: rainlanguage/rain.math.float

Length of output: 1964


Add trailing newline to committed artifact.

The file crates/float/abi/TestDecimalFloat.json is missing a trailing newline, which will cause diff checks to fail. Add a newline at the end of the file to fix this.

🧰 Tools
🪛 GitHub Actions: copy-artifacts / 0_copy-artifacts.txt

[warning] 1-1: File has 'No newline at end of file' (diff output indicates missing trailing newline).


[error] 1-1: CI step failed (exit code 1) after detecting an unexpected change/diff in this ABI JSON file (packLossless/unpack ABI and bytecode/sourceMap content differed).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/float/abi/TestDecimalFloat.json` at line 1, The JSON artifact file
TestDecimalFloat.json is missing a trailing newline which breaks diffs; open the
committed file (crates/float/abi/TestDecimalFloat.json) and add a single newline
character at the end of the file, save and recommit so the artifact (containing
the ABI entries like packLossless and unpack) ends with a newline.

Comment thread script/CopyArtifacts.sol
Comment on lines +8 to +11
function run() external {
_copyArtifact("DecimalFloat");
_copyArtifact("TestDecimalFloat");
}
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.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider documenting the prerequisite.

The script assumes forge build has already been run to populate out/. Adding a comment or NatSpec to run() would make this clearer for future maintainers.

📝 Optional documentation addition
+    /// `@notice` Copy ABI artifacts from out/ to crates/float/abi/.
+    /// `@dev` Requires `forge build` to have been run first.
     function run() external {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function run() external {
_copyArtifact("DecimalFloat");
_copyArtifact("TestDecimalFloat");
}
/// `@notice` Copy ABI artifacts from out/ to crates/float/abi/.
/// `@dev` Requires `forge build` to have been run first.
function run() external {
_copyArtifact("DecimalFloat");
_copyArtifact("TestDecimalFloat");
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/CopyArtifacts.sol` around lines 8 - 11, Add a short prerequisite note
to the run() function stating that the script expects compiled artifacts in out/
(i.e., that "forge build" has been executed) so maintainers know to run
compilation first; add this as either a NatSpec comment above run() or an inline
comment referencing run() and the helper _copyArtifact to clarify the dependency
on the out/ directory.

Full forge JSON includes solc source unit IDs in metadata.sources,
sourceMap, and friends — these shift with filesystem enumeration order,
so committed-on-Mac differs from rebuilt-on-Linux even with identical
source. The diff check fights itself.

Switching the committed copy to a jq-extracted subset of stable fields
the rust crate actually consumes:
- abi (alloy::sol! type generation)
- bytecode.object (revm setup in evm.rs)
- deployedBytecode.object (revm setup)

LibCopyArtifacts shares the path conventions, the contract list and
the jq extraction between script/CopyArtifacts.sol and the
test/script/CopyArtifacts.t.sol staleness check.

`ffi = true` in foundry.toml to invoke jq from inside forge script /
test (only this script and test exercise FFI; everything else is fine).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
thedavidmeister and others added 4 commits May 11, 2026 00:17
Mirrors the same change applied to rainix's reusable workflows in
rainlanguage/rainix#148. Workflow does forge build + forge script +
git diff --exit-code; default shallow clone covers HEAD which is all
the diff check needs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the assertion fails, emit a GitHub Actions ::error:: annotation
that names the directory and the regen command. The diff itself is
already printed by `git diff --exit-code` immediately above; the
annotation surfaces in the PR UI so contributors don't have to dig
through the log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
reuse lint flagged the new .prettierignore as missing copyright/license
metadata. Add it to the existing umbrella annotation rather than
inlining a comment header (matches how .gitignore, .envrc and the rest
of the repo's metadata files are covered).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thedavidmeister thedavidmeister merged commit 88354c6 into main May 10, 2026
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 May 10, 2026

Tip

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

SIZE=M

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