Skip to content

Commit a9b7fe2

Browse files
authored
Merge pull request #17 from Bug-Hunter-X/fix-14-implement-campaign-status-update-in-boundless-contract
Fix: Implement Campaign Status Update in Boundless Contract
2 parents aabbed2 + 2497ac6 commit a9b7fe2

File tree

8 files changed

+1887
-7
lines changed

8 files changed

+1887
-7
lines changed

contracts/boundless/src/logic/campaign.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,32 @@ impl CampaignManagement for BoundlessContract {
9595
Ok(())
9696
}
9797

98-
fn update_campaign_status(
98+
fn update_campaign_status(
9999
env: Env,
100100
campaign_id: u64,
101101
status: Status,
102102
admin: Address,
103103
) -> Result<(), BoundlessError> {
104-
// TODO: update campaign status logic
105-
// - Verify admin authorization
106-
// - Get campaign from storage
107-
// - Update status
108-
// - Store updated campaign
109-
// - Emit status update event
104+
admin.require_auth();
105+
let contract_admin = <BoundlessContract as ContractManagement>::get_admin(&env);
106+
if admin != contract_admin {
107+
return Err(BoundlessError::Unauthorized);
108+
}
109+
110+
let campaign_key = crate::datatypes::DataKey::Campaign(campaign_id);
111+
let mut campaign: Campaign = env
112+
.storage()
113+
.persistent()
114+
.get(&campaign_key)
115+
.ok_or(BoundlessError::CampaignNotFound)?;
116+
117+
campaign.status = status.clone();
118+
env.storage().persistent().set(&campaign_key, &campaign);
119+
env.events().publish(
120+
(Symbol::new(&env, "campaign"), Symbol::new(&env, "status_update")),
121+
(campaign_id, status, admin),
122+
);
123+
110124
Ok(())
111125
}
112126

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
#![cfg(test)]
2+
3+
use crate::{
4+
datatypes::{Campaign, Status},
5+
BoundlessContract, BoundlessContractClient,
6+
};
7+
use soroban_sdk::{
8+
testutils::Address as _,
9+
Address, Env, Symbol, Vec,
10+
};
11+
12+
extern crate std;
13+
mod boundless {
14+
soroban_sdk::contractimport!(file = "../../target/wasm32v1-none/release/boundless.wasm");
15+
}
16+
17+
#[test]
18+
fn test_update_campaign_status_success() {
19+
let env = Env::default();
20+
env.mock_all_auths();
21+
22+
let admin = Address::generate(&env);
23+
let contract_id = env.register(BoundlessContract, ());
24+
let contract = BoundlessContractClient::new(&env, &contract_id);
25+
26+
contract.initialize(&admin);
27+
28+
let campaign_id = 1u64;
29+
let owner = Address::generate(&env);
30+
let title = Symbol::new(&env, "TestCampaign");
31+
let description = Symbol::new(&env, "TestDescription");
32+
let funding_goal = 1000i128;
33+
let escrow_contract_id = Address::generate(&env);
34+
let milestones = Vec::new(&env);
35+
let backers = Vec::new(&env);
36+
37+
let campaign = Campaign {
38+
id: campaign_id,
39+
owner: owner.clone(),
40+
title: title.clone(),
41+
description: description.clone(),
42+
funding_goal,
43+
escrow_contract_id: escrow_contract_id.clone(),
44+
milestones,
45+
backers,
46+
status: Status::Active,
47+
};
48+
49+
let campaign_key = crate::datatypes::DataKey::Campaign(campaign_id);
50+
env.as_contract(&contract_id, || {
51+
env.storage().persistent().set(&campaign_key, &campaign);
52+
});
53+
54+
// Update status to Completed
55+
contract.update_campaign_status(&campaign_id, &Status::Completed, &admin);
56+
57+
let updated_campaign: Campaign = env.as_contract(&contract_id, || {
58+
env.storage().persistent().get(&campaign_key).unwrap()
59+
});
60+
assert_eq!(updated_campaign.status, Status::Completed);
61+
}
62+
63+
#[test]
64+
#[should_panic]
65+
fn test_update_campaign_status_unauthorized() {
66+
let env = Env::default();
67+
env.mock_all_auths();
68+
69+
let admin = Address::generate(&env);
70+
let unauthorized_user = Address::generate(&env);
71+
let contract_id = env.register(BoundlessContract, ());
72+
let contract = BoundlessContractClient::new(&env, &contract_id);
73+
74+
contract.initialize(&admin);
75+
76+
let campaign_id = 1u64;
77+
let owner = Address::generate(&env);
78+
let title = Symbol::new(&env, "TestCampaign");
79+
let description = Symbol::new(&env, "TestDescription");
80+
let funding_goal = 1000i128;
81+
let escrow_contract_id = Address::generate(&env);
82+
let milestones = Vec::new(&env);
83+
let backers = Vec::new(&env);
84+
85+
let campaign = Campaign {
86+
id: campaign_id,
87+
owner: owner.clone(),
88+
title: title.clone(),
89+
description: description.clone(),
90+
funding_goal,
91+
escrow_contract_id: escrow_contract_id.clone(),
92+
milestones,
93+
backers,
94+
status: Status::Active,
95+
};
96+
97+
let campaign_key = crate::datatypes::DataKey::Campaign(campaign_id);
98+
env.as_contract(&contract_id, || {
99+
env.storage().persistent().set(&campaign_key, &campaign);
100+
});
101+
102+
contract.update_campaign_status(&campaign_id, &Status::Completed, &unauthorized_user);
103+
}
104+
105+
#[test]
106+
#[should_panic]
107+
fn test_update_campaign_status_not_found() {
108+
let env = Env::default();
109+
env.mock_all_auths();
110+
111+
let admin = Address::generate(&env);
112+
let contract_id = env.register(BoundlessContract, ());
113+
let contract = BoundlessContractClient::new(&env, &contract_id);
114+
115+
contract.initialize(&admin);
116+
117+
let campaign_id = 999u64; // Non-existent campaign
118+
119+
contract.update_campaign_status(&campaign_id, &Status::Completed, &admin);
120+
}
121+
122+
#[test]
123+
fn test_update_campaign_status_to_failed() {
124+
let env = Env::default();
125+
env.mock_all_auths();
126+
127+
let admin = Address::generate(&env);
128+
let contract_id = env.register(BoundlessContract, ());
129+
let contract = BoundlessContractClient::new(&env, &contract_id);
130+
131+
contract.initialize(&admin);
132+
133+
let campaign_id = 1u64;
134+
let owner = Address::generate(&env);
135+
let title = Symbol::new(&env, "TestCampaign");
136+
let description = Symbol::new(&env, "TestDescription");
137+
let funding_goal = 1000i128;
138+
let escrow_contract_id = Address::generate(&env);
139+
let milestones = Vec::new(&env);
140+
let backers = Vec::new(&env);
141+
142+
let campaign = Campaign {
143+
id: campaign_id,
144+
owner: owner.clone(),
145+
title: title.clone(),
146+
description: description.clone(),
147+
funding_goal,
148+
escrow_contract_id: escrow_contract_id.clone(),
149+
milestones,
150+
backers,
151+
status: Status::Active,
152+
};
153+
154+
let campaign_key = crate::datatypes::DataKey::Campaign(campaign_id);
155+
env.as_contract(&contract_id, || {
156+
env.storage().persistent().set(&campaign_key, &campaign);
157+
});
158+
159+
// Update status to Failed
160+
contract.update_campaign_status(&campaign_id, &Status::Failed, &admin);
161+
162+
let updated_campaign: Campaign = env.as_contract(&contract_id, || {
163+
env.storage().persistent().get(&campaign_key).unwrap()
164+
});
165+
assert_eq!(updated_campaign.status, Status::Failed);
166+
}
167+
168+
#[test]
169+
fn test_update_campaign_status_to_pending() {
170+
let env = Env::default();
171+
env.mock_all_auths();
172+
173+
let admin = Address::generate(&env);
174+
let contract_id = env.register(BoundlessContract, ());
175+
let contract = BoundlessContractClient::new(&env, &contract_id);
176+
177+
contract.initialize(&admin);
178+
179+
let campaign_id = 1u64;
180+
let owner = Address::generate(&env);
181+
let title = Symbol::new(&env, "TestCampaign");
182+
let description = Symbol::new(&env, "TestDescription");
183+
let funding_goal = 1000i128;
184+
let escrow_contract_id = Address::generate(&env);
185+
let milestones = Vec::new(&env);
186+
let backers = Vec::new(&env);
187+
188+
let campaign = Campaign {
189+
id: campaign_id,
190+
owner: owner.clone(),
191+
title: title.clone(),
192+
description: description.clone(),
193+
funding_goal,
194+
escrow_contract_id: escrow_contract_id.clone(),
195+
milestones,
196+
backers,
197+
status: Status::Active,
198+
};
199+
200+
let campaign_key = crate::datatypes::DataKey::Campaign(campaign_id);
201+
env.as_contract(&contract_id, || {
202+
env.storage().persistent().set(&campaign_key, &campaign);
203+
});
204+
205+
// Update status to Pending
206+
contract.update_campaign_status(&campaign_id, &Status::Pending, &admin);
207+
208+
let updated_campaign: Campaign = env.as_contract(&contract_id, || {
209+
env.storage().persistent().get(&campaign_key).unwrap()
210+
});
211+
assert_eq!(updated_campaign.status, Status::Pending);
212+
}

contracts/boundless/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
pub mod admin;
44
pub mod campaign;
55
pub mod milestone;
6+
pub mod campaign_update_status;

0 commit comments

Comments
 (0)