Skip to content

feat(release): publish Rust contract bindings - #38

Open
fredo wants to merge 12 commits into
mainfrom
feat/rust-bindings-release
Open

feat(release): publish Rust contract bindings#38
fredo wants to merge 12 commits into
mainfrom
feat/rust-bindings-release

Conversation

@fredo

@fredo fredo commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Implements ENG-4070.

Publishes Alloy StateOracle bindings from the canonical contract ABI through crates.io while keeping npm, Cargo, and tag versions aligned. Adds OIDC trusted publishing and drift checks so public-crate and repository-pinned consumers share the same source-owned contract boundary.

Keep Cargo consumers on the same canonical ABI and release train as the
npm package.

Relates to ENG-4070.
@linear-code

linear-code Bot commented Jul 24, 2026

Copy link
Copy Markdown

ENG-4070

@socket-security

socket-security Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​alloy-sol-types@​1.7.110010093100100

View full report

Comment thread bindings/rust/Cargo.toml Outdated
readme = "README.md"
keywords = ["ethereum", "solidity", "abi", "bindings", "credible-layer"]
publish = ["crates-io"]
include = ["src/**", "abi/StateOracle.json", "README.md", "RELEASING.md"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This allowlist leaves both repository license files out of the published crate. I confirmed the package contains the manifest, documentation, ABI, and source, but neither license text. Please include both files so consumers receive the terms declared by the manifest.

version: nightly
- name: Setup Rust
run: |
rustup toolchain install stable --profile minimal --component clippy,rustfmt --no-self-update

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The manifest promises Rust 1.85, but CI only tests the moving stable toolchain. A newer language feature or dependency can raise the minimum while every check stays green. Please add a Rust 1.85 build so the published minimum remains enforced.

Comment thread .github/workflows/release.yml Outdated
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This permission is available to every step in the job, including compilation and package verification of registry dependencies. Dependency code executed there can request the same OIDC identity intended for publishing. Please move verification to a job without token permission and keep the privileged publish job minimal.

Comment thread .github/workflows/release.yml Outdated
- name: Authenticate to crates.io
if: steps.published.outputs.exists != 'true'
id: crates-io-auth
uses: rust-lang/crates-io-auth-action@v1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This privileged job follows mutable tags for checkout, artifact download, and authentication. Pin those actions to reviewed commit SHAs so a later tag update cannot gain release authority without a repository change.

name: credible-layer-contracts-artifacts
path: artifacts/
release-npm:
release-npm-verify:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Cargo verification job is the only place that rejects a generated StateOracle ABI which differs from the committed Rust snapshot, but this npm job runs in parallel and can still publish that mismatched artifact. Please make npm packaging depend on the ABI verification, or repeat the comparison here, so npm and Cargo cannot ship different contract boundaries.

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The release packages trust the output of this job, so its actions are part of the publishing boundary even though this job has no token permission. A moved checkout, Foundry, or upload action tag can still change what npm and the GitHub release publish. Please pin these actions and the Foundry version used to generate release artifacts.

run: cargo publish --manifest-path bindings/rust/Cargo.toml --no-verify
release-github:
needs: create-artifacts
runs-on: ubuntu-latest

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This job still only waits for artifact generation, so a tag that does not match either package manifest can create a public GitHub release while the version checks fail in parallel. That contradicts the documented fail before publishing behavior and leaves a release for a version the packages do not declare. Please make this job wait for both package verification jobs before calling gh release create.

uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1
with:
version: nightly
version: v1.7.1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pinning Foundry here does not pin the Solidity compiler used by forge build. foundry.toml leaves solc unset, auto detection is enabled, and these contracts use a caret pragma, so a clean runner selects the newest allowed compiler and that choice can move as new versions are released. The canonical ABI is therefore not derived from a fully fixed toolchain. Please pin the Solc version used for artifact generation as well.

self.assertIn('cp "${INTERFACES}/IStateOracleV1.json"', script)
self.assertIn('cp "${INTERFACES}/IStateOracleV2.json"', script)

def test_state_oracle_release_mapping_preserves_supported_abis(self):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This test does not preserve either ABI. It only checks the table and module names, so an additive edit to the frozen V1 interface passes here and the compatibility job only emits a warning. V1 matches the published 0.2.0 ABI today, but nothing prevents it from drifting later. Please compare the complete V1 ABI with the 0.2.0 release artifact or a pinned digest.

@phylax-ci phylax-ci left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Blocking: shell/create_artifacts.sh:73-85 regenerates and overwrites the historical V1 snapshot from the editable interface, while test/release/test_release_workflow.py:263-274 only asserts documentation and module names. Because the compatibility job treats additive ABI changes as warnings, an added V1 function or event can silently change the Rust binding advertised for the already-published 0.2.0 boundary. @fredo Next step: add one CI assertion that compares the complete normalized V1 ABI against the v0.2.0 release artifact and fails on any mismatch.

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.

3 participants