Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 186 additions & 20 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,52 +12,218 @@ jobs:
create-artifacts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
submodules: recursive
Comment thread
fredo marked this conversation as resolved.
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1
with:
version: nightly
version: v1.7.1
Comment thread
fredo marked this conversation as resolved.
- name: Create artifacts
run: ./shell/create_artifacts.sh
- name: Verify committed Rust ABI
run: git diff --exit-code -- bindings/rust/abi/IStateOracleV1.json bindings/rust/abi/IStateOracleV2.json
- name: Upload artifact directory
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: credible-layer-contracts-artifacts
path: artifacts/
release-npm:
release-npm-verify:
Comment thread
fredo marked this conversation as resolved.
needs: create-artifacts
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
node-version: 24.18.1

- name: Download artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: credible-layer-contracts-artifacts
path: artifacts/

- name: Build npm package
id: package
run: |
set -euo pipefail
npm_version=$(jq -r '.version' package.json)
if [[ "$npm_version" != "$GITHUB_REF_NAME" ]]; then
echo "::error::npm version ${npm_version} does not match tag ${GITHUB_REF_NAME}"
exit 1
fi
package_file=$(npm pack --ignore-scripts=true --json | jq -r '.[0].filename')
if [[ ! -f "$package_file" ]]; then
echo "::error::npm pack did not create ${package_file}"
exit 1
fi
echo "package_path=${package_file}" >> "$GITHUB_OUTPUT"

- name: Upload verified npm package
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: credible-layer-contracts-npm-package
path: ${{ steps.package.outputs.package_path }}
if-no-files-found: error
retention-days: 1

release-npm:
needs: release-npm-verify
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.18.1
registry-url: https://registry.npmjs.org

# npm >= 11.5.1 is required for OIDC trusted publishing.
- name: Update npm
run: npm install -g npm@latest
- name: Download verified npm package
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: credible-layer-contracts-npm-package
path: npm-package/

