@@ -83,6 +83,7 @@ pub enum ContractError {
8383 InvalidReferrer = 34 ,
8484 WalletCapExceeded = 35 ,
8585 DiscountTierLimitExceeded = 36 ,
86+ WalletBlacklisted = 37 ,
8687}
8788
8889pub mod fee {
@@ -332,6 +333,10 @@ pub mod constants {
332333 DataKey :: Whitelist ( creator. clone ( ) )
333334 }
334335
336+ pub fn blacklisted ( wallet : & Address ) -> DataKey {
337+ DataKey :: Blacklisted ( wallet. clone ( ) )
338+ }
339+
335340 pub fn creator ( creator : & Address ) -> DataKey {
336341 creator_key ( creator)
337342 }
@@ -608,6 +613,9 @@ pub enum DataKey {
608613 /// decide whether to emit the TTL-extension event without a TTL read
609614 /// (the Soroban SDK does not expose TTL reads to contract code).
610615 CreatorTtlLiveUntil ( Address ) ,
616+ /// Wallet addresses the protocol admin has barred from buying, selling,
617+ /// or registering as a creator.
618+ Blacklisted ( Address ) ,
611619}
612620
613621/// Time-locked key allocation for creator self-vesting.
@@ -1004,6 +1012,20 @@ fn assert_not_paused(env: &Env) -> Result<(), ContractError> {
10041012 Ok ( ( ) )
10051013}
10061014
1015+ fn is_blacklisted ( env : & Env , wallet : & Address ) -> bool {
1016+ env. storage ( )
1017+ . persistent ( )
1018+ . get :: < DataKey , bool > ( & constants:: storage:: blacklisted ( wallet) )
1019+ . unwrap_or ( false )
1020+ }
1021+
1022+ fn assert_not_blacklisted ( env : & Env , wallet : & Address ) -> Result < ( ) , ContractError > {
1023+ if is_blacklisted ( env, wallet) {
1024+ return Err ( ContractError :: WalletBlacklisted ) ;
1025+ }
1026+ Ok ( ( ) )
1027+ }
1028+
10071029fn assert_is_admin ( env : & Env , caller : & Address ) -> Result < ( ) , ContractError > {
10081030 let admin: Address = env
10091031 . storage ( )
@@ -1521,6 +1543,7 @@ impl CreatorKeysContract {
15211543
15221544 creator. require_auth ( ) ;
15231545 assert_not_paused ( & env) ?;
1546+ assert_not_blacklisted ( & env, & creator) ?;
15241547
15251548 validate_creator_handle ( & handle) ?;
15261549 if let Some ( config) = co_creator. as_ref ( ) {
@@ -1684,6 +1707,7 @@ impl CreatorKeysContract {
16841707 ) -> Result < u32 , ContractError > {
16851708 buyer. require_auth ( ) ;
16861709 assert_not_paused ( & env) ?;
1710+ assert_not_blacklisted ( & env, & buyer) ?;
16871711
16881712 if payment <= 0 {
16891713 return Err ( ContractError :: NotPositiveAmount ) ;
@@ -1852,6 +1876,7 @@ impl CreatorKeysContract {
18521876 ) -> Result < u32 , ContractError > {
18531877 seller. require_auth ( ) ;
18541878 assert_not_paused ( & env) ?;
1879+ assert_not_blacklisted ( & env, & seller) ?;
18551880
18561881 let mut profile: CreatorProfile = read_registered_creator_profile ( & env, & creator) ?;
18571882
@@ -2231,6 +2256,48 @@ impl CreatorKeysContract {
22312256 is_paused ( & env)
22322257 }
22332258
2259+ /// Blocks a wallet from buying, selling, or registering as a creator.
2260+ ///
2261+ /// Only the protocol admin may call this. Emits a `blacklist` event.
2262+ pub fn blacklist_wallet (
2263+ env : Env ,
2264+ admin : Address ,
2265+ wallet : Address ,
2266+ ) -> Result < ( ) , ContractError > {
2267+ admin. require_auth ( ) ;
2268+ assert_is_admin ( & env, & admin) ?;
2269+ env. storage ( )
2270+ . persistent ( )
2271+ . set ( & constants:: storage:: blacklisted ( & wallet) , & true ) ;
2272+ env. events ( )
2273+ . publish ( ( events:: BLACKLIST_ADDED_EVENT_NAME , wallet) , ( ) ) ;
2274+ Ok ( ( ) )
2275+ }
2276+
2277+ /// Restores a previously blacklisted wallet's access to buy, sell, and
2278+ /// register as a creator.
2279+ ///
2280+ /// Only the protocol admin may call this. Emits an `unblacklist` event.
2281+ pub fn remove_from_blacklist (
2282+ env : Env ,
2283+ admin : Address ,
2284+ wallet : Address ,
2285+ ) -> Result < ( ) , ContractError > {
2286+ admin. require_auth ( ) ;
2287+ assert_is_admin ( & env, & admin) ?;
2288+ env. storage ( )
2289+ . persistent ( )
2290+ . remove ( & constants:: storage:: blacklisted ( & wallet) ) ;
2291+ env. events ( )
2292+ . publish ( ( events:: BLACKLIST_REMOVED_EVENT_NAME , wallet) , ( ) ) ;
2293+ Ok ( ( ) )
2294+ }
2295+
2296+ /// Read-only view: returns whether `wallet` is currently blacklisted.
2297+ pub fn is_wallet_blacklisted ( env : Env , wallet : Address ) -> bool {
2298+ is_blacklisted ( & env, & wallet)
2299+ }
2300+
22342301 pub fn get_key_balance ( env : Env , creator : Address , wallet : Address ) -> u32 {
22352302 let key = constants:: storage:: holder_balance_key ( & creator, & wallet) ;
22362303 // Read-only callers get `0` for unseen balances to avoid sparse-map lookups failing.
0 commit comments