Skip to content

Commit

Permalink
Track mint counts for each tiered whitelist stage
Browse files Browse the repository at this point in the history
  • Loading branch information
MightOfOaks committed Oct 31, 2024
1 parent 835c76f commit 69ea6bd
Show file tree
Hide file tree
Showing 35 changed files with 940 additions and 105 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,21 @@ sg-multi-test = { version = "3.1.0" }
sg-splits = { version = "3.14.0", path = "contracts/splits" }
sg-std = { version = "3.2.0" }
sg-whitelist = { version = "3.14.0", path = "contracts/whitelists/whitelist" }
sg-tiered-whitelist = { version = "3.14.0", path = "contracts/whitelists/tiered-whitelist" }
thiserror = "1.0.31"
url = "2.2.2"
sha2 = { version = "0.10.2", default-features = false }

whitelist-mtree = { version = "3.14.0", path = "contracts/whitelists/whitelist-merkletree" }
tiered-whitelist-merkletree = { version = "3.14.0", path = "contracts/whitelists/tiered-whitelist-merkletree" }
vending-minter-merkle-wl = { version = "3.14.0", path = "contracts/minters/vending-minter-merkle-wl" }
vending-factory = { version = "3.14.0", path = "contracts/factories/vending-factory" }
vending-minter = { version = "3.14.0", path = "contracts/minters/vending-minter" }
open-edition-factory = { version = "3.14.0", path = "contracts/factories/open-edition-factory" }
open-edition-minter = { version = "3.14.0", path = "contracts/minters/open-edition-minter" }
whitelist-immutable = { version = "3.14.0", path = "contracts/whitelists/whitelist-immutable" }
sg-whitelist-flex = { version = "3.14.0", path = "contracts/whitelists/whitelist-flex" }
sg-tiered-whitelist-flex = { version = "3.14.0", path = "contracts/whitelists/tiered-whitelist-flex" }
ethereum-verify = { version = "3.14.0", path = "packages/ethereum-verify" }
sg-eth-airdrop = { version = "3.14.0", path = "contracts/sg-eth-airdrop" }
test-suite = { version = "3.14.0", path = "test-suite" }
Expand Down
1 change: 1 addition & 0 deletions contracts/minters/open-edition-minter-merkle-wl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ sg721 = { workspace = true }
sg-std = { workspace = true }
sg-whitelist = { workspace = true, features = ["library"] }
whitelist-mtree = { workspace = true, features = ["library"] }
tiered-whitelist-merkletree = { workspace = true, features = ["library"] }
sg-metadata = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
Expand Down
109 changes: 99 additions & 10 deletions contracts/minters/open-edition-minter-merkle-wl/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::msg::{
};
use crate::state::{
increment_token_index, Config, ConfigExtension, CONFIG, MINTABLE_NUM_TOKENS, MINTER_ADDRS,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT,
SG721_ADDRESS, STATUS, TOTAL_MINT_COUNT, WHITELIST_FS_MINTER_ADDRS, WHITELIST_MINTER_ADDRS,
WHITELIST_SS_MINTER_ADDRS, WHITELIST_TS_MINTER_ADDRS,
};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
Expand All @@ -25,6 +26,7 @@ use sg2::query::Sg2QueryMsg;
use sg4::{MinterConfig, Status, StatusResponse, SudoMsg};
use sg721::{ExecuteMsg as Sg721ExecuteMsg, InstantiateMsg as Sg721InstantiateMsg};
use sg_std::{StargazeMsgWrapper, NATIVE_DENOM};
use tiered_whitelist_merkletree::msg::QueryMsg as TieredWhitelistQueryMsg;
use url::Url;
use whitelist_mtree::msg::{
ConfigResponse as WhitelistConfigResponse, HasMemberResponse, QueryMsg as WhitelistQueryMsg,
Expand Down Expand Up @@ -373,12 +375,13 @@ pub fn execute_mint_sender(
}

// Check if already minted max per address limit
if matches!(mint_count_per_addr(deps.as_ref(), &info)?, count if count >= config.extension.per_address_limit)
if is_public_mint
& matches!(mint_count_per_addr(deps.as_ref(), &info)?, count if count >= config.extension.per_address_limit)
{
return Err(ContractError::MaxPerAddressLimitExceeded {});
}

_execute_mint(deps, env, info, action, false, None)
_execute_mint(deps, env, info, action, false, None, is_public_mint)
}

