Skip to content

Commit 5451187

Browse files
committed
Merge remote-tracking branch 'origin/serkan/min-reserve-price-logic-update' into serkan/blacklist-tokens
2 parents abf6f12 + efe121e commit 5451187

13 files changed

Lines changed: 519 additions & 150 deletions

File tree

‎Cargo.lock‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎contracts/reserve-auction/src/error.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub enum ContractError {
4141
#[error("InvalidReservePrice: {min}")]
4242
InvalidReservePrice { min: Coin },
4343

44+
#[error("InvalidMinReservePriceManagerAddress")]
45+
InvalidMinReservePriceManagerAddress {},
46+
4447
#[error("BidTooLow: {0}")]
4548
BidTooLow(Uint128),
4649

@@ -55,4 +58,7 @@ pub enum ContractError {
5558

5659
#[error("Auction within halt window: a halt has occurred and the auction cannot be settled")]
5760
AuctionWithinHaltWindow,
61+
62+
#[error("Token is blacklisted: collection={0}, token_id={1}")]
63+
TokenBlacklisted(String, String),
5864
}

‎contracts/reserve-auction/src/execute.rs‎

Lines changed: 193 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
use std::vec;
22

33
use crate::error::ContractError;
4-
use crate::helpers::{only_no_auction, settle_auction, validate_reserve_price};
4+
use crate::helpers::{
5+
build_blacklist_key, only_blacklist_manager, only_min_reserve_price_manager, only_no_auction,
6+
only_not_blacklisted, settle_auction, validate_reserve_price, BLACKLIST_MANAGER,
7+
};
58
use crate::msg::ExecuteMsg;
6-
use crate::state::{auctions, Auction, HighBid};
7-
use crate::state::{CONFIG, HALT_MANAGER};
9+
use crate::state::{
10+
auctions, Auction, HighBid, BLACKLIST, CONFIG, HALT_MANAGER, MIN_RESERVE_PRICES,
11+
MIN_RESERVE_PRICE_MANAGER,
12+
};
813
use cosmwasm_std::{
914
attr, coin, ensure, ensure_eq, has_coins, Addr, Coin, DepsMut, Env, Event, MessageInfo,
1015
Timestamp,
@@ -76,6 +81,36 @@ pub fn execute(
7681
api.addr_validate(&collection)?,
7782
&token_id,
7883
),
84+
ExecuteMsg::SetMinReservePrices { min_reserve_prices } => {
85+
execute_set_min_reserve_prices(deps, info, min_reserve_prices)
86+
}
87+
ExecuteMsg::UnsetMinReservePrices { denoms } => {
88+
execute_unset_min_reserve_prices(deps, info, denoms)
89+
}
90+
ExecuteMsg::UpdateMinReservePriceManager { manager } => {
91+
execute_update_min_reserve_price_manager(deps, info, manager)
92+
}
93+
ExecuteMsg::AddToBlacklist {
94+
collection,
95+
token_id,
96+
} => execute_add_to_blacklist(deps, info, api.addr_validate(&collection)?, token_id),
97+
ExecuteMsg::RemoveFromBlacklist {
98+
collection,
99+
token_id,
100+
} => execute_remove_from_blacklist(deps, info, api.addr_validate(&collection)?, token_id),
101+
ExecuteMsg::BatchAddToBlacklist {
102+
collection,
103+
token_ids,
104+
} => execute_batch_add_to_blacklist(deps, info, api.addr_validate(&collection)?, token_ids),
105+
ExecuteMsg::BatchRemoveFromBlacklist {
106+
collection,
107+
token_ids,
108+
} => execute_batch_remove_from_blacklist(
109+
deps,
110+
info,
111+
api.addr_validate(&collection)?,
112+
token_ids,
113+
),
79114
}
80115
}
81116

@@ -109,6 +144,9 @@ pub fn execute_create_auction(
109144

110145
only_tradable(&deps.querier, &env.block, &collection)?;
111146

147+
// Check if token is blacklisted
148+
only_not_blacklisted(deps.as_ref().storage, &collection, token_id)?;
149+
112150
let mut response = Response::new();
113151

114152
validate_reserve_price(deps.as_ref().storage, &reserve_price)?;
@@ -230,8 +268,12 @@ pub fn execute_cancel_auction(
230268
nonpayable(&info)?;
231269
let auction = auctions().load(deps.storage, (collection.clone(), token_id.to_string()))?;
232270

233-
// Ensure caller is the seller
234-
ensure_eq!(auction.seller, info.sender, ContractError::Unauthorized {});
271+
let is_blacklist_manager = info.sender.as_str() == BLACKLIST_MANAGER;
272+
273+
if !is_blacklist_manager {
274+
// Ensure caller is the seller
275+
ensure_eq!(auction.seller, info.sender, ContractError::Unauthorized {});
276+
}
235277

236278
// Ensure auction hasn't started
237279
ensure!(
@@ -267,6 +309,9 @@ pub fn execute_place_bid(
267309

268310
let mut auction = auctions().load(deps.storage, (collection, token_id.to_string()))?;
269311

312+
// Check if token is blacklisted
313+
only_not_blacklisted(deps.as_ref().storage, &auction.collection, token_id)?;
314+
270315
let auction_denom = auction.denom();
271316
let bid_amount = must_pay(&info, &auction_denom)?;
272317

@@ -372,3 +417,146 @@ pub fn execute_settle_auction(
372417

373418
settle_auction(deps, block_time, auction, &config, &halt_manager, response)
374419
}
420+
421+
pub fn execute_set_min_reserve_prices(
422+
deps: DepsMut,
423+
info: MessageInfo,
424+
min_reserve_prices: Vec<Coin>,
425+
) -> Result<Response, ContractError> {
426+
only_min_reserve_price_manager(deps.as_ref(), &info.sender)?;
427+
428+
let mut response = Response::new();
429+
430+
for min_reserve_price in min_reserve_prices {
431+
ensure!(
432+
!MIN_RESERVE_PRICES.has(deps.storage, min_reserve_price.denom.clone()),
433+
ContractError::InvalidInput("found duplicate denom".to_string())
434+
);
435+
436+
MIN_RESERVE_PRICES.save(
437+
deps.storage,
438+
min_reserve_price.denom.clone(),
439+
&min_reserve_price.amount,
440+
)?;
441+
response = response.add_event(
442+
Event::new("set-min-reserve-price")
443+
.add_attribute("denom", min_reserve_price.denom)
444+
.add_attribute("amount", min_reserve_price.amount),
445+
);
446+
}
447+
Ok(response)
448+
}
449+
450+
pub fn execute_unset_min_reserve_prices(
451+
deps: DepsMut,
452+
info: MessageInfo,
453+
denoms: Vec<String>,
454+
) -> Result<Response, ContractError> {
455+
only_min_reserve_price_manager(deps.as_ref(), &info.sender)?;
456+
457+
let mut response = Response::new();
458+
459+
for denom in denoms {
460+
ensure!(
461+
MIN_RESERVE_PRICES.has(deps.storage, denom.clone()),
462+
ContractError::InvalidInput("denom not found".to_string())
463+
);
464+
465+
MIN_RESERVE_PRICES.remove(deps.storage, denom.clone());
466+
response =
467+
response.add_event(Event::new("unset-min-reserve-price").add_attribute("denom", denom));
468+
}
469+
Ok(response)
470+
}
471+
472+
pub fn execute_update_min_reserve_price_manager(
473+
deps: DepsMut,
474+
info: MessageInfo,
475+
manager: String,
476+
) -> Result<Response, ContractError> {
477+
only_min_reserve_price_manager(deps.as_ref(), &info.sender)?;
478+
479+
MIN_RESERVE_PRICE_MANAGER.save(deps.storage, &deps.api.addr_validate(&manager)?)?;
480+
481+
Ok(Response::new().add_attribute("action", "update-min-reserve-price-manager"))
482+
}
483+
484+
pub fn execute_add_to_blacklist(
485+
deps: DepsMut,
486+
info: MessageInfo,
487+
collection: Addr,
488+
token_id: String,
489+
) -> Result<Response, ContractError> {
490+
only_blacklist_manager(&info.sender)?;
491+
492+
let key = build_blacklist_key(collection.as_ref(), &token_id);
493+
BLACKLIST.save(deps.storage, key, &())?;
494+
495+
let response = Response::new()
496+
.add_attribute("action", "add-to-blacklist")
497+
.add_attribute("collection", collection.to_string())
498+
.add_attribute("token_id", token_id);
499+
500+
Ok(response)
501+
}
502+
503+
pub fn execute_remove_from_blacklist(
504+
deps: DepsMut,
505+
info: MessageInfo,
506+
collection: Addr,
507+
token_id: String,
508+
) -> Result<Response, ContractError> {
509+
only_blacklist_manager(&info.sender)?;
510+
511+
let key = build_blacklist_key(collection.as_ref(), &token_id);
512+
BLACKLIST.remove(deps.storage, key);
513+
514+
let response = Response::new()
515+
.add_attribute("action", "remove-from-blacklist")
516+
.add_attribute("collection", collection.to_string())
517+
.add_attribute("token_id", token_id);
518+
519+
Ok(response)
520+
}
521+
522+
pub fn execute_batch_add_to_blacklist(
523+
deps: DepsMut,
524+
info: MessageInfo,
525+
collection: Addr,
526+
token_ids: Vec<String>,
527+
) -> Result<Response, ContractError> {
528+
only_blacklist_manager(&info.sender)?;
529+
530+
for token_id in &token_ids {
531+
let key = build_blacklist_key(collection.as_ref(), token_id);
532+
BLACKLIST.save(deps.storage, key, &())?;
533+
}
534+
535+
let response = Response::new()
536+
.add_attribute("action", "batch-add-to-blacklist")
537+
.add_attribute("collection", collection.to_string())
538+
.add_attribute("count", token_ids.len().to_string());
539+
540+
Ok(response)
541+
}
542+
543+
pub fn execute_batch_remove_from_blacklist(
544+
deps: DepsMut,
545+
info: MessageInfo,
546+
collection: Addr,
547+
token_ids: Vec<String>,
548+
) -> Result<Response, ContractError> {
549+
only_blacklist_manager(&info.sender)?;
550+
551+
for token_id in &token_ids {
552+
let key = build_blacklist_key(collection.as_ref(), token_id);
553+
BLACKLIST.remove(deps.storage, key);
554+
}
555+
556+
let response = Response::new()
557+
.add_attribute("action", "batch-remove-from-blacklist")
558+
.add_attribute("collection", collection.to_string())
559+
.add_attribute("count", token_ids.len().to_string());
560+
561+
Ok(response)
562+
}

‎contracts/reserve-auction/src/helpers.rs‎

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
use cosmwasm_std::{coin, ensure, Addr, Coin, Deps, DepsMut, Event, Storage, Timestamp};
1+
use cosmwasm_std::{coin, ensure, ensure_eq, Addr, Coin, Deps, DepsMut, Event, Storage, Timestamp};
22
use sg_marketplace_common::{
33
nft::{load_collection_royalties, transfer_nft},
44
sale::payout_nft_sale_fees,
55
};
66
use sg_std::Response;
77

8-
use crate::state::{auctions, Auction, Config, HaltManager, MIN_RESERVE_PRICES};
8+
use crate::state::{
9+
auctions, Auction, Config, HaltManager, BLACKLIST, MIN_RESERVE_PRICES,
10+
MIN_RESERVE_PRICE_MANAGER,
11+
};
912
use crate::ContractError;
1013

14+
pub const BLACKLIST_MANAGER: &str =
15+
"stars14ay8uhnnacg79dvygpf5rh9wz2m7tj8jnw60w233xja4akax4mrs54770s";
16+
1117
pub fn only_no_auction(deps: Deps, collection: &Addr, token_id: &str) -> Result<(), ContractError> {
1218
if auctions()
1319
.may_load(deps.storage, (collection.clone(), token_id.to_string()))?
@@ -21,6 +27,44 @@ pub fn only_no_auction(deps: Deps, collection: &Addr, token_id: &str) -> Result<
2127
Ok(())
2228
}
2329

30+
pub fn only_min_reserve_price_manager(deps: Deps, sender: &Addr) -> Result<(), ContractError> {
31+
let min_reserve_price_manager = MIN_RESERVE_PRICE_MANAGER.load(deps.storage)?;
32+
ensure_eq!(
33+
sender,
34+
min_reserve_price_manager,
35+
ContractError::Unauthorized {}
36+
);
37+
Ok(())
38+
}
39+
40+
pub fn build_blacklist_key(collection: &str, token_id: &str) -> String {
41+
format!("{}/{}", collection, token_id)
42+
}
43+
44+
pub fn only_not_blacklisted(
45+
storage: &dyn Storage,
46+
collection: &Addr,
47+
token_id: &str,
48+
) -> Result<(), ContractError> {
49+
let key = build_blacklist_key(collection.as_ref(), token_id);
50+
if BLACKLIST.has(storage, key) {
51+
return Err(ContractError::TokenBlacklisted(
52+
collection.to_string(),
53+
token_id.to_string(),
54+
));
55+
}
56+
Ok(())
57+
}
58+
59+
pub fn only_blacklist_manager(sender: &Addr) -> Result<(), ContractError> {
60+
ensure_eq!(
61+
sender.as_str(),
62+
BLACKLIST_MANAGER,
63+
ContractError::Unauthorized {}
64+
);
65+
Ok(())
66+
}
67+
2468
pub fn validate_reserve_price(
2569
storage: &dyn Storage,
2670
check_reserve_price: &Coin,
@@ -59,6 +103,9 @@ pub fn settle_auction(
59103
ContractError::AuctionNotEnded {}
60104
);
61105

106+
// Check if token is blacklisted before settling
107+
only_not_blacklisted(deps.storage, &auction.collection, &auction.token_id)?;
108+
62109
// If auction is set to end within a halt window, then postpone it instead
63110
let auction_end_time = auction.end_time.unwrap();
64111
if halt_manager.is_within_halt_window(auction_end_time.seconds()) {

‎contracts/reserve-auction/src/instantiate.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use cosmwasm_std::entry_point;
33

44
use crate::msg::InstantiateMsg;
5-
use crate::state::{Config, HaltManager, HALT_MANAGER};
5+
use crate::state::{Config, HaltManager, HALT_MANAGER, MIN_RESERVE_PRICE_MANAGER};
66
use crate::{error::ContractError, state::MIN_RESERVE_PRICES};
77
use cosmwasm_std::{DepsMut, Env, Event, MessageInfo};
88
use cw2::set_contract_version;
@@ -20,6 +20,12 @@ pub fn instantiate(
2020
msg: InstantiateMsg,
2121
) -> Result<Response, ContractError> {
2222
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
23+
24+
MIN_RESERVE_PRICE_MANAGER.save(
25+
deps.storage,
26+
&deps.api.addr_validate(&msg.min_reserve_price_manager)?,
27+
)?;
28+
2329
let config = Config {
2430
fair_burn: deps.api.addr_validate(&msg.fair_burn)?,
2531
trading_fee_percent: msg.trading_fee_percent,

0 commit comments

Comments
 (0)