Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Infrastructure

- Added a `Makefile` with a `build-docker` target utilizing the `stellar/rs-soroban-sdk` image to guarantee WASM binary reproducibility, allowing anyone to verify that the deployed on-chain bytecode matches the source (#533).
- Resolved pre-existing CI debt surfaced by the `fmt` and `clippy` gates added in #403: test fixture missing bindings restored in `src/test.rs` and `src/tests/test_init.rs`, `result` double-move fixed in `src/tests/test_admin.rs`, `cargo fmt --all` drift cleared across `src/issues_test.rs` and `src/lib.rs`, and clippy lints addressed (`manual_div_ceil` in `src/lib.rs`; `dead_code` suppressed on deferred storage helpers pending the DataKey audit in #409). All three CI jobs (`test`, `fmt`, `clippy`) now exit 0 on a clean checkout (#418).

### Refactored
Expand Down
9 changes: 6 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ git remote add upstream https://github.com/Iris-IV/ProofOfHeart-stellar.git
> **Heads up:** The first `cargo build` downloads and compiles all Rust dependencies. This can take **10–20 minutes** and use **1–2 GB** of disk space. Subsequent builds are much faster.

```bash
# Build WASM
cargo build --target wasm32-unknown-unknown --release
# Build WASM (Local development)
stellar contract build

# Build reproducible WASM (Required for production deployment)
make build-docker

# Run tests
cargo test --features testutils
Expand All @@ -60,7 +63,7 @@ CI runs these checks on every PR. Run locally before pushing:
cargo fmt --check
cargo clippy --all-targets --features testutils -- -D warnings
cargo test --features testutils
cargo build --target wasm32-unknown-unknown --release
stellar contract build
```

All four must pass.
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
default: build

all: test

build:
stellar contract build

build-docker:
docker run --rm -v $(PWD):/workspace -w /workspace stellar/rs-soroban-sdk:20.1.0 stellar contract build

test:
cargo test --features testutils

fmt:
cargo fmt --all

clean:
cargo clean
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,11 @@ This repository contains the **Soroban smart contract** that powers the on-chain
git clone https://github.com/Iris-IV/ProofOfHeart-stellar.git
cd ProofOfHeart-stellar

# Build the contract
cargo build --target wasm32-unknown-unknown --release
# Build the contract for local development
stellar contract build

# Build a deterministic, reproducible WASM binary for deployment/verification
make build-docker
```

### Test
Expand Down
35 changes: 0 additions & 35 deletions src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,38 +509,3 @@ pub(crate) fn resume_campaign(env: &Env, campaign_id: u32, caller: Address) -> R

Ok(())
}

use soroban_sdk::{contractimpl, Address, Env, String};
use crate::errors::Error;

#[contractimpl]
impl ProofOfHeartContract {
/// Sets or updates the maximum funding goal cap for a specific campaign category.
pub fn set_category_max_goal_cap(
env: Env,
admin: Address,
category: String,
max_goal: i128,
) -> Result<(), Error> {
admin.require_auth();

// Verify admin permissions (assumes admin check helper exists)
Self::verify_admin(&env, &admin)?;

let cap_key = DataKey::CategoryMaxGoalCap(category.clone());
env.storage().persistent().set(&cap_key, &max_goal);

env.events().publish(
(Symbol::new(&env, "category_cap_updated"), category),
max_goal,
);

Ok(())
}

/// Retrieves the maximum funding goal cap for a given category, if defined.
pub fn get_category_max_goal_cap(env: Env, category: String) -> Option<i128> {
let cap_key = DataKey::CategoryMaxGoalCap(category);
env.storage().persistent().get(&cap_key)
}
}
7 changes: 0 additions & 7 deletions src/campaigns.rs

This file was deleted.

30 changes: 0 additions & 30 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,33 +647,3 @@ impl ProofOfHeart {

#[cfg(test)]
mod tests;

use soroban_sdk::{contract, contractimpl, Env, String, Vec};

#[contract]
pub struct ProofOfHeartContract;

#[contractimpl]
impl ProofOfHeartContract {
/// Lists active campaigns, optionally filtered by a specific tag string.
pub fn list_active_campaigns(env: Env, tag_filter: Option<String>) -> Vec<Campaign> {
let all_campaigns: Vec<Campaign> = env
.storage()
.instance()
.get(&DataKey::Campaigns)
.unwrap_or(Vec::new(&env));

match tag_filter {
Some(filter_tag) => {
let mut filtered = Vec::new(&env);
for campaign in all_campaigns.iter() {
if campaign.tags.contains(&filter_tag) {
filtered.push_back(campaign);
}
}
filtered
}
None => all_campaigns,
}
}
}
18 changes: 12 additions & 6 deletions src/tests/test_campaign_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ fn test_update_campaign_emits_title_and_description() {

let events = env.events().all();
let last_event = events.last().unwrap();
let payload: (String, String) = soroban_sdk::FromVal::from_val(&env, &last_event.2);
let payload: (String, String, String, String) =
soroban_sdk::FromVal::from_val(&env, &last_event.2);

assert_eq!(payload.0, new_title);
assert_eq!(payload.1, new_desc);
assert_eq!(payload.0, String::from_str(&env, "Original Title"));
assert_eq!(payload.1, String::from_str(&env, "Original Description"));
assert_eq!(payload.2, new_title);
assert_eq!(payload.3, new_desc);
}

#[test]
Expand Down Expand Up @@ -94,9 +97,12 @@ fn test_update_campaign_event_tracks_latest_description() {

let events = env.events().all();
let last_event = events.last().unwrap();
let payload: (String, String) = soroban_sdk::FromVal::from_val(&env, &last_event.2);
assert_eq!(payload.0, String::from_str(&env, "Title V3"));
assert_eq!(payload.1, String::from_str(&env, "Description V3"));
let payload: (String, String, String, String) =
soroban_sdk::FromVal::from_val(&env, &last_event.2);
assert_eq!(payload.0, String::from_str(&env, "Title V2"));
assert_eq!(payload.1, String::from_str(&env, "Description V2"));
assert_eq!(payload.2, String::from_str(&env, "Title V3"));
assert_eq!(payload.3, String::from_str(&env, "Description V3"));
}

#[test]
Expand Down
Loading