Skip to content

Add optional mint count limit for tiered whitelist stages #709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 48 additions & 8 deletions contracts/minters/open-edition-minter-merkle-wl/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use crate::msg::{
};
use crate::state::{
increment_token_index, Config, ConfigExtension, CONFIG, MINTABLE_NUM_TOKENS, MINTER_ADDRS,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT, WHITELIST_FS_MINTER_ADDRS, WHITELIST_MINTER_ADDRS,
WHITELIST_SS_MINTER_ADDRS, WHITELIST_TS_MINTER_ADDRS,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT, WHITELIST_FS_MINTER_ADDRS, WHITELIST_FS_MINT_COUNT,
WHITELIST_MINTER_ADDRS, WHITELIST_SS_MINTER_ADDRS, WHITELIST_SS_MINT_COUNT,
WHITELIST_TS_MINTER_ADDRS, WHITELIST_TS_MINT_COUNT,
};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
Expand All @@ -26,7 +27,7 @@ use sg2::query::Sg2QueryMsg;
use sg4::{MinterConfig, Status, StatusResponse, SudoMsg};
use sg721::{ExecuteMsg as Sg721ExecuteMsg, InstantiateMsg as Sg721InstantiateMsg};
use sg_std::StargazeMsgWrapper;
use tiered_whitelist_merkletree::msg::QueryMsg as TieredWhitelistQueryMsg;
use tiered_whitelist_merkletree::msg::{QueryMsg as TieredWhitelistQueryMsg, StageResponse};
use url::Url;
use whitelist_mtree::msg::{
ConfigResponse as WhitelistConfigResponse, HasMemberResponse, QueryMsg as WhitelistQueryMsg,
Expand Down Expand Up @@ -436,15 +437,36 @@ fn is_public_mint(
}

// Check wl per address limit
let wl_mint_count = whitelist_mint_count(deps, info, whitelist.clone())?.0;
let wl_mint_count = whitelist_mint_count(deps, info, whitelist.clone())?;
let max_count = match allocation {
Some(allocation) => allocation,
None => wl_config.per_address_limit,
};
if wl_mint_count >= max_count {
if wl_mint_count.0 >= max_count {
return Err(ContractError::MaxPerAddressLimitExceeded {});
}

// Check if whitelist stage mint count limit is reached
if wl_mint_count.1 && wl_mint_count.2.is_some() {
let active_stage: StageResponse = deps.querier.query_wasm_smart(
whitelist.clone(),
&TieredWhitelistQueryMsg::Stage {
stage_id: wl_mint_count.2.unwrap() - 1,
},
)?;
if active_stage.stage.mint_count_limit.is_some() {
let stage_mint_count = match wl_mint_count.2.unwrap() {
1 => WHITELIST_FS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
2 => WHITELIST_SS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
3 => WHITELIST_TS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
_ => return Err(ContractError::InvalidStageID {}),
};
if stage_mint_count >= active_stage.stage.mint_count_limit.unwrap() {
return Err(ContractError::WhitelistMintCountLimitReached {});
}
}
}

Ok(false)
}

Expand Down Expand Up @@ -1004,9 +1026,27 @@ fn save_whitelist_mint_count(
) -> StdResult<()> {
if is_tiered_whitelist & stage_id.is_some() {
match stage_id {
Some(1) => WHITELIST_FS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(2) => WHITELIST_SS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(3) => WHITELIST_TS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(1) => {
let _ = WHITELIST_FS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_fs_mint_count =
WHITELIST_FS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_fs_mint_count += 1;
WHITELIST_FS_MINT_COUNT.save(deps.storage, &wl_fs_mint_count)
}
Some(2) => {
let _ = WHITELIST_SS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_ss_mint_count =
WHITELIST_SS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_ss_mint_count += 1;
WHITELIST_SS_MINT_COUNT.save(deps.storage, &wl_ss_mint_count)
}
Some(3) => {
let _ = WHITELIST_TS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_ts_mint_count =
WHITELIST_TS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_ts_mint_count += 1;
WHITELIST_TS_MINT_COUNT.save(deps.storage, &wl_ts_mint_count)
}
_ => Err(StdError::generic_err("Invalid stage ID")),
}
} else {
Expand Down
6 changes: 6 additions & 0 deletions contracts/minters/open-edition-minter-merkle-wl/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub enum ContractError {
#[error("Invalid reply ID")]
InvalidReplyID {},

#[error("Invalid stage ID")]
InvalidStageID {},

#[error("Not enough funds sent")]
NotEnoughFunds {},

Expand Down Expand Up @@ -121,6 +124,9 @@ pub enum ContractError {
#[error("Max minting limit per address exceeded")]
MaxPerAddressLimitExceeded {},

#[error("WhitelistMintCountLimitReached")]
WhitelistMintCountLimitReached {},

#[error("Token id: {token_id} already sold")]
TokenIdAlreadySold { token_id: u32 },

Expand Down
3 changes: 3 additions & 0 deletions contracts/minters/open-edition-minter-merkle-wl/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub const WHITELIST_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlma");
pub const WHITELIST_FS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlfsma");
pub const WHITELIST_SS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlssma");
pub const WHITELIST_TS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wltsma");
pub const WHITELIST_FS_MINT_COUNT: Item<u32> = Item::new("wlfsmc");
pub const WHITELIST_SS_MINT_COUNT: Item<u32> = Item::new("wlssmc");
pub const WHITELIST_TS_MINT_COUNT: Item<u32> = Item::new("wltsmc");
/// This keeps track of the mint count
pub const TOTAL_MINT_COUNT: Item<u32> = Item::new("total_mint_count");

Expand Down
60 changes: 50 additions & 10 deletions contracts/minters/open-edition-minter-wl-flex/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use crate::msg::{
};
use crate::state::{
increment_token_index, Config, ConfigExtension, CONFIG, MINTABLE_NUM_TOKENS, MINTER_ADDRS,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT, WHITELIST_FS_MINTER_ADDRS, WHITELIST_MINTER_ADDRS,
WHITELIST_SS_MINTER_ADDRS, WHITELIST_TS_MINTER_ADDRS,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT, WHITELIST_FS_MINTER_ADDRS, WHITELIST_FS_MINT_COUNT,
WHITELIST_MINTER_ADDRS, WHITELIST_SS_MINTER_ADDRS, WHITELIST_SS_MINT_COUNT,
WHITELIST_TS_MINTER_ADDRS, WHITELIST_TS_MINT_COUNT,
};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
Expand All @@ -26,7 +27,7 @@ use sg2::query::Sg2QueryMsg;
use sg4::{MinterConfig, Status, StatusResponse, SudoMsg};
use sg721::{ExecuteMsg as Sg721ExecuteMsg, InstantiateMsg as Sg721InstantiateMsg};
use sg_std::StargazeMsgWrapper;
use sg_tiered_whitelist_flex::msg::QueryMsg as TieredWhitelistQueryMsg;
use sg_tiered_whitelist_flex::msg::{QueryMsg as TieredWhitelistQueryMsg, StageResponse};
use sg_whitelist_flex::msg::{
ConfigResponse as WhitelistConfigResponse, HasMemberResponse, Member,
QueryMsg as WhitelistQueryMsg,
Expand Down Expand Up @@ -416,24 +417,45 @@ fn is_public_mint(deps: Deps, info: &MessageInfo) -> Result<bool, ContractError>
}

// Check wl per address limit
let wl_mint_count = whitelist_mint_count(deps, info, whitelist.clone())?.0;
let wl_mint_count = whitelist_mint_count(deps, info, whitelist.clone())?;
if config.extension.num_tokens.is_none() {
ensure!(
wl_mint_count < config.extension.per_address_limit,
wl_mint_count.0 < config.extension.per_address_limit,
ContractError::MaxPerAddressLimitExceeded {}
);
}

let wl_limit: Member = deps.querier.query_wasm_smart(
whitelist,
whitelist.clone(),
&WhitelistQueryMsg::Member {
member: info.sender.to_string(),
},
)?;
if wl_mint_count >= wl_limit.mint_count {
if wl_mint_count.0 >= wl_limit.mint_count {
return Err(ContractError::MaxPerAddressLimitExceeded {});
}

// Check if whitelist stage mint count limit is reached
if wl_mint_count.1 && wl_mint_count.2.is_some() {
let active_stage: StageResponse = deps.querier.query_wasm_smart(
whitelist.clone(),
&TieredWhitelistQueryMsg::Stage {
stage_id: wl_mint_count.2.unwrap() - 1,
},
)?;
if active_stage.stage.mint_count_limit.is_some() {
let stage_mint_count = match wl_mint_count.2.unwrap() {
1 => WHITELIST_FS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
2 => WHITELIST_SS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
3 => WHITELIST_TS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
_ => return Err(ContractError::InvalidStageID {}),
};
if stage_mint_count >= active_stage.stage.mint_count_limit.unwrap() {
return Err(ContractError::WhitelistMintCountLimitReached {});
}
}
}

Ok(false)
}

Expand Down Expand Up @@ -504,9 +526,27 @@ fn save_whitelist_mint_count(
) -> StdResult<()> {
if is_tiered_whitelist & stage_id.is_some() {
match stage_id {
Some(1) => WHITELIST_FS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(2) => WHITELIST_SS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(3) => WHITELIST_TS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(1) => {
let _ = WHITELIST_FS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_fs_mint_count =
WHITELIST_FS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_fs_mint_count += 1;
WHITELIST_FS_MINT_COUNT.save(deps.storage, &wl_fs_mint_count)
}
Some(2) => {
let _ = WHITELIST_SS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_ss_mint_count =
WHITELIST_SS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_ss_mint_count += 1;
WHITELIST_SS_MINT_COUNT.save(deps.storage, &wl_ss_mint_count)
}
Some(3) => {
let _ = WHITELIST_TS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_ts_mint_count =
WHITELIST_TS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_ts_mint_count += 1;
WHITELIST_TS_MINT_COUNT.save(deps.storage, &wl_ts_mint_count)
}
_ => Err(StdError::generic_err("Invalid stage ID")),
}
} else {
Expand Down
6 changes: 6 additions & 0 deletions contracts/minters/open-edition-minter-wl-flex/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub enum ContractError {
#[error("Invalid reply ID")]
InvalidReplyID {},

#[error("Invalid stage ID")]
InvalidStageID {},

#[error("Not enough funds sent")]
NotEnoughFunds {},

Expand Down Expand Up @@ -118,6 +121,9 @@ pub enum ContractError {
#[error("Max minting limit per address exceeded")]
MaxPerAddressLimitExceeded {},

#[error("WhitelistMintCountLimitReached")]
WhitelistMintCountLimitReached {},

#[error("Token id: {token_id} already sold")]
TokenIdAlreadySold { token_id: u32 },

Expand Down
3 changes: 3 additions & 0 deletions contracts/minters/open-edition-minter-wl-flex/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub const WHITELIST_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlma");
pub const WHITELIST_FS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlfsma");
pub const WHITELIST_SS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlssma");
pub const WHITELIST_TS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wltsma");
pub const WHITELIST_FS_MINT_COUNT: Item<u32> = Item::new("wlfsmc");
pub const WHITELIST_SS_MINT_COUNT: Item<u32> = Item::new("wlssmc");
pub const WHITELIST_TS_MINT_COUNT: Item<u32> = Item::new("wltsmc");

/// This keeps track of the mint count
pub const TOTAL_MINT_COUNT: Item<u32> = Item::new("total_mint_count");
Expand Down
59 changes: 50 additions & 9 deletions contracts/minters/open-edition-minter/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use crate::msg::{
};
use crate::state::{
increment_token_index, Config, ConfigExtension, CONFIG, MINTABLE_NUM_TOKENS, MINTER_ADDRS,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT, WHITELIST_FS_MINTER_ADDRS, WHITELIST_MINTER_ADDRS,
WHITELIST_SS_MINTER_ADDRS, WHITELIST_TS_MINTER_ADDRS,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT, WHITELIST_FS_MINTER_ADDRS, WHITELIST_FS_MINT_COUNT,
WHITELIST_MINTER_ADDRS, WHITELIST_SS_MINTER_ADDRS, WHITELIST_SS_MINT_COUNT,
WHITELIST_TS_MINTER_ADDRS, WHITELIST_TS_MINT_COUNT,
};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
Expand All @@ -26,7 +27,7 @@ use sg2::query::Sg2QueryMsg;
use sg4::{MinterConfig, Status, StatusResponse, SudoMsg};
use sg721::{ExecuteMsg as Sg721ExecuteMsg, InstantiateMsg as Sg721InstantiateMsg};
use sg_std::StargazeMsgWrapper;
use sg_tiered_whitelist::msg::QueryMsg as TieredWhitelistQueryMsg;
use sg_tiered_whitelist::msg::{QueryMsg as TieredWhitelistQueryMsg, StageResponse};
use sg_whitelist::msg::{
ConfigResponse as WhitelistConfigResponse, HasMemberResponse, QueryMsg as WhitelistQueryMsg,
};
Expand Down Expand Up @@ -410,12 +411,34 @@ fn is_public_mint(deps: Deps, info: &MessageInfo) -> Result<bool, ContractError>
});
}

// Check wl per address limit
let wl_mint_count = whitelist_mint_count(deps, info, whitelist.clone())?.0;
if wl_mint_count >= wl_config.per_address_limit {
let wl_mint_count = whitelist_mint_count(deps, info, whitelist.clone())?;

// Check if whitelist per address limit is reached
if wl_mint_count.0 >= wl_config.per_address_limit {
return Err(ContractError::MaxPerAddressLimitExceeded {});
}

// Check if whitelist stage mint count limit is reached
if wl_mint_count.1 && wl_mint_count.2.is_some() {
let active_stage: StageResponse = deps.querier.query_wasm_smart(
whitelist.clone(),
&TieredWhitelistQueryMsg::Stage {
stage_id: wl_mint_count.2.unwrap() - 1,
},
)?;
if active_stage.stage.mint_count_limit.is_some() {
let stage_mint_count = match wl_mint_count.2.unwrap() {
1 => WHITELIST_FS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
2 => WHITELIST_SS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
3 => WHITELIST_TS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0),
_ => return Err(ContractError::InvalidStageID {}),
};
if stage_mint_count >= active_stage.stage.mint_count_limit.unwrap() {
return Err(ContractError::WhitelistMintCountLimitReached {});
}
}
}

Ok(false)
}

Expand Down Expand Up @@ -489,9 +512,27 @@ fn save_whitelist_mint_count(
) -> StdResult<()> {
if is_tiered_whitelist & stage_id.is_some() {
match stage_id {
Some(1) => WHITELIST_FS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(2) => WHITELIST_SS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(3) => WHITELIST_TS_MINTER_ADDRS.save(deps.storage, &info.sender, &count),
Some(1) => {
let _ = WHITELIST_FS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_fs_mint_count =
WHITELIST_FS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_fs_mint_count += 1;
WHITELIST_FS_MINT_COUNT.save(deps.storage, &wl_fs_mint_count)
}
Some(2) => {
let _ = WHITELIST_SS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_ss_mint_count =
WHITELIST_SS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_ss_mint_count += 1;
WHITELIST_SS_MINT_COUNT.save(deps.storage, &wl_ss_mint_count)
}
Some(3) => {
let _ = WHITELIST_TS_MINTER_ADDRS.save(deps.storage, &info.sender, &count);
let mut wl_ts_mint_count =
WHITELIST_TS_MINT_COUNT.may_load(deps.storage)?.unwrap_or(0);
wl_ts_mint_count += 1;
WHITELIST_TS_MINT_COUNT.save(deps.storage, &wl_ts_mint_count)
}
_ => Err(StdError::generic_err("Invalid stage ID")),
}
} else {
Expand Down
6 changes: 6 additions & 0 deletions contracts/minters/open-edition-minter/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub enum ContractError {
#[error("Invalid reply ID")]
InvalidReplyID {},

#[error("Invalid stage ID")]
InvalidStageID {},

#[error("Not enough funds sent")]
NotEnoughFunds {},

Expand Down Expand Up @@ -118,6 +121,9 @@ pub enum ContractError {
#[error("Max minting limit per address exceeded")]
MaxPerAddressLimitExceeded {},

#[error("WhitelistMintCountLimitReached")]
WhitelistMintCountLimitReached {},

#[error("Token id: {token_id} already sold")]
TokenIdAlreadySold { token_id: u32 },

Expand Down
3 changes: 3 additions & 0 deletions contracts/minters/open-edition-minter/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub const WHITELIST_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlma");
pub const WHITELIST_FS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlfsma");
pub const WHITELIST_SS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlssma");
pub const WHITELIST_TS_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wltsma");
pub const WHITELIST_FS_MINT_COUNT: Item<u32> = Item::new("wlfsmc");
pub const WHITELIST_SS_MINT_COUNT: Item<u32> = Item::new("wlssmc");
pub const WHITELIST_TS_MINT_COUNT: Item<u32> = Item::new("wltsmc");

/// This keeps track of the mint count
pub const TOTAL_MINT_COUNT: Item<u32> = Item::new("total_mint_count");
Expand Down
Loading
Loading