Skip to content

feat: slashing tests, multi-sig withdrawals, search utilities (#362 #367 #368 #353)#391

Merged
codebestia merged 7 commits into
ShadeProtocol:mainfrom
gregemax:feat/task-362-225-362-slashing-tests
Jul 2, 2026
Merged

feat: slashing tests, multi-sig withdrawals, search utilities (#362 #367 #368 #353)#391
codebestia merged 7 commits into
ShadeProtocol:mainfrom
gregemax:feat/task-362-225-362-slashing-tests

Conversation

@gregemax

Copy link
Copy Markdown
Contributor

Description

Implements four sequential tasks across the crowdfund and shade contracts: comprehensive test suites for the slashing mechanism and multi-sig withdrawal feature, the full multi-sig massive withdrawal implementation, and on-chain search/filtering utilities.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Test improvements

Related Issues

Fixes #362
Fixes #367
Fixes #368
Fixes #353

Changes Made

#362 – Slashing Mechanism Tests (crowdfund)

  • contracts/crowdfund/tests/test_feature_225.rs — 46 tests: happy-path, unauthorized access, event emission, storage rollback, edge cases

#367 – Multi-Sig Requirements for Massive Withdrawals (shade)

  • types.rs — 6 new DataKey variants, WithdrawalProposalStatus, WithdrawalProposal, MultiSigConfig
  • errors.rs — 10 new error codes (55–64)
  • events.rs — 6 detailed events: threshold set, config, proposed, approved, executed, cancelled
  • components/multisig_withdrawal.rs — 326-line component with atomic quorum execution
  • interface.rs — 9 new ShadeTrait methods
  • shade.rs — 9 new contractimpl delegations

#368 – Multi-Sig Withdrawal Tests (shade)

  • src/tests/test_feature_231.rs — 57 tests: happy-path (11), unauthorized (18), events (7), rollback (4), edge cases (17)
  • src/tests/mod.rs — registered test_feature_231

#353 – On-Chain Search and Filtering Utilities (shade)

  • types.rs — 7 new types: SubscriptionPlanFilter, SubscriptionFilter, EventFilter, WithdrawalProposalFilter, PageInfo, InvoicePage, MerchantPage
  • events.rs — 4 search-executed events for off-chain indexing
  • components/search.rs — 492-line component: paginated invoice/merchant search, subscription plan/subscription/event/withdrawal proposal filtering
  • interface.rs — 7 new ShadeTrait methods
  • shade.rs — 7 new contractimpl delegations

Testing

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

Test coverage added: 46 tests (crowdfund slashing) + 57 tests (shade multi-sig) = 103 new tests

Checklist

  • My code follows the project style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes

Additional Notes

Four individual commits on branch feat/task-362-225-362-slashing-tests:

gregemax added 4 commits June 30, 2026 02:16
…ocol#362

Add tests/test_feature_225.rs with 46 tests covering:
- Happy-path: single/majority backer approval, sequential milestone releases,
  mixed votes, pledge tracking, goal_reached flag
- Unauthorized access: non-backer vote, double vote, locked milestone release,
  release without majority, double release, pre-deadline release, goal-not-met
  release, execute_campaign blocked in milestone mode, invalid index panics,
  invalid milestone sum/zero-entry panics, majority rejection
- Event emission: MilestoneUnlocked, MilestoneVoteCast, MilestoneReleased,
  CampaignExecuted, RefundClaimed, BatchRefundProcessed
- Storage rollback: failed release state preserved, duplicate vote tally
  unchanged, double-init preserves original state, post-deadline contribute
  does not mutate raised amount
- Edge cases: no milestones set, approval exactly at 50% threshold,
  one-unit-above majority, zero/negative/invalid amounts, uninitialized
  contract accessors, single 100% milestone, many small milestones,
  batch refund with no contributors, off-by-one index bounds
…Protocol#367

New DataKey variants (types.rs):
  MultiSigThreshold(Address), MultiSigSigners, MultiSigQuorum,
  WithdrawalProposal(u64), WithdrawalProposalCount,
  WithdrawalApproval(u64, Address)

New types (types.rs):
  WithdrawalProposalStatus enum (Pending/Executed/Cancelled)
  WithdrawalProposal struct (id, merchant, token, amount, recipient,
    approvals, status, created_at, updated_at, note)
  MultiSigConfig struct (threshold, signers, quorum)

New errors (errors.rs): BelowMultiSigThreshold, MultiSigSignersNotSet,
  InvalidQuorum, NotASigner, AlreadyApproved, ProposalNotFound,
  ProposalNotPending, QuorumNotReached, NotProposer, ThresholdNotSet

New events (events.rs): MultiSigThresholdSetEvent,
  MultiSigConfiguredEvent, WithdrawalProposedEvent,
  WithdrawalApprovedEvent, WithdrawalExecutedEvent,
  WithdrawalCancelledEvent — each with full structural metadata

New component (components/multisig_withdrawal.rs):
  set_multisig_threshold, get_multisig_threshold, configure_multisig,
  get_signers, get_quorum, propose_withdrawal, approve_withdrawal
  (auto-executes at quorum via MerchantAccountWithdrawClient),
  cancel_withdrawal, get_withdrawal_proposal, has_approved,
  get_proposal_count

ShadeTrait interface (interface.rs): 9 new public functions exposed

Shade impl (shade.rs): delegate all 9 functions to multisig_component,
  guarded by pausable_component::assert_not_paused
…ol#368

Add src/tests/test_feature_231.rs with 57 tests covering:

Happy-path (11):
  set/get threshold, configure multisig stores quorum, pending proposal
  fields, proposal IDs increment, single approval at quorum-1 executes,
  two approvals at quorum-2 executes, approval count before quorum,
  has_approved reflects votes, merchant cancel, admin cancel,
  threshold update, multisig reconfiguration

Unauthorized/malicious (18):
  non-admin cannot set threshold or configure multisig, non-signer cannot
  approve, double vote rejected, stranger cannot cancel, below-threshold
  proposal rejected, zero-amount rejected, approve/cancel nonexistent
  proposal, approve cancelled/executed proposal, cancel executed proposal,
  quorum=0 panics, quorum>signers panics, empty signer list panics,
  exact-threshold boundary accepted, non-merchant cannot propose,
  propose without multisig configured panics

Event emission (7):
  threshold set, multisig configured, withdrawal proposed, approval
  pre-quorum, execution at quorum emits >=2 events, cancellation,
  multiple proposals emit distinct events

Storage rollback (4):
  duplicate vote does not increment count, failed proposal does not
  advance counter, failed cancel leaves status Pending, bad configure
  does not overwrite good config

Edge cases (17):
  proposal count zero initially, has_approved false for unknown proposal,
  get_threshold unset panics, threshold=0 rejects proposals,
  quorum==signer_count requires all, large amount no overflow, multiple
  proposals isolated, cancel one does not affect other, 1-of-1 executes,
  get nonexistent proposal panics, threshold increase blocks old amount,
  paused blocks propose/approve/cancel, note stored correctly,
  timestamps recorded on proposal

Register in src/tests/mod.rs
…l#353

New filter types (types.rs):
  SubscriptionPlanFilter (merchant, active, token)
  SubscriptionFilter (plan_id, customer, status)
  EventFilter (merchant, cancelled, start_date, end_date, min_available)
  WithdrawalProposalFilter (merchant, status, token, created_after)
  PageInfo (count, next_cursor, has_next_page)
  InvoicePage (items, page_info)
  MerchantPage (items, page_info)

New events (events.rs):
  InvoiceSearchExecutedEvent (caller, result_count, has_next_page, timestamp)
  SubscriptionPlanSearchExecutedEvent (caller, result_count, timestamp)
  EventSearchExecutedEvent (caller, result_count, timestamp)
  WithdrawalProposalSearchExecutedEvent (caller, result_count, timestamp)

New component (components/search.rs, 492 lines):
  search_invoices_paginated  — cursor-based pagination over InvoiceFilter
  search_merchants_paginated — cursor-based pagination over MerchantFilter
  search_subscription_plans  — filter plans by merchant/active/token
  search_subscriptions       — filter by plan_id/customer/status
  search_events              — filter by merchant/cancelled/date/seats
  search_withdrawal_proposals — filter by merchant/status/token/created_after
  find_merchant_id           — address → merchant ID lookup

ShadeTrait interface (interface.rs): 7 new public methods
Shade impl (shade.rs): 7 new delegations to search_component
@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@gregemax 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

@codebestia codebestia merged commit f81ad71 into ShadeProtocol:main Jul 2, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants