Skip to content

Commit 41e4a1a

Browse files
authored
Merge pull request #501 from temitope-007/fix-duplicate-contributor-count
Fix #195: Add contributor_count increment guard to prevent duplicate counting
2 parents fd62d2b + e721055 commit 41e4a1a

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

contracts/src/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub enum DataKey {
5151
MinContribution,
5252
ExtensionRequest(u64),
5353
ExtensionVote(u64, Address),
54+
HasContributed(u64, Address), // (campaign_id, contributor)
5455
/// Tracks which (old_contract_id, campaign_id) pairs have already been migrated.
5556
MigratedId(Address, u64),
5657
}
@@ -372,12 +373,16 @@ impl StellarGoalVaultContract {
372373
campaign.pledged_amount += amount;
373374

374375
// Only increment contributor_count on first-time pledge
375-
let contribution_key = DataKey::Contribution(campaign_id, contributor.clone(), token.clone());
376-
let current_contribution: i128 = env.storage().persistent().get(&contribution_key).unwrap_or(0);
377-
if current_contribution == 0 {
376+
let has_contributed_key = DataKey::HasContributed(campaign_id, contributor.clone());
377+
let has_contributed: bool = env.storage().persistent().get(&has_contributed_key).unwrap_or(false);
378+
if !has_contributed {
378379
campaign.contributor_count += 1;
380+
env.storage().persistent().set(&has_contributed_key, &true);
379381
}
380382

383+
let contribution_key = DataKey::Contribution(campaign_id, contributor.clone(), token.clone());
384+
let current_contribution: i128 = env.storage().persistent().get(&contribution_key).unwrap_or(0);
385+
381386
// Write updated campaign back to storage
382387
env.storage()
383388
.persistent()

contracts/src/test.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,38 @@ mod tests {
725725
assert_eq!(client.get_contributor_count(&campaign_id), 1);
726726
}
727727

728+
729+
#[test]
730+
fn test_contributor_count_no_double_count_multiple_tokens() {
731+
let env = Env::default();
732+
env.mock_all_auths();
733+
734+
let creator = Address::generate(&env);
735+
let contributor = Address::generate(&env);
736+
let admin = Address::generate(&env);
737+
738+
let token1 = deploy_token(&env, &admin, &contributor, 1_000);
739+
let token2 = deploy_token(&env, &admin, &contributor, 1_000);
740+
let client = deploy_contract(&env);
741+
742+
let campaign_id = client.create_campaign(
743+
&creator,
744+
&soroban_sdk::vec![&env, token1.clone(), token2.clone()],
745+
&1_000_i128,
746+
&(env.ledger().timestamp() + 1_000),
747+
&String::from_str(&env, "multiple tokens pledge test"),
748+
&0_i128,
749+
);
750+
751+
// Contributor pledges with token1
752+
client.contribute(&campaign_id, &contributor, &token1, &400);
753+
assert_eq!(client.get_contributor_count(&campaign_id), 1);
754+
755+
// Contributor pledges with token2 - count should remain 1
756+
client.contribute(&campaign_id, &contributor, &token2, &300);
757+
assert_eq!(client.get_contributor_count(&campaign_id), 1);
758+
}
759+
728760
// ── #184: minimum contribution tests ──────────────────────────────────────
729761

730762
#[test]

0 commit comments

Comments
 (0)