Skip to content

Commit

Permalink
Refactor update phase config, fix metadata, clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeHartnell authored and Jake Hartnell committed Mar 26, 2024
1 parent ecdfb9d commit 5fc2de8
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 118 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

9 changes: 5 additions & 4 deletions contracts/external/cw-abc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ cw2 = { workspace = true }
cw-storage-plus = { workspace = true }
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
thiserror = { workspace = true }
cw-address-like = { workspace = true }
cw-ownable = { workspace = true }
cw-paginate-storage = { workspace = true }
cw-tokenfactory-issuer = { workspace = true, features = ["library"] }
dao-interface = { workspace = true }
rust_decimal = { workspace = true }
integer-sqrt = { workspace = true }
integer-cbrt = { workspace = true }
getrandom = { workspace = true, features = ["js"] }
thiserror = { workspace = true }
token-bindings = { workspace = true }
cw-ownable = { workspace = true }
cw-paginate-storage = { workspace = true }
cw-tokenfactory-issuer = { workspace = true, features = ["library"] }

[dev-dependencies]
speculoos = { workspace = true }
Expand Down
7 changes: 4 additions & 3 deletions contracts/external/cw-abc/src/abc.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{ensure, Decimal as StdDecimal, Uint128};
use dao_interface::token::NewDenomMetadata;

use crate::curves::{decimal, Constant, Curve, DecimalPlaces, Linear, SquareRoot};
use crate::ContractError;
use token_bindings::Metadata;

#[cw_serde]
pub struct SupplyToken {
/// The denom to create for the supply token
pub subdenom: String,
/// Metadata for the supply token to create
pub metadata: Option<Metadata>,
pub metadata: Option<NewDenomMetadata>,
/// Number of decimal places for the supply token, needed for proper curve math.
/// Default for token factory is 6
pub decimals: u8,
Expand Down Expand Up @@ -87,8 +87,8 @@ impl HatchConfig {

#[cw_serde]
pub struct OpenConfig {
// TODO isn't this the same as initial_allocation_ratio? Maybe clearer to just call it an entrance fee?
/// Percentage of capital put into the Reserve Pool during the Open phase
/// when buying from the curve.
pub allocation_percentage: StdDecimal,
/// Exit taxation ratio
pub exit_tax: StdDecimal,
Expand Down Expand Up @@ -129,6 +129,7 @@ impl ClosedConfig {
pub struct CommonsPhaseConfig {
/// The Hatch phase where initial contributors (Hatchers) participate in a hatch sale.
pub hatch: HatchConfig,
/// TODO Vest tokens after hatch phase
/// The Vesting phase where tokens minted during the Hatch phase are locked (burning is disabled) to combat early speculation/arbitrage.
/// pub vesting: VestingConfig,
/// The Open phase where anyone can mint tokens by contributing the reserve token into the curve and becoming members of the Commons.
Expand Down
93 changes: 63 additions & 30 deletions contracts/external/cw-abc/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@ use token_bindings::{TokenFactoryMsg, TokenFactoryQuery};

use crate::abc::{CommonsPhase, CurveFn, MinMax};
use crate::contract::CwAbcResult;
use crate::msg::UpdatePhaseConfigMsg;
use crate::state::{
CURVE_STATE, DONATIONS, HATCHERS, HATCHER_ALLOWLIST, PHASE, PHASE_CONFIG, SUPPLY_DENOM,
TOKEN_ISSUER_CONTRACT,
CURVE_STATE, CURVE_TYPE, DONATIONS, HATCHERS, HATCHER_ALLOWLIST, PHASE, PHASE_CONFIG,
SUPPLY_DENOM, TOKEN_ISSUER_CONTRACT,
};
use crate::ContractError;

pub fn execute_buy(
deps: DepsMut<TokenFactoryQuery>,
_env: Env,
info: MessageInfo,
curve_fn: CurveFn,
) -> CwAbcResult {
pub fn execute_buy(deps: DepsMut<TokenFactoryQuery>, _env: Env, info: MessageInfo) -> CwAbcResult {
let curve_type = CURVE_TYPE.load(deps.storage)?;
let curve_fn = curve_type.to_curve_fn();

let mut curve_state = CURVE_STATE.load(deps.storage)?;

let payment = must_pay(&info, &curve_state.reserve_denom)?;
Expand Down Expand Up @@ -115,12 +114,10 @@ fn update_hatcher_contributions(
Ok(())
}

pub fn execute_sell(
deps: DepsMut<TokenFactoryQuery>,
_env: Env,
info: MessageInfo,
curve_fn: CurveFn,
) -> CwAbcResult {
pub fn execute_sell(deps: DepsMut<TokenFactoryQuery>, _env: Env, info: MessageInfo) -> CwAbcResult {
let curve_type = CURVE_TYPE.load(deps.storage)?;
let curve_fn = curve_type.to_curve_fn();

let supply_denom = SUPPLY_DENOM.load(deps.storage)?;
let burn_amount = must_pay(&info, &supply_denom)?;

Expand Down Expand Up @@ -281,35 +278,71 @@ pub fn update_hatch_allowlist(
Ok(Response::new().add_attributes(vec![("action", "update_hatch_allowlist")]))
}

/// Update the hatch config
pub fn update_hatch_config(
pub fn update_phase_config(
deps: DepsMut<TokenFactoryQuery>,
_env: Env,
info: MessageInfo,
initial_raise: Option<MinMax>,
initial_allocation_ratio: Option<StdDecimal>,
update_phase_config_msg: UpdatePhaseConfigMsg,
) -> CwAbcResult {
// Assert that the sender is the contract owner
cw_ownable::assert_owner(deps.storage, &info.sender)?;

// Ensure we're in the Hatch phase
PHASE.load(deps.storage)?.expect_hatch()?;
// Load phase and phase config
let phase = PHASE.load(deps.storage)?;

// Load the current phase config
let mut phase_config = PHASE_CONFIG.load(deps.storage)?;

// Update the hatch config if new values are provided
if let Some(initial_raise) = initial_raise {
phase_config.hatch.initial_raise = initial_raise;
}
if let Some(initial_allocation_ratio) = initial_allocation_ratio {
phase_config.hatch.initial_allocation_ratio = initial_allocation_ratio;
}
match update_phase_config_msg {
UpdatePhaseConfigMsg::Hatch {
exit_tax,
initial_raise,
initial_allocation_ratio,
} => {
// Check we are in the hatch phase
phase.expect_hatch()?;

// Update the hatch config if new values are provided
if let Some(initial_raise) = initial_raise {
phase_config.hatch.initial_raise = initial_raise;
}
if let Some(initial_allocation_ratio) = initial_allocation_ratio {
phase_config.hatch.initial_allocation_ratio = initial_allocation_ratio;
}
if let Some(exit_tax) = exit_tax {
phase_config.hatch.exit_tax = exit_tax;
}

phase_config.hatch.validate()?;
PHASE_CONFIG.save(deps.storage, &phase_config)?;
// Validate config
phase_config.hatch.validate()?;
PHASE_CONFIG.save(deps.storage, &phase_config)?;

Ok(Response::new().add_attribute("action", "update_hatch_config"))
Ok(Response::new().add_attribute("action", "update_hatch_phase_config"))
}
UpdatePhaseConfigMsg::Open {
exit_tax,
allocation_percentage,
} => {
// Check we are in the open phase
phase.expect_open()?;

// Update the hatch config if new values are provided
if let Some(allocation_percentage) = allocation_percentage {
phase_config.open.allocation_percentage = allocation_percentage;
}
if let Some(exit_tax) = exit_tax {
phase_config.hatch.exit_tax = exit_tax;
}

// Validate config
phase_config.open.validate()?;
PHASE_CONFIG.save(deps.storage, &phase_config)?;

Ok(Response::new().add_attribute("action", "update_open_phase_config"))
}
// TODO what should the closed phase configuration be, is there one?
_ => todo!(),
}
}

/// Update the ownership of the contract
Expand Down
115 changes: 44 additions & 71 deletions contracts/external/cw-abc/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use cosmwasm_std::{
};
use cw2::set_contract_version;
use cw_tokenfactory_issuer::msg::{
ExecuteMsg as IssuerExecuteMsg, InstantiateMsg as IssuerInstantiateMsg,
DenomUnit, ExecuteMsg as IssuerExecuteMsg, InstantiateMsg as IssuerInstantiateMsg, Metadata,
};
use cw_utils::parse_reply_instantiate_data;
use std::collections::HashSet;
Expand Down Expand Up @@ -120,44 +120,17 @@ pub fn execute(
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> CwAbcResult {
// default implementation stores curve info as enum, you can do something else in a derived
// contract and just pass in your custom curve to do_execute
let curve_type = CURVE_TYPE.load(deps.storage)?;
let curve_fn = curve_type.to_curve_fn();
do_execute(deps, env, info, msg, curve_fn)
}

/// We pull out logic here, so we can import this from another contract and set a different Curve.
/// This contacts sets a curve with an enum in InstantiateMsg and stored in state, but you may want
/// to use custom math not included - make this easily reusable
pub fn do_execute(
deps: DepsMut<TokenFactoryQuery>,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
curve_fn: CurveFn,
) -> CwAbcResult {
match msg {
ExecuteMsg::Buy {} => commands::execute_buy(deps, env, info, curve_fn),
ExecuteMsg::Burn {} => commands::execute_sell(deps, env, info, curve_fn),
ExecuteMsg::Buy {} => commands::execute_buy(deps, env, info),
ExecuteMsg::Burn {} => commands::execute_sell(deps, env, info),
ExecuteMsg::Donate {} => commands::execute_donate(deps, env, info),
ExecuteMsg::UpdateHatchAllowlist { to_add, to_remove } => {
commands::update_hatch_allowlist(deps, info, to_add, to_remove)
}
ExecuteMsg::UpdatePhaseConfig(update) => match update {
UpdatePhaseConfigMsg::Hatch {
initial_raise,
initial_allocation_ratio,
} => commands::update_hatch_config(
deps,
env,
info,
initial_raise,
initial_allocation_ratio,
),
_ => todo!(),
},
ExecuteMsg::UpdatePhaseConfig(update_msg) => {
commands::update_phase_config(deps, env, info, update_msg)
}
ExecuteMsg::UpdateOwnership(action) => {
commands::update_ownership(deps, &env, &info, action)
}
Expand Down Expand Up @@ -231,13 +204,15 @@ pub fn reply(
SUPPLY_DENOM.save(deps.storage, &denom)?;

// Msgs to be executed to finalize setup
let msgs: Vec<WasmMsg> = vec![
let mut msgs: Vec<WasmMsg> = vec![
// Grant an allowance to mint
WasmMsg::Execute {
contract_addr: issuer_addr.clone(),
msg: to_binary(&IssuerExecuteMsg::SetMinterAllowance {
address: env.contract.address.to_string(),
// TODO let this be capped
// Allowance needs to be max as this the is the amount of tokens
// the minter is allowed to mint, not to be confused with max supply
// which we have to enforce elsewhere.
allowance: Uint128::MAX,
})?,
funds: vec![],
Expand All @@ -247,48 +222,46 @@ pub fn reply(
contract_addr: issuer_addr.clone(),
msg: to_binary(&IssuerExecuteMsg::SetBurnerAllowance {
address: env.contract.address.to_string(),
// TODO let this be capped
allowance: Uint128::MAX,
})?,
funds: vec![],
},
];

// TODO fix metadata
// // If metadata, set it by calling the contract
// if let Some(metadata) = token_info.metadata {
// // The first denom_unit must be the same as the tf and base denom.
// // It must have an exponent of 0. This the smallest unit of the token.
// // For more info: // https://docs.cosmos.network/main/architecture/adr-024-coin-metadata
// let mut denom_units = vec![DenomUnit {
// denom: denom.clone(),
// exponent: 0,
// aliases: vec![token_info.subdenom],
// }];

// // Caller can optionally define additional units
// if let Some(mut additional_units) = metadata.additional_denom_units {
// denom_units.append(&mut additional_units);
// }

// // Sort denom units by exponent, must be in ascending order
// denom_units.sort_by(|a, b| a.exponent.cmp(&b.exponent));

// msgs.push(WasmMsg::Execute {
// contract_addr: issuer_addr.clone(),
// msg: to_binary(&IssuerExecuteMsg::SetDenomMetadata {
// metadata: Metadata {
// description: metadata.description,
// denom_units,
// base: denom.clone(),
// display: metadata.display,
// name: metadata.name,
// symbol: metadata.symbol,
// },
// })?,
// funds: vec![],
// });
// }
// If metadata, set it by calling the contract
if let Some(metadata) = token_info.metadata {
// The first denom_unit must be the same as the tf and base denom.
// It must have an exponent of 0. This the smallest unit of the token.
// For more info: // https://docs.cosmos.network/main/architecture/adr-024-coin-metadata
let mut denom_units = vec![DenomUnit {
denom: denom.clone(),
exponent: 0,
aliases: vec![token_info.subdenom],
}];

// Caller can optionally define additional units
if let Some(mut additional_units) = metadata.additional_denom_units {
denom_units.append(&mut additional_units);
}

// Sort denom units by exponent, must be in ascending order
denom_units.sort_by(|a, b| a.exponent.cmp(&b.exponent));

msgs.push(WasmMsg::Execute {
contract_addr: issuer_addr.clone(),
msg: to_binary(&IssuerExecuteMsg::SetDenomMetadata {
metadata: Metadata {
description: metadata.description,
denom_units,
base: denom.clone(),
display: metadata.display,
name: metadata.name,
symbol: metadata.symbol,
},
})?,
funds: vec![],
});
}

Ok(Response::new()
.add_attribute("cw-tokenfactory-issuer-address", issuer_addr)
Expand Down
3 changes: 2 additions & 1 deletion contracts/external/cw-abc/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ pub struct InstantiateMsg {
pub enum UpdatePhaseConfigMsg {
/// Update the hatch phase configuration
Hatch {
exit_tax: Option<StdDecimal>,
initial_raise: Option<MinMax>,
initial_allocation_ratio: Option<StdDecimal>,
},
/// Update the open phase configuration
Open {
exit_tax: Option<StdDecimal>,
reserve_ratio: Option<StdDecimal>,
allocation_percentage: Option<StdDecimal>,
},
/// Update the closed phase configuration
Closed {},
Expand Down
Loading

0 comments on commit 5fc2de8

Please sign in to comment.