Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Security-critical contracts require code owner review from the relevant team.
/contracts/bridge/ @MettaChain/bridge
/contracts/lending/ @MettaChain/lending
/contracts/oracle/ @MettaChain/oracle
29 changes: 29 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: UTC
open-pull-requests-limit: 10
commit-message:
prefix: "chore(deps)"
labels:
- dependencies
- rust

- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
day: monday
time: "04:30"
timezone: UTC
open-pull-requests-limit: 5
commit-message:
prefix: "chore(ci)"
labels:
- dependencies
- github-actions
71 changes: 71 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Release

on:
push:
tags:
- "v*"
workflow_dispatch:

permissions:
contents: write

jobs:
release:
name: Publish Release Artefacts
runs-on: ubuntu-latest

steps:
- name: Checkout Code Repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install Stable Rust Toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache Cargo Dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-release-

- name: Install Release Tooling
run: |
cargo install cargo-deny --locked
cargo install cargo-sbom --locked

- name: Verify Dependency Policy
run: cargo deny check

- name: Generate Workspace SBOM
run: cargo sbom --output-format spdxjson23 > propchain-sbom.json

- name: Validate SBOM Shape
run: |
jq -e '
.SPDXID == "SPDXRef-DOCUMENT" and
(.creationInfo.creators | length > 0) and
(.packages | length > 0) and
(.relationships | length > 0)
' propchain-sbom.json > /dev/null

- name: Upload SBOM Workflow Artifact
uses: actions/upload-artifact@v4
with:
name: propchain-sbom
path: propchain-sbom.json

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: propchain-sbom.json
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
10 changes: 9 additions & 1 deletion .github/workflows/smoke-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ jobs:
- name: Checkout Code Repository
uses: actions/checkout@v4

- name: Validate CODEOWNERS coverage for security-critical contracts
shell: bash
run: |
test -f .github/CODEOWNERS
grep -Eq '^/contracts/bridge/\s+@MettaChain/bridge$' .github/CODEOWNERS
grep -Eq '^/contracts/lending/\s+@MettaChain/lending$' .github/CODEOWNERS
grep -Eq '^/contracts/oracle/\s+@MettaChain/oracle$' .github/CODEOWNERS

