Skip to content

feat: advanced crowdfunding suite, bridge deposits, campaign stats, backer badges & DAO upgrade governance#392

Open
KodeSage wants to merge 8 commits into
ShadeProtocol:mainfrom
KodeSage:feat/taskfy
Open

feat: advanced crowdfunding suite, bridge deposits, campaign stats, backer badges & DAO upgrade governance#392
KodeSage wants to merge 8 commits into
ShadeProtocol:mainfrom
KodeSage:feat/taskfy

Conversation

@KodeSage

Copy link
Copy Markdown
Contributor

Description

This PR delivers four additive features across the shade and crowdfund contracts that round out the advanced crowdfunding experience. Each integrates with the existing fundraising/payment modules, applies require_auth() and role-based access control, optimizes storage for Soroban rent, and emits detailed events for off-chain indexing:

  1. Bridge Listener Interface for External Deposits (shade, Add Bridge Listener Interface for External Deposits #364) — record confirmed cross-chain deposits via an admin-managed relayer allowlist, with replay protection.
  2. Read-Only Views for Deep Campaign Statistics (crowdfund, Add Read-Only Views for Deep Campaign Statistics #373) — aggregate campaign metrics, an organizer-only backer leaderboard, and an on-chain stats snapshot event.
  3. Gamification Badges and Achievements for Backers (crowdfund, Implement Gamification Badges and Achievements for Backers #369) — on-chain-verified achievement badges (FirstBacker, EarlyBacker, Whale, GoalGetter).
  4. DAO Governance for Protocol Upgrades (shade, Implement DAO Governance for Protocol Upgrades #357) — a council-based propose → vote → finalize flow that gates WASM upgrades.

All four are backwards compatible — no existing signature, storage key, or behavior was changed.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code refactoring
  • Test improvements
  • Other (please describe):

Related Issues

Fixes #364
Fixes #373
Fixes #369
Fixes #357

Changes Made

1. Bridge Listener Interface for External Deposits — shade (#364)

  • components/bridge.rs: admin-managed bridge-listener allowlist; record_bridge_deposit verifies the caller is a registered listener, the token is accepted, and the amount is positive.
  • Replay protection keyed on the origin-chain tx hash (ProcessedBridgeDeposit), set before state writes so concurrent retries are rejected.
  • Per-recipient/per-token running credit total for accurate state queries.
  • New DataKeys (BridgeListener, BridgeListenerCount, BridgeDeposit, BridgeDepositCount, ProcessedBridgeDeposit, BridgeCredit) + BridgeDeposit type; idempotent register/remove; detailed BridgeListenerRegistered/Removed and BridgeDepositRecorded events.

2. Read-Only Views for Deep Campaign Statistics — crowdfund (#373)

  • get_campaign_stats() — public, no-auth, no-mutation aggregate: goal, raised, total matched, matching-pool balance, contributor count, average/largest pledge, largest backer, percent funded (bps, saturating), deadline, time remaining, ended/goal-reached/executed flags.
  • get_backer_leaderboard(caller, limit) — organizer-only ranked backers (per-backer amounts are sensitive, so it's role-gated).
  • snapshot_campaign_stats(caller) — organizer-only; emits a detailed CampaignStatsSnapshotEvent for indexers/UIs and returns the stats.
  • Added a single TotalMatched DataKey (O(1) update); everything else is derived in the read view (no redundant persisted state).
  • Fixed a missing #[contractevent] on PledgeReceivedEvent that prevented the crate from compiling.

3. Gamification Badges and Achievements for Backers — crowdfund (#369)

  • BadgeKind enum: FirstBacker, EarlyBacker, Whale, GoalGetter, each with on-chain eligibility rules verified at award time.
  • award_badge(caller, backer, kind) — callable by the backer (self-claim) or organizer (role check); idempotent double-award guard; emits BadgeAwardedEvent.
  • set_badge_config(...) — organizer-only Whale threshold + EarlyBacker limit.
  • Views: has_badge, badge_awarded_at, badge_count, get_backer_badges.
  • New DataKeys (Badge, BadgeCount, WhaleThreshold, EarlyBackerLimit); badge ownership stored as a single award timestamp per (backer, kind).

4. DAO Governance for Protocol Upgrades — shade (#357)

  • components/governance.rs: admin-managed council; propose_upgradevote_on_upgrade (one member, one vote, in-window) → finalize_upgrade (quorum + simple majority ⇒ WASM swap, else Defeated). Preserves the existing admin emergency upgrade path.
  • New UpgradeProposal/ProposalStatus types and a consolidated GovState record (voting params + counters), plus GovMember/GovProposal/GovVote DataKeys.
  • Governance errors live in a separate GovernanceError enum (codes 100+) so the existing ContractError enum is untouched.
  • 11 ShadeTrait methods exposed; 6 detailed events (GovMemberAdded/Removed, GovConfigSet, UpgradeProposed, UpgradeVoteCast, UpgradeProposalFinalized) + reused ContractUpgraded.

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • All existing tests pass locally
  • I have tested this manually

Tests added per feature:

  • Bridge (shade/src/tests/test_bridge.rs) — 11 tests: registration/idempotency, deposit recording + credit accumulation, replay rejection, unauthorized/unregistered callers, unaccepted token, non-positive amount, unknown-deposit lookup.
  • Campaign stats (crowdfund/src/test.rs) — 8 tests: aggregate metrics, matching-pool reflection, overfunded/ended, leaderboard ordering + organizer-only gating, snapshot returns + emits, pre-init panic.
  • Badges (crowdfund/src/test.rs) — 15 tests: each badge's eligibility + rejection paths, config gating, self-claim vs organizer vs third-party, double-award guard, multi-badge accumulation.
  • Governance (shade/src/tests/test_governance.rs) — 15 tests: membership idempotency, config validation, full pass-and-execute flow, defeated (no quorum / tie), and every failure code (#100#107).
cargo test -p crowdfund                          # campaign stats + badges
cargo test -p shade --lib tests::test_bridge     # bridge
cargo test -p shade --lib tests::test_governance # governance

Note: the shade crate has unrelated, pre-existing compile errors on main (two half-merged features: auto_withdrawal and an escrow expired-refund path). The shade feature suites were validated by temporarily stubbing that breakage, running the isolated tests, then reverting those files to byte-identical — so no unrelated files are touched here. The crowdfund crate builds and its full suite passes.

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Screenshots (if applicable)

N/A — smart-contract changes with no UI.

Additional Notes

@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@KodeSage Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant