Skip to content

Commit

Permalink
SG-1034 - fund foundation (#621)
Browse files Browse the repository at this point in the history
* fund foundation

* allow airdrop in stars

* fix airdrop price
  • Loading branch information
jhernandezb authored Oct 9, 2023
1 parent 2abbe21 commit e2cb431
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 102 deletions.
5 changes: 0 additions & 5 deletions contracts/factories/open-edition-factory/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ pub fn instantiate(
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
let params = msg.params;

ensure!(
params.extension.airdrop_mint_price.denom == params.min_mint_price.denom,
BaseContractError::InvalidDenom {}
);

ensure!(
params.creation_fee.denom == NATIVE_DENOM,
BaseContractError::InvalidDenom {}
Expand Down
4 changes: 2 additions & 2 deletions contracts/minters/open-edition-minter/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ fn _execute_mint(

let mint_price: Coin = mint_price(deps.as_ref(), is_admin)?;
// Exact payment only accepted
let payment = may_pay(&info, &config.mint_price.denom)?;
let payment = may_pay(&info, &mint_price.denom)?;
if payment != mint_price.amount {
return Err(ContractError::IncorrectPaymentAmount(
coin(payment.u128(), &config.mint_price.denom),
Expand Down Expand Up @@ -629,7 +629,7 @@ pub fn mint_price(deps: Deps, is_admin: bool) -> Result<Coin, StdError> {
let factory_params = factory.params;
Ok(coin(
factory_params.extension.airdrop_mint_price.amount.u128(),
config.mint_price.denom,
factory_params.extension.airdrop_mint_price.denom,
))
} else {
Ok(config.mint_price)
Expand Down
18 changes: 9 additions & 9 deletions contracts/minters/vending-minter/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use crate::validation::{check_dynamic_per_address_limit, get_three_percent_of_to
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
coin, coins, ensure, to_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut,
Empty, Env, Event, MessageInfo, Order, Reply, ReplyOn, StdError, StdResult, Timestamp, Uint128,
coin, ensure, to_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Empty,
Env, Event, MessageInfo, Order, Reply, ReplyOn, StdError, StdResult, Timestamp, Uint128,
WasmMsg,
};
use cw2::set_contract_version;
Expand All @@ -21,13 +21,11 @@ use cw_utils::{may_pay, maybe_addr, nonpayable, parse_reply_instantiate_data};
use rand_core::{RngCore, SeedableRng};
use rand_xoshiro::Xoshiro128PlusPlus;
use semver::Version;
use sg1::checked_fair_burn;
use sg1::{checked_fair_burn, ibc_denom_fair_burn};
use sg2::query::Sg2QueryMsg;
use sg4::{MinterConfig, Status, StatusResponse, SudoMsg};
use sg721::{ExecuteMsg as Sg721ExecuteMsg, InstantiateMsg as Sg721InstantiateMsg};
use sg_std::{
create_fund_community_pool_msg, StargazeMsgWrapper, GENESIS_MINT_START_TIME, NATIVE_DENOM,
};
use sg_std::{StargazeMsgWrapper, GENESIS_MINT_START_TIME, NATIVE_DENOM};
use sg_whitelist::msg::{
ConfigResponse as WhitelistConfigResponse, HasMemberResponse, QueryMsg as WhitelistQueryMsg,
};
Expand Down Expand Up @@ -655,9 +653,11 @@ fn _execute_mint(
if mint_price.denom != NATIVE_DENOM {
// only send non-zero amounts
if !network_fee.is_zero() {
let msg =
create_fund_community_pool_msg(coins(network_fee.u128(), mint_price.clone().denom));
res = res.add_message(msg);
ibc_denom_fair_burn(
coin(network_fee.u128(), mint_price.clone().denom),
None,
&mut res,
)?;
}
} else {
checked_fair_burn(&info, network_fee.u128(), None, &mut res)?;
Expand Down
37 changes: 18 additions & 19 deletions packages/sg1/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use cosmwasm_std::{coin, coins, Addr, BankMsg, Coin, Decimal, Event, MessageInfo, Uint128};
use cw_utils::{may_pay, PaymentError};
use sg_std::{
create_fund_community_pool_msg, create_fund_fairburn_pool_msg, Response, SubMsg, NATIVE_DENOM,
};
use sg_std::{create_fund_fairburn_pool_msg, Response, SubMsg, NATIVE_DENOM};
use thiserror::Error;

// governance parameters
const FEE_BURN_PERCENT: u64 = 50;
const FOUNDATION: &str = "stars1xqz6xujjyz0r9uzn7srasle5uynmpa0zkjr5l8";

/// Burn and distribute fees and return an error if the fee is not enough
pub fn checked_fair_burn(
Expand Down Expand Up @@ -39,31 +38,31 @@ pub fn ibc_denom_fair_burn(

match &developer {
Some(developer) => {
// Calculate the fees. 50% to dev, 50% to community pool
// Calculate the fees. 50% to dev, 50% to foundation
let dev_fee = (fee.amount.mul_ceil(Decimal::percent(FEE_BURN_PERCENT))).u128();
let dev_coin = coins(dev_fee, fee.denom.to_string());
let comm_fee = coin(fee.amount.u128() - dev_fee, fee.denom.to_string());
let dev_coin = coin(dev_fee, fee.denom.to_string());
let foundation_coin = coin(fee.amount.u128() - dev_fee, fee.denom);

event = event.add_attribute("dev_addr", developer.to_string());
event = event.add_attribute("dev_denom", fee.denom.to_string());
event = event.add_attribute("dev_amount", fee.amount.u128().to_string());
event = event.add_attribute("com_pool_denom", comm_fee.denom.to_string());
event = event.add_attribute("com_pool_amount", comm_fee.amount.u128().to_string());
event = event.add_attribute("dev_coin", dev_coin.to_string());
event = event.add_attribute("foundation_coin", foundation_coin.to_string());

res.messages.push(SubMsg::new(BankMsg::Send {
to_address: developer.to_string(),
amount: dev_coin,
amount: vec![dev_coin],
}));
res.messages.push(SubMsg::new(BankMsg::Send {
to_address: FOUNDATION.to_string(),
amount: vec![foundation_coin],
}));
res.messages
.push(SubMsg::new(create_fund_community_pool_msg(vec![comm_fee])));
}
None => {
// No dev, send all to community pool.
event = event.add_attribute("com_pool_denom", fee.denom.to_string());
event = event.add_attribute("com_pool_amount", fee.amount.u128().to_string());

res.messages
.push(SubMsg::new(create_fund_community_pool_msg(vec![fee])));
// No dev, send all to foundation.
event = event.add_attribute("foundation_coin", fee.to_string());
res.messages.push(SubMsg::new(BankMsg::Send {
to_address: FOUNDATION.to_string(),
amount: vec![fee],
}));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ pub const SHUFFLE_FEE: u128 = 500_000_000;
pub const MAX_PER_ADDRESS_LIMIT: u32 = 50;
pub const DEV_ADDRESS: &str = "stars1abcd4kdla12mh86psg4y4h6hh05g2hmqoap350";
pub const MIN_MINT_PRICE_OPEN_EDITION: u128 = 100_000_000;
pub const FOUNDATION: &str = "stars1xqz6xujjyz0r9uzn7srasle5uynmpa0zkjr5l8";
66 changes: 3 additions & 63 deletions test-suite/src/open_edition_minter/tests/ibc_asset_mint.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
use base_factory::ContractError as BaseContractError;
use cosmwasm_std::{coin, Addr, Coin, Decimal, Uint128};
use cw_multi_test::{BankSudo, Executor, SudoMsg};
use open_edition_factory::{
state::{OpenEditionMinterParams, ParamsExtension},
types::{NftData, NftMetadataType},
};
use open_edition_factory::state::{OpenEditionMinterParams, ParamsExtension};
use open_edition_minter::msg::ExecuteMsg;
use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM};

use crate::common_setup::{
setup_accounts_and_block::setup_block_time,
setup_minter::{
common::constants::{
CREATION_FEE, DEV_ADDRESS, MINT_FEE_FAIR_BURN, MIN_MINT_PRICE_OPEN_EDITION,
CREATION_FEE, DEV_ADDRESS, FOUNDATION, MINT_FEE_FAIR_BURN, MIN_MINT_PRICE_OPEN_EDITION,
},
open_edition_minter::minter_params::{default_nft_data, init_msg},
},
Expand Down Expand Up @@ -166,7 +162,7 @@ fn one_hundred_percent_burned_ibc_minter() {
// "community_pool" address from packages/sg-multi-test/src/multi.rs
let balance = router
.wrap()
.query_balance(Addr::unchecked("community_pool"), denom)
.query_balance(Addr::unchecked(FOUNDATION), denom)
.unwrap();
assert_eq!(balance.amount, mint_price.amount * Decimal::percent(50));
}
Expand Down Expand Up @@ -236,59 +232,3 @@ fn zero_mint_fee() {
let res = router.execute_contract(buyer, minter_addr, &mint_msg, &[mint_price]);
assert!(res.is_ok());
}

#[test]
fn denom_mismatch_creating_minter() {
// create factory w NATIVE_DENOM, then try creating a minter w different denom
let denom = "ibc/asset";
let mint_price = coin(MIN_MINT_PRICE_OPEN_EDITION, denom.to_string());
let mismatch_denom = coin(MIN_MINT_PRICE_OPEN_EDITION, NATIVE_DENOM);
let nft_data = NftData {
nft_data_type: NftMetadataType::OffChainMetadata,
token_uri: Some("ipfs://1234".to_string()),
extension: None,
};

let params_extension = ParamsExtension {
max_per_address_limit: 10,
airdrop_mint_fee_bps: 100,
airdrop_mint_price: Coin {
denom: mint_price.to_string(),
amount: Uint128::new(100_000_000u128),
},
dev_fee_address: DEV_ADDRESS.to_string(),
};
let per_address_limit_minter = Some(2);
let init_msg = init_msg(
nft_data,
per_address_limit_minter,
None,
None,
Some(mint_price.clone()),
);
let custom_minter_params = OpenEditionMinterParams {
code_id: 1,
allowed_sg721_code_ids: vec![1, 2, 3, 5, 6],
frozen: false,
creation_fee: coin(CREATION_FEE, NATIVE_DENOM),
min_mint_price: mint_price,
mint_fee_bps: MINT_FEE_FAIR_BURN,
max_trading_offset_secs: 60 * 60 * 24 * 7,
extension: ParamsExtension {
max_per_address_limit: 10,
airdrop_mint_fee_bps: 100,
dev_fee_address: DEV_ADDRESS.to_string(),
airdrop_mint_price: mismatch_denom,
},
};

let vt =
open_edition_minter_ibc_template(params_extension, init_msg, custom_minter_params).unwrap();
let err = vt.collection_response_vec[0]
.error
.as_ref()
.unwrap()
.root_cause()
.to_string();
assert_eq!(err, BaseContractError::InvalidDenom {}.to_string());
}
28 changes: 24 additions & 4 deletions test-suite/src/vending_minter/tests/ibc_asset_mint.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::common_setup::setup_collection_whitelist::WHITELIST_AMOUNT;
use cosmwasm_std::{coin, coins, Addr};
use crate::common_setup::{
setup_collection_whitelist::WHITELIST_AMOUNT, setup_minter::common::constants::FOUNDATION,
};
use cosmwasm_std::{coin, coins, Addr, Decimal, Uint128};
use cw_multi_test::{BankSudo, Executor, SudoMsg};
use sg2::{msg::Sg2ExecuteMsg, tests::mock_collection_params};
use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM};
Expand Down Expand Up @@ -124,7 +126,7 @@ fn wl_denom_mismatch() {
err.source().unwrap().to_string(),
MinterContractError::InvalidDenom {
expected: NATIVE_DENOM.to_string(),
got: denom.to_string()
got: denom.to_string(),
}
.to_string()
);
Expand Down Expand Up @@ -238,6 +240,24 @@ fn wl_denom_mint() {

// Whitelist mint succeeds
let mint_msg = ExecuteMsg::Mint {};
let res = app.execute_contract(buyer, minter_addr, &mint_msg, &[wl_mint_price]);
let res = app.execute_contract(
buyer.clone(),
minter_addr,
&mint_msg,
&[wl_mint_price.clone()],
);
assert!(res.is_ok());

// confirm balances
// confirm buyer IBC assets spent
let balance = app.wrap().query_balance(buyer, denom).unwrap();
assert_eq!(balance.amount, Uint128::zero());
// for seller should get 90% of IBC asset
let balance = app.wrap().query_balance(creator, denom).unwrap();
assert_eq!(balance.amount, wl_mint_price.amount * Decimal::percent(90));
let balance = app
.wrap()
.query_balance(Addr::unchecked(FOUNDATION), denom)
.unwrap();
assert_eq!(balance.amount, wl_mint_price.amount * Decimal::percent(10));
}

0 comments on commit e2cb431

Please sign in to comment.