feat: multi-campaign registry contract (milestonex-campaigns-registry) - #65
Merged
Conversation
MillestoneX#44) Adds a new, additive contracts-registry crate supporting many campaigns in one instance (create_campaign/donate/end_campaign/cancel_campaign, all scoped by campaign_id), per issue MillestoneX#44's acceptance criteria. Does not modify milestonex-campaign, which remains canonical for the single-campaign use case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Issue #44 asks for a contract-level multi-campaign registry, since
milestonex-campaignis single-campaign-per-instance by design. This adds a new, additive contract crate —campaigns-registry/(milestonex-campaigns-registry) — implementing the API the issue's acceptance criteria describes:create_campaign(creator, metadata) -> u64donate(donor, campaign_id, amount, asset)end_campaign(campaign_id)/cancel_campaign(campaign_id)— creator-driven status transitions, plus automaticActive→GoalReachedon donationget_campaign(campaign_id)/get_campaign_status(campaign_id)/campaign_count()— read viewsMAX_CAMPAIGNS_PER_INSTANCEconstant (10,000), enforced increate_campaignDataKey::Campaign(id),DataKey::DonorData(id, donor))Errorenum whose discriminants numerically matchmilestonex-campaign::types::Errorwherever the two contracts share a concept (see doc comment oncampaigns-registry::types::Error)This does not modify
milestonex-campaign— the "Option B (conservative)" canonical-contract decision in the README is unchanged;campaign/remains canonical for single-campaign deployments.campaigns-registryis a separate, additive contract for the many-campaigns-per-instance casecampaign/intentionally doesn't cover.Full API, storage-scoping model, migration plan, and explicitly-deferred scope (milestones, refunds, multi-asset release, freeze/upgrade, reentrancy lock, diagnostics, real token custody — none of which are in issue #44's acceptance criteria) are written up in docs/multi-campaign.md.
On the "Issue 9 (type unification)" dependency
Issue #44 lists "Issue 9 (type unification)" as a dependency. I checked GitHub issue #9 in this repo — it's about
donate's per-milestone read loop, not type unification, so that cross-reference doesn't currently resolve to a tracked issue here. Separately, I found thatmilestonex-common'sCampaignStatus/AssetInfotypes are already unused bycampaign/(it depends oncommonbut never imports it) and have drifted from whatcampaignactually implements.campaigns-registryfollowscampaign's own practical approach (local types, nocommondependency) rather than the aspirational shared crate. Both points are written up in docs/multi-campaign.md's "Type unification note" in case a type-unification issue needs to be filed separately.This is a major feature — flagging for roadmap review
The issue itself asks to "coordinate with roadmap" given the scope. This PR is a complete, tested starting point for that review, not a claim that rollout details (whether this becomes the recommended path for new multi-campaign integrations, deployment plumbing, etc.) are already decided.
Closes #44
Test plan
create_campaign_tests.rs,donate_tests.rs,status_transition_tests.rs, andconcurrent_campaigns_tests.rs(the last directly covers the acceptance criteria's "5+ concurrent campaigns, distinct counters, distinct statuses" requirement), plus 3 error-table tests intypes.rsmirroringcampaign's own error-code test pattern.cargo check/cargo test/cargo fmtfor this crate. This environment's MSVC linker fails buildingproc-macro2's build script (pre-existing, environment-level — same failure occurs onmainbefore this PR's changes, e.g. buildingcampaignitself hits the identical error). Every function in this PR was written by closely mirroring already-compiling code incampaign/src/*.rs(same storage/TTL patterns, samepanic_with_error!/validate_campaign_transitionidioms, same test fixture style viaenv.as_contract+env.register_contract), and I did a manual line-by-line review against those proven patterns, but this has not been compiler-verified. Please runcargo test -p milestonex-campaigns-registryin CI/a working toolchain before merge — I'd expect at most minor fixes needed, but I can't rule that out without a working build.🤖 Generated with Claude Code