Skip to content

Commit

Permalink
Add optional mint count limit for whitelist stages
Browse files Browse the repository at this point in the history
  • Loading branch information
MightOfOaks committed Jan 12, 2025
1 parent 5e14a4b commit 5463638
Show file tree
Hide file tree
Showing 39 changed files with 680 additions and 81 deletions.
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

0 comments on commit 5463638

Please sign in to comment.