Skip to content

Commit

Permalink
Convert minter to accept flat rate discounts only
Browse files Browse the repository at this point in the history
  • Loading branch information
MightOfOaks committed Mar 26, 2024
1 parent 5f2654a commit 44a5172
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 196 deletions.
188 changes: 53 additions & 135 deletions contracts/name-minter/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@ use sg_name::{Metadata, SgNameExecuteMsg};
use sg_name_common::{charge_fees, SECONDS_PER_YEAR};
use sg_name_minter::{Config, SudoParams, PUBLIC_MINT_START_TIME_IN_SECONDS};
use sg_std::{Response, SubMsg, NATIVE_DENOM};
use whitelist_updatable::helpers::WhitelistUpdatableContract;
use whitelist_updatable_flatrate::helpers::WhitelistUpdatableFlatrateContract;

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg};
use crate::state::{
WhitelistContract, ADMIN, CONFIG, NAME_COLLECTION, NAME_MARKETPLACE, PAUSED, SUDO_PARAMS,
WHITELISTS,
ADMIN, CONFIG, NAME_COLLECTION, NAME_MARKETPLACE, PAUSED, SUDO_PARAMS, WHITELISTS,
};

// version info for migration info
Expand Down Expand Up @@ -56,8 +54,7 @@ pub fn instantiate(
.whitelists
.iter()
.filter_map(|addr| api.addr_validate(addr).ok())
.map(WhitelistUpdatableContract)
.map(WhitelistContract::Updatable)
.map(WhitelistUpdatableFlatrateContract)
.collect::<Vec<_>>();

WHITELISTS.save(deps.storage, &lists)?;
Expand Down Expand Up @@ -132,14 +129,8 @@ pub fn execute(
Ok(ADMIN.execute_update_admin(deps, info, maybe_addr(api, admin)?)?)
}
ExecuteMsg::Pause { pause } => execute_pause(deps, info, pause),
ExecuteMsg::AddWhitelist {
address,
whitelist_type,
} => execute_add_whitelist(deps, info, address, whitelist_type),
ExecuteMsg::RemoveWhitelist {
address,
whitelist_type,
} => execute_remove_whitelist(deps, info, address, whitelist_type),
ExecuteMsg::AddWhitelist { address } => execute_add_whitelist(deps, info, address),
ExecuteMsg::RemoveWhitelist { address } => execute_remove_whitelist(deps, info, address),
ExecuteMsg::UpdateConfig { config } => execute_update_config(deps, info, env, config),
}
}
Expand All @@ -166,13 +157,10 @@ pub fn execute_mint_and_list(
// Assumes no duplicate addresses between whitelists
// Otherwise there will be edge cases with per addr limit between the whitelists

let list = whitelists.iter().find(|whitelist| match whitelist {
WhitelistContract::Updatable(updatable) => updatable
let list = whitelists.iter().find(|whitelist| {
whitelist
.includes(&deps.querier, sender.to_string())
.unwrap_or(false),
WhitelistContract::Flatrate(flatrate) => flatrate
.includes(&deps.querier, sender.to_string())
.unwrap_or(false),
.unwrap_or(false)
});

// if not on any whitelist, check public mint start time
Expand All @@ -181,34 +169,24 @@ pub fn execute_mint_and_list(
}

let discount = list
.map(|whitelist| match whitelist {
WhitelistContract::Updatable(updatable) => {
res.messages
.push(SubMsg::new(updatable.process_address(sender)?));
updatable.mint_discount_percent(&deps.querier)
}
WhitelistContract::Flatrate(flatrate) => {
res.messages
.push(SubMsg::new(flatrate.process_address(sender)?));
flatrate.mint_discount_amount(&deps.querier)
}
.map(|list| {
res.messages
.push(SubMsg::new(list.process_address(sender)?));
list.mint_discount_amount(&deps.querier)
})
.transpose()?
.unwrap_or(None);

let whitelist_type = list.map(|whitelist| match whitelist {
WhitelistContract::Updatable(_) => Some(WhitelistType::Updatable),
WhitelistContract::Flatrate(_) => Some(WhitelistType::Flatrate),
});
println!("discount: {:?}", discount);

let price = validate_payment(
name.len(),
&info,
params.base_price.u128(),
discount,
whitelist_type.unwrap_or(None),
)?;
charge_fees(&mut res, params.fair_burn_percent, price.amount);
let price = validate_payment(name.len(), &info, params.base_price.u128(), discount)?;
if price.clone().is_some() {
charge_fees(
&mut res,
params.fair_burn_percent,
price.clone().unwrap().amount,
);
}

let collection = NAME_COLLECTION.load(deps.storage)?;
let marketplace = NAME_MARKETPLACE.load(deps.storage)?;
Expand Down Expand Up @@ -238,7 +216,10 @@ pub fn execute_mint_and_list(
let event = Event::new("mint-and-list")
.add_attribute("name", name)
.add_attribute("owner", sender)
.add_attribute("price", price.amount.to_string());
.add_attribute(
"price",
price.unwrap_or(coin(0, NATIVE_DENOM)).amount.to_string(),
);
Ok(res
.add_event(event)
.add_message(mint_msg_exec)
Expand All @@ -259,34 +240,17 @@ pub fn execute_pause(
Ok(Response::new().add_event(event))
}

#[derive(Eq, PartialEq, Clone, JsonSchema, Deserialize, Debug, Serialize)]
pub enum WhitelistType {
Updatable,
Flatrate,
}

pub fn execute_add_whitelist(
deps: DepsMut,
info: MessageInfo,
address: String,
whitelist_type: Option<WhitelistType>,
) -> Result<Response, ContractError> {
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;

let whitelist_type = whitelist_type.unwrap_or(WhitelistType::Updatable);

let whitelist = match whitelist_type {
WhitelistType::Updatable => WhitelistContract::Updatable(
deps.api
.addr_validate(&address)
.map(WhitelistUpdatableContract)?,
),
WhitelistType::Flatrate => WhitelistContract::Flatrate(
deps.api
.addr_validate(&address)
.map(WhitelistUpdatableFlatrateContract)?,
),
};
let whitelist = deps
.api
.addr_validate(&address)
.map(WhitelistUpdatableFlatrateContract)?;

let mut lists = WHITELISTS.load(deps.storage)?;
lists.push(whitelist);
Expand All @@ -301,25 +265,12 @@ pub fn execute_remove_whitelist(
deps: DepsMut,
info: MessageInfo,
address: String,
whitelist_type: Option<WhitelistType>,
) -> Result<Response, ContractError> {
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;

let whitelist_type = whitelist_type.unwrap_or(WhitelistType::Updatable);
let whitelist_addr = deps.api.addr_validate(&address)?;

let whitelist = deps.api.addr_validate(&address)?;
let mut lists = WHITELISTS.load(deps.storage)?;
lists.retain(|whitelist| {
let addr_matches = match whitelist {
WhitelistContract::Updatable(updatable) => updatable.addr() == whitelist_addr,
WhitelistContract::Flatrate(flatrate) => flatrate.addr() == whitelist_addr,
};
let type_matches = match whitelist {
WhitelistContract::Updatable(_) => whitelist_type == WhitelistType::Updatable,
WhitelistContract::Flatrate(_) => whitelist_type == WhitelistType::Flatrate,
};
!(addr_matches && type_matches)
});
lists.retain(|addr| addr.addr() != whitelist);

WHITELISTS.save(deps.storage, &lists)?;

Expand Down Expand Up @@ -379,9 +330,8 @@ fn validate_payment(
name_len: usize,
info: &MessageInfo,
base_price: u128,
discount: Option<Decimal>,
whitelist_type: Option<WhitelistType>,
) -> Result<Coin, ContractError> {
discount: Option<u64>,
) -> Result<Option<Coin>, ContractError> {
// Because we know we are left with ASCII chars, a simple byte count is enough
let mut amount: Uint128 = (match name_len {
0..=2 => {
Expand All @@ -393,23 +343,15 @@ fn validate_payment(
})
.into();

amount = match whitelist_type {
Some(WhitelistType::Updatable) => discount
.map(|d| amount * (Decimal::one() - d))
.unwrap_or(amount),
Some(WhitelistType::Flatrate) => {
// we assume that discount is a flat amount and
// not a percentage and is a whole number
discount
.map(|d| amount - (d * Uint128::from(1u128)))
.unwrap_or(amount)
}
None => amount,
};
if discount.is_some() && amount.ge(&Uint128::from(discount.unwrap())) {
amount = amount
.checked_sub(Uint128::from(discount.unwrap()))
.unwrap();
}

// let amount = discount
// .map(|d| amount * (Decimal::one() - d))
// .unwrap_or(amount);
if amount.is_zero() {
return Ok(None);
}

let payment = must_pay(info, NATIVE_DENOM)?;
if payment != amount {
Expand All @@ -419,7 +361,7 @@ fn validate_payment(
});
}

Ok(coin(amount.u128(), NATIVE_DENOM))
Ok(Some(coin(amount.u128(), NATIVE_DENOM)))
}

fn invalid_char(c: char) -> bool {
Expand Down Expand Up @@ -489,7 +431,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, Contra
mod tests {
use cosmwasm_std::{coin, Addr, Decimal, MessageInfo};

use crate::contract::{validate_name, WhitelistType};
use crate::contract::validate_name;

use super::validate_payment;

Expand Down Expand Up @@ -534,7 +476,8 @@ mod tests {
funds: vec![coin(base_price, "ustars")],
};
assert_eq!(
validate_payment(5, &info, base_price, None, None)
validate_payment(5, &info, base_price, None)
.unwrap()
.unwrap()
.amount
.u128(),
Expand All @@ -546,7 +489,8 @@ mod tests {
funds: vec![coin(base_price * 10, "ustars")],
};
assert_eq!(
validate_payment(4, &info, base_price, None, None)
validate_payment(4, &info, base_price, None)
.unwrap()
.unwrap()
.amount
.u128(),
Expand All @@ -558,36 +502,15 @@ mod tests {
funds: vec![coin(base_price * 100, "ustars")],
};
assert_eq!(
validate_payment(3, &info, base_price, None, None)
validate_payment(3, &info, base_price, None)
.unwrap()
.unwrap()
.amount
.u128(),
base_price * 100
);
}

#[test]
fn check_validate_payment_with_discount() {
let base_price = 100_000_000;

let info = MessageInfo {
sender: Addr::unchecked("sender"),
funds: vec![coin(base_price / 2, "ustars")],
};
assert_eq!(
validate_payment(
5,
&info,
base_price,
Some(Decimal::percent(50)),
Some(WhitelistType::Updatable)
)
.unwrap()
.amount
.u128(),
base_price / 2
);
}
#[test]
fn check_validate_payment_with_flatrate_discount() {
let base_price = 100_000_000;
Expand All @@ -598,16 +521,11 @@ mod tests {
};
assert_eq!(
// we treat the discount as a flat amount given as 100.0
validate_payment(
5,
&info,
base_price,
Some(Decimal::from_ratio(10000u128, 100u128)),
Some(WhitelistType::Flatrate)
)
.unwrap()
.amount
.u128(),
validate_payment(5, &info, base_price, Some(100),)
.unwrap()
.unwrap()
.amount
.u128(),
base_price - 100
);
}
Expand Down
Loading

0 comments on commit 44a5172

Please sign in to comment.