- name: Install Stable Rust Toolchain
uses: dtolnay/rust-toolchain@stable
with:
Expand All @@ -43,4 +51,4 @@ jobs:
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Run Core Verification Tests (test)
run: cargo test --all-features --workspace
run: cargo test --all-features --workspace
10 changes: 5 additions & 5 deletions contracts/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4474,7 +4474,7 @@ pub mod propchain_contracts {

/// Rejects the zero address (all 32 bytes == 0x00).
fn ensure_not_zero_address(account: AccountId) -> Result<(), Error> {
if account == AccountId::from([0x0; 32]) {
if account == AccountId::from([0x0u8; 32]) {
return Err(Error::ZeroAddress);
}
Ok(())
Expand Down Expand Up @@ -4648,7 +4648,7 @@ mod tests_pause {
#[ink::test]
fn test_pause_resume_flow() {
let mut contract = PropertyRegistry::new();
let _admin = AccountId::from([0x1; 32]);
let _admin = AccountId::from([0x1u8; 32]);

// 1. Verify initial state
assert!(!contract.get_pause_state().paused);
Expand Down Expand Up @@ -4684,7 +4684,7 @@ mod tests_pause {

// In simple unit testing here, tracking caller changes requires `ink::env::test::set_caller`.
// Let's simulate a second account approval.
let account2 = AccountId::from([0x2; 32]);
let account2 = AccountId::from([0x2u8; 32]);
ink::env::test::set_caller::<ink::env::DefaultEnvironment>(contract.admin());
assert!(contract.set_pause_guardian(account2, true).is_ok());

Expand All @@ -4699,7 +4699,7 @@ mod tests_pause {
#[ink::test]
fn test_oracle_circuit_breaker_blocks_and_resets_external_calls() {
let mut contract = PropertyRegistry::new();
let oracle = AccountId::from([0x9; 32]);
let oracle = AccountId::from([0x9u8; 32]);

let metadata = PropertyMetadata {
location: "Breaker Street".into(),
Expand Down Expand Up @@ -4740,7 +4740,7 @@ mod tests_pause {
#[ink::test]
fn test_compliance_circuit_breaker_blocks_registration() {
let mut contract = PropertyRegistry::new();
let registry = AccountId::from([0x7; 32]);
let registry = AccountId::from([0x7u8; 32]);

contract
.set_compliance_registry(Some(registry))
Expand Down
6 changes: 3 additions & 3 deletions contracts/oracle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ mod propchain_oracle {
let source = OracleSource {
id: id.clone(),
source_type: OracleSourceType::Custom,
address: AccountId::from([0x0; 32]),
address: AccountId::from([0x0u8; 32]),
is_active: true,
weight,
last_updated: self.env().block_timestamp(),
Expand Down Expand Up @@ -1934,7 +1934,7 @@ mod propchain_oracle {
let dummy_source = OracleSource {
id: source_id.clone(),
source_type: OracleSourceType::Custom,
address: AccountId::from([0x0; 32]),
address: AccountId::from([0x0u8; 32]),
is_active: false,
weight: 0,
last_updated: 0,
Expand Down Expand Up @@ -3473,7 +3473,7 @@ mod propchain_oracle {

impl Default for PropertyValuationOracle {
fn default() -> Self {
Self::new(AccountId::from([0x0; 32]))
Self::new(AccountId::from([0x0u8; 32]))
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
rules (Settings → Branches → Add rule for `main`):

- **Require a pull request before merging** — no direct pushes to `main`.
- **Require review from Code Owners** — changes under `contracts/bridge`,
`contracts/lending`, and `contracts/oracle` must be approved by the matching
owners defined in `.github/CODEOWNERS`.
- **Require signed commits** — every commit on `main` must be GPG/SSH signed.
- **Disallow force pushes** to `main`.
- **Disallow branch deletion** for `main`.
Expand All @@ -17,6 +20,13 @@ GitHub API (`PUT /repos/{owner}/{repo}/branches/main/protection`). This doc
exists so the expected configuration is written down and reviewable, and so
CI/README can reference a single source of truth for the policy.

The repository now tracks these security-sensitive paths in
`.github/CODEOWNERS`:

- `contracts/bridge`
- `contracts/lending`
- `contracts/oracle`

## Signing your commits

```
Expand Down
49 changes: 49 additions & 0 deletions docs/SBOM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# SBOM Release Artefact

Each tagged release publishes a `propchain-sbom.json` asset generated from the
workspace with `cargo sbom`.

## What ships

- **Format**: SPDX JSON 2.3
- **Asset name**: `propchain-sbom.json`
- **Source**: the Cargo workspace rooted at this repository
- **Release hook**: `.github/workflows/release.yml`

## What to look for

The most useful top-level fields are:

- `SPDXID`: confirms the document identifier.
- `creationInfo`: records when the SBOM was produced and which tool created it.
- `packages`: lists workspace crates and third-party dependencies captured from
Cargo metadata.
- `relationships`: records the dependency graph between the packages in the
document.

## Validation

The release workflow validates the generated artefact before upload by checking
that the document has the expected SPDX identifier plus non-empty
`creationInfo.creators`, `packages`, and `relationships` sections.

You can reproduce the same flow locally:

```bash
cargo install cargo-sbom --locked
cargo sbom --output-format spdxjson23 > propchain-sbom.json
jq -e '
.SPDXID == "SPDXRef-DOCUMENT" and
(.creationInfo.creators | length > 0) and
(.packages | length > 0) and
(.relationships | length > 0)
' propchain-sbom.json > /dev/null
```

## How to use it

- Review `packages` to see the exact dependency inventory captured for a
release.
- Review `relationships` to understand how a crate is pulled into the workspace.
- Pair the SBOM with `cargo deny check` and advisory scanning for compliance and
vulnerability triage.
Loading