// Check if a whitelist exists and not ended
Expand Down Expand Up @@ -409,7 +412,7 @@ fn is_public_mint(

let res: HasMemberResponse = if proof_hashes.is_some() {
deps.querier.query_wasm_smart(
whitelist,
whitelist.clone(),
&WhitelistQueryMsg::HasMember {
member: match (stage, allocation) {
(None, Some(allocation)) => format!("{}{}", info.sender, allocation),
Expand All @@ -433,12 +436,12 @@ fn is_public_mint(
}

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

Expand Down Expand Up @@ -476,19 +479,20 @@ pub fn execute_mint_to(
}
}

_execute_mint(deps, env, info, action, true, Some(recipient))
_execute_mint(deps, env, info, action, true, Some(recipient), true)
}

// Generalize checks and mint message creation
// mint -> _execute_mint(recipient: None, token_id: None)
// mint_to(recipient: "friend") -> _execute_mint(Some(recipient), token_id: None)
fn _execute_mint(
deps: DepsMut,
mut deps: DepsMut,
_env: Env,
info: MessageInfo,
action: &str,
is_admin: bool,
recipient: Option<Addr>,
is_public: bool,
) -> Result<Response, ContractError> {
let mintable_num_tokens = MINTABLE_NUM_TOKENS.may_load(deps.storage)?;
if let Some(mintable_nb_tokens) = mintable_num_tokens {
Expand Down Expand Up @@ -579,8 +583,21 @@ fn _execute_mint(
res = res.add_message(msg);

// Save the new mint count for the sender's address
let new_mint_count = mint_count_per_addr(deps.as_ref(), &info)? + 1;
MINTER_ADDRS.save(deps.storage, &info.sender, &new_mint_count)?;
if is_public {
let new_mint_count = mint_count(deps.as_ref(), &info)? + 1;
MINTER_ADDRS.save(deps.storage, &info.sender, &new_mint_count)?;
} else {
let whitelist_addr = config.extension.whitelist.unwrap();
// Fetch and increment the mint count for the current whitelist stage
let wl_mint_count_response = whitelist_mint_count(deps.as_ref(), &info, whitelist_addr)?;
save_whitelist_mint_count(
deps.branch(),
&info,
wl_mint_count_response.1,
wl_mint_count_response.2,
wl_mint_count_response.0 + 1,
)?
}

// Update the mint count
TOTAL_MINT_COUNT.update(
Expand Down Expand Up @@ -940,6 +957,78 @@ fn mint_count_per_addr(deps: Deps, info: &MessageInfo) -> Result<u32, StdError>
Ok(mint_count)
}

// Returns the stored whitelist mint count, whether the whitelist is a tiered wl, and the stage id if applicable
fn whitelist_mint_count(
deps: Deps,
info: &MessageInfo,
whitelist_addr: Addr,
) -> Result<(u32, bool, Option<u32>), StdError> {
let is_tiered_whitelist = cw2::query_contract_info(&deps.querier, whitelist_addr.clone())
.map(|info| info.contract.contains("tiered-whitelist"))
.unwrap_or(false);

if is_tiered_whitelist {
let active_stage_id = deps
.querier
.query_wasm_smart(whitelist_addr, &TieredWhitelistQueryMsg::ActiveStageId {})?;
match active_stage_id {
1 => Ok((
WHITELIST_FS_MINTER_ADDRS
.key(&info.sender)
.may_load(deps.storage)?
.unwrap_or(0),
true,
Some(1),
)),
2 => Ok((
WHITELIST_SS_MINTER_ADDRS
.key(&info.sender)
.may_load(deps.storage)?
.unwrap_or(0),
true,
Some(2),
)),
3 => Ok((
WHITELIST_TS_MINTER_ADDRS
.key(&info.sender)
.may_load(deps.storage)?
.unwrap_or(0),
true,
Some(3),
)),
_ => Err(StdError::generic_err("Invalid stage ID")),
}
} else {
Ok((
WHITELIST_MINTER_ADDRS
.key(&info.sender)
.may_load(deps.storage)?
.unwrap_or(0),
false,
None,
))
}
}

fn save_whitelist_mint_count(
deps: DepsMut,
info: &MessageInfo,
is_tiered_whitelist: bool,
stage_id: Option<u32>,
count: u32,
) -> 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),
_ => Err(StdError::generic_err("Invalid stage ID")),
}
} else {
WHITELIST_MINTER_ADDRS.save(deps.storage, &info.sender, &count)
}
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result<Response, ContractError> {
match msg {
Expand Down
7 changes: 6 additions & 1 deletion contracts/minters/open-edition-minter-merkle-wl/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ pub type Config = MinterConfig<ConfigExtension>;
pub const CONFIG: Item<Config> = Item::new("config");
pub const SG721_ADDRESS: Item<Addr> = Item::new("sg721_address");
pub const MINTER_ADDRS: Map<&Addr, u32> = Map::new("ma");

// Keep track of the number of tokens minted by each address for regular whitelists
pub const WHITELIST_MINTER_ADDRS: Map<&Addr, u32> = Map::new("wlma");
// Keep track of the number of tokens minted by each address for first, second & third tiered whitelist stages
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");
/// This keeps track of the mint count
pub const TOTAL_MINT_COUNT: Item<u32> = Item::new("total_mint_count");

Expand Down
1 change: 1 addition & 0 deletions contracts/minters/open-edition-minter-wl-flex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ sg4 = { workspace = true }
sg721 = { workspace = true }
sg-std = { workspace = true }
sg-whitelist-flex = { workspace = true, features = ["library"] }
sg-tiered-whitelist-flex = { workspace = true, features = ["library"] }
sg-metadata = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
Expand Down
Loading

0 comments on commit 69ea6bd

Please sign in to comment.