Skip to content

Commit ae48129

Browse files
Merge pull request #86 from Great-2025/fix/security-issues-26-25
Fix security issues #25 and #26: Implement blacklist functionality an…
2 parents a4b1870 + 7f3fbba commit ae48129

2 files changed

Lines changed: 405 additions & 0 deletions

File tree

contracts/substream_contracts/src/lib.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub enum DataKey {
5353
ProtocolFeeBps,
5454
Moderator(Address),
5555
VerifiedCreator(Address),
56+
BlacklistedUser(Address, Address), // (creator, user_to_block)
5657
}
5758

5859
#[contracttype]
@@ -120,6 +121,18 @@ pub struct CreatorVerified {
120121
#[topic] pub verified_by: Address,
121122
}
122123

124+
#[contractevent]
125+
pub struct UserBlacklisted {
126+
#[topic] pub creator: Address,
127+
#[topic] pub user: Address,
128+
}
129+
130+
#[contractevent]
131+
pub struct UserUnblacklisted {
132+
#[topic] pub creator: Address,
133+
#[topic] pub user: Address,
134+
}
135+
123136
#[contract]
124137
pub struct SubStreamContract;
125138

@@ -243,6 +256,47 @@ impl SubStreamContract {
243256
pub fn cancel_group(env: Env, subscriber: Address, channel_id: Address) {
244257
cancel_internal(&env, &subscriber, &channel_id);
245258
}
259+
260+
// --- Blacklist functionality for Issue #25 ---
261+
262+
pub fn blacklist_user(env: Env, creator: Address, user_to_block: Address) {
263+
creator.require_auth();
264+
265+
let blacklist_key = DataKey::BlacklistedUser(creator.clone(), user_to_block.clone());
266+
267+
// Check if already blacklisted
268+
if env.storage().persistent().has(&blacklist_key) {
269+
panic!("user already blacklisted");
270+
}
271+
272+
// Add to blacklist
273+
env.storage().persistent().set(&blacklist_key, &true);
274+
275+
// Emit event
276+
UserBlacklisted { creator, user: user_to_block }.publish(&env);
277+
}
278+
279+
pub fn unblacklist_user(env: Env, creator: Address, user_to_unblock: Address) {
280+
creator.require_auth();
281+
282+
let blacklist_key = DataKey::BlacklistedUser(creator.clone(), user_to_unblock.clone());
283+
284+
// Check if user is actually blacklisted
285+
if !env.storage().persistent().has(&blacklist_key) {
286+
panic!("user not blacklisted");
287+
}
288+
289+
// Remove from blacklist
290+
env.storage().persistent().remove(&blacklist_key);
291+
292+
// Emit event
293+
UserUnblacklisted { creator, user: user_to_unblock }.publish(&env);
294+
}
295+
296+
pub fn is_user_blacklisted(env: Env, creator: Address, user: Address) -> bool {
297+
let blacklist_key = DataKey::BlacklistedUser(creator, user);
298+
env.storage().persistent().get(&blacklist_key).unwrap_or(false)
299+
}
246300
}
247301

248302
// --- Internal Logic & Helpers ---
@@ -363,6 +417,14 @@ fn subscribe_core(env: &Env, payer: &Address, beneficiary: &Address, stream_id:
363417
let key = subscription_key(beneficiary, stream_id);
364418
if subscription_exists(env, &key) { panic!("exists"); }
365419

420+
// Check if beneficiary is blacklisted by any of the creators
421+
for creator in &creators {
422+
let blacklist_key = DataKey::BlacklistedUser(creator.clone(), beneficiary.clone());
423+
if env.storage().persistent().has(&blacklist_key) {
424+
panic!("user is blacklisted by creator");
425+
}
426+
}
427+
366428
let token_client = TokenClient::new(env, token);
367429
token_client.transfer(payer, &env.current_contract_address(), &amount);
368430

0 commit comments

Comments
 (0)