- name: Publish to npm
run: |
set -euo pipefail
shopt -s nullglob
packages=(npm-package/*.tgz)
if [[ ${#packages[@]} -ne 1 ]]; then
echo "::error::Expected exactly one npm package, found ${#packages[@]}"
exit 1
fi
npm publish "${packages[0]}" --access public --ignore-scripts=true
release-cargo-verify:
needs: create-artifacts
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
exists: ${{ steps.published.outputs.exists }}
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

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

- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: credible-layer-contracts-artifacts
path: artifacts/

- name: Publish to npm
run: npm publish --access public --ignore-scripts=true
- name: Verify release inputs
run: |
set -euo pipefail
crate_version=$(cargo metadata \
--manifest-path bindings/rust/Cargo.toml \
--format-version 1 \
--no-deps | jq -r '.packages[0].version')
npm_version=$(jq -r '.version' package.json)
if [[ "$crate_version" != "$GITHUB_REF_NAME" ]]; then
echo "::error::Cargo version ${crate_version} does not match tag ${GITHUB_REF_NAME}"
exit 1
fi
if [[ "$npm_version" != "$GITHUB_REF_NAME" ]]; then
echo "::error::npm version ${npm_version} does not match tag ${GITHUB_REF_NAME}"
exit 1
fi
for interface in IStateOracleV1 IStateOracleV2; do
if ! cmp -s "artifacts/interfaces/${interface}.json" "bindings/rust/abi/${interface}.json"; then
echo "::error::Committed ${interface} Rust ABI differs from the release artifact"
diff -u "bindings/rust/abi/${interface}.json" "artifacts/interfaces/${interface}.json" || true
exit 1
fi
done

- name: Verify Cargo package
run: |
cargo fmt --manifest-path bindings/rust/Cargo.toml -- --check
cargo clippy --manifest-path bindings/rust/Cargo.toml --all-targets -- -D warnings -D clippy::pedantic
cargo test --manifest-path bindings/rust/Cargo.toml
cargo publish --manifest-path bindings/rust/Cargo.toml --dry-run

- name: Check whether version is already published
id: published
env:
CRATE_NAME: credible-layer-contracts
run: |
set -euo pipefail
crate_version=$(cargo metadata \
--manifest-path bindings/rust/Cargo.toml \
--format-version 1 \
--no-deps | jq -r '.packages[0].version')
status=$(curl \
--silent \
--show-error \
--output /dev/null \
--write-out '%{http_code}' \
--user-agent credible-layer-contracts-release \
"https://crates.io/api/v1/crates/${CRATE_NAME}/${crate_version}")
case "$status" in
200) echo "exists=true" >> "$GITHUB_OUTPUT" ;;
404) echo "exists=false" >> "$GITHUB_OUTPUT" ;;
*)
echo "::error::Unexpected crates.io response: HTTP ${status}"
exit 1
;;
esac

release-cargo:
needs: release-cargo-verify
if: needs.release-cargo-verify.outputs.exists != 'true'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Authenticate to crates.io
id: crates-io-auth
uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5

- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ steps.crates-io-auth.outputs.token }}
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.

permissions:
contents: write
uses: phylaxsystems/actions/.github/workflows/release-github.yaml@main
secrets:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
with:
artifact_name: credible-layer-contracts-artifacts
steps:
- name: Download artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: credible-layer-contracts-artifacts
path: artifacts/

- name: Create GitHub release
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mapfile -d '' artifact_files < <(find artifacts -type f -print0)
if (( ${#artifact_files[@]} == 0 )); then
echo "::error::No release artifacts were downloaded"
exit 1
fi
gh release create "$GITHUB_REF_NAME" \
"${artifact_files[@]}" \
--generate-notes \
--title "$GITHUB_REF_NAME" \
--verify-tag
49 changes: 49 additions & 0 deletions .github/workflows/solidity-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,60 @@ jobs:
- name: Test release configuration
run: python3 test/release/test_release_workflow.py

rust-bindings:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: v1.7.1
- name: Setup Rust
run: |
rustup toolchain install stable --profile minimal --component clippy,rustfmt --no-self-update
Comment thread
fredo marked this conversation as resolved.
rustup default stable
- name: Verify generated ABI and Cargo package
run: |
./shell/create_artifacts.sh
git diff --exit-code -- bindings/rust/abi/IStateOracleV1.json bindings/rust/abi/IStateOracleV2.json
cargo fmt --manifest-path bindings/rust/Cargo.toml -- --check
cargo clippy --manifest-path bindings/rust/Cargo.toml --all-targets -- -D warnings -D clippy::pedantic
cargo test --manifest-path bindings/rust/Cargo.toml
cargo publish --manifest-path bindings/rust/Cargo.toml --dry-run

rust-bindings-msrv:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Rust 1.85
run: rustup toolchain install 1.85.0 --profile minimal --no-self-update
- name: Test Rust bindings on the declared MSRV
run: cargo +1.85.0 test --manifest-path bindings/rust/Cargo.toml --all-targets

solidity-base:
uses: phylaxsystems/actions/.github/workflows/solidity-base.yaml@main
with:
# Run this separately below with a pinned Foundry version. The reusable
# workflow otherwise installs latest and can invalidate snapshots without
# any contract change.
disable-gas-snapshot: true
gas-diff-tolerance: 25

gas-snapshot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1
with:
version: v1.7.1
- name: Compare gas reports
run: FOUNDRY_PROFILE=snapshot forge snapshot --check --silent --tolerance 25

contract-compatibility:
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ docs/

artifacts/

# The Rust bindings crate is a library; consumers resolve their own lockfile.
bindings/rust/Cargo.lock
bindings/rust/target/

# macOS system files
.DS_Store
**/.DS_Store
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,32 @@ Every broadcast entrypoint in `DeployTestingAdminVerifiers.s.sol` likewise requi

## Installation

### Rust bindings

Each tagged release publishes versioned StateOracle interface bindings as the
`credible-layer-contracts` Cargo crate. Registry consumers can install it with:

```bash
cargo add credible-layer-contracts
```

For an unreleased revision, Cargo can resolve the crate directly from this
repository. Pin a commit rather than a branch or tag:

```toml
[dependencies]
credible-layer-contracts = { git = "https://github.com/phylaxsystems/credible-layer-contracts.git", rev = "<commit>" }
```

Both forms expose the historical `0.2.0` interface as
`credible_layer_contracts::state_oracle::v1::IStateOracleV1` and the current
`0.3.0` interface as `credible_layer_contracts::state_oracle::v2::IStateOracleV2`.
Future breaking changes add another interface generation rather than replacing
an existing one. The committed ABI snapshots allow git consumers to build
without installing Foundry or initializing submodules.

### Solidity development

1. Clone the repository:

```bash
Expand Down
25 changes: 25 additions & 0 deletions bindings/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "credible-layer-contracts"
version = "0.3.0"
edition = "2024"
rust-version = "1.85"
authors = ["Phylax Systems"]
license = "MIT OR Apache-2.0"
description = "Alloy Rust bindings for the Credible Layer protocol contracts"
repository = "https://github.com/phylaxsystems/credible-layer-contracts"
homepage = "https://github.com/phylaxsystems/credible-layer-contracts"
readme = "README.md"
keywords = ["ethereum", "solidity", "abi", "bindings", "credible-layer"]
publish = ["crates-io"]
include = [
"src/**",
"abi/IStateOracleV1.json",
"abi/IStateOracleV2.json",
"README.md",
"RELEASING.md",
"LICENSE-MIT",
"LICENSE-APACHE",
]

[dependencies]
alloy-sol-types = { version = "1.6.1", features = ["json"] }
Loading
Loading