From fc5d5d6847e9679b83d1aa6c4309b92487e5482e Mon Sep 17 00:00:00 2001 From: Jake Hartnell Date: Wed, 30 Aug 2023 16:23:14 -0700 Subject: [PATCH] Clean up and notes --- contracts/external/cw-abc/src/contract.rs | 265 ++-------------------- contracts/external/cw-abc/src/testing.rs | 225 +++++++++++++++++- 2 files changed, 232 insertions(+), 258 deletions(-) diff --git a/contracts/external/cw-abc/src/contract.rs b/contracts/external/cw-abc/src/contract.rs index cbb782385..55c4d18cb 100644 --- a/contracts/external/cw-abc/src/contract.rs +++ b/contracts/external/cw-abc/src/contract.rs @@ -60,21 +60,6 @@ pub fn instantiate( phase_config.validate()?; - // Tnstantiate cw-token-factory-issuer contract - // DAO (sender) is set as contract admin - let issuer_instantiate_msg = SubMsg::reply_always( - WasmMsg::Instantiate { - admin: Some(info.sender.to_string()), - code_id: token_issuer_code_id, - msg: to_binary(&IssuerInstantiateMsg::NewToken { - subdenom: supply.subdenom.clone(), - })?, - funds: info.funds, - label: "cw-tokenfactory-issuer".to_string(), - }, - INSTANTIATE_TOKEN_FACTORY_ISSUER_REPLY_ID, - ); - // Save new token info for use in reply TOKEN_INSTANTIATION_INFO.save(deps.storage, &supply)?; @@ -108,8 +93,25 @@ pub fn instantiate( // TODO don't hardcode this? PHASE.save(deps.storage, &CommonsPhase::Hatch)?; + // Initialize owner to sender cw_ownable::initialize_owner(deps.storage, deps.api, Some(info.sender.as_str()))?; + // TODO Potential renounce admin? + // Tnstantiate cw-token-factory-issuer contract + // Sender is set as contract admin + let issuer_instantiate_msg = SubMsg::reply_always( + WasmMsg::Instantiate { + admin: Some(info.sender.to_string()), + code_id: token_issuer_code_id, + msg: to_binary(&IssuerInstantiateMsg::NewToken { + subdenom: supply.subdenom.clone(), + })?, + funds: info.funds, + label: "cw-tokenfactory-issuer".to_string(), + }, + INSTANTIATE_TOKEN_FACTORY_ISSUER_REPLY_ID, + ); + Ok(Response::default().add_submessage(issuer_instantiate_msg)) } @@ -224,30 +226,11 @@ pub fn reply( let token_info = TOKEN_INSTANTIATION_INFO.load(deps.storage)?; TOKEN_INSTANTIATION_INFO.remove(deps.storage); - // // Load the DAO address - // let dao = DAO.load(deps.storage)?; - // Format the denom and save it let denom = format!("factory/{}/{}", &issuer_addr, token_info.subdenom); SUPPLY_DENOM.save(deps.storage, &denom)?; - // // Check supply is greater than zero, iterate through initial - // // balances and sum them, add DAO balance as well. - // let initial_supply = token - // .initial_balances - // .iter() - // .fold(Uint128::zero(), |previous, new_balance| { - // previous + new_balance.amount - // }); - // let total_supply = initial_supply + token.initial_dao_balance.unwrap_or_default(); - - // // Cannot instantiate with no initial token owners because it would - // // immediately lock the DAO. - // if initial_supply.is_zero() { - // return Err(ContractError::InitialBalancesError {}); - // } - // Msgs to be executed to finalize setup let mut msgs: Vec = vec![]; @@ -316,217 +299,3 @@ pub fn reply( _ => Err(ContractError::UnknownReplyId { id: msg.id }), } } - -// #[cfg(test)] -// pub(crate) mod tests { -// use super::*; -// use crate::abc::CurveType; -// use crate::queries::query_curve_info; -// use cosmwasm_std::{ -// testing::{mock_env, mock_info}, -// CosmosMsg, Decimal, Uint128, -// }; -// use speculoos::prelude::*; - -// use crate::testing::*; - -// // fn get_balance>(deps: Deps, addr: U) -> Uint128 { -// // query_balance(deps, addr.into()).unwrap().balance -// // } - -// // fn setup_test(deps: DepsMut, decimals: u8, reserve_decimals: u8, curve_type: CurveType) { -// // // this matches `linear_curve` test case from curves.rs -// // let creator = String::from(CREATOR); -// // let msg = default_instantiate(decimals, reserve_decimals, curve_type); -// // let info = mock_info(&creator, &[]); - -// // // make sure we can instantiate with this -// // let res = instantiate(deps, mock_env(), info, msg).unwrap(); -// // assert_eq!(0, res.messages.len()); -// // } - -// /// Mock token factory querier dependencies - -// // #[test] -// // fn proper_instantiation() -> CwAbcResult<()> { -// // let mut deps = mock_tf_dependencies(); - -// // // this matches `linear_curve` test case from curves.rs -// // let creator = String::from("creator"); -// // let curve_type = CurveType::SquareRoot { -// // slope: Uint128::new(1), -// // scale: 1, -// // }; -// // let msg = default_instantiate_msg(2, 8, curve_type.clone()); -// // let info = mock_info(&creator, &[]); - -// // // make sure we can instantiate with this -// // let res = instantiate(deps.as_mut(), mock_env(), info, msg)?; -// // assert_that!(res.messages.len()).is_equal_to(1); -// // let submsg = res.messages.get(0).unwrap(); -// // assert_that!(submsg.msg).is_equal_to(CosmosMsg::Custom(TokenFactoryMsg::Token( -// // TokenMsg::CreateDenom { -// // subdenom: TEST_SUPPLY_DENOM.to_string(), -// // metadata: Some(default_supply_metadata()), -// // }, -// // ))); - -// // // TODO! -// // // // token info is proper -// // // let token = query_token_info(deps.as_ref()).unwrap(); -// // // assert_that!(&token.name, &msg.name); -// // // assert_that!(&token.symbol, &msg.symbol); -// // // assert_that!(token.decimals, 2); -// // // assert_that!(token.total_supply, Uint128::zero()); - -// // // curve state is sensible -// // let state = query_curve_info(deps.as_ref(), curve_type.to_curve_fn())?; -// // assert_that!(state.reserve).is_equal_to(Uint128::zero()); -// // assert_that!(state.supply).is_equal_to(Uint128::zero()); -// // assert_that!(state.reserve_denom.as_str()).is_equal_to(TEST_RESERVE_DENOM); -// // // spot price 0 as supply is 0 -// // assert_that!(state.spot_price).is_equal_to(Decimal::zero()); - -// // // curve type is stored properly -// // let curve = CURVE_TYPE.load(&deps.storage).unwrap(); -// // assert_eq!(curve_type, curve); - -// // // no balance -// // // assert_eq!(get_balance(deps.as_ref(), &creator), Uint128::zero()); - -// // Ok(()) -// // } - -// // #[test] -// // fn buy_issues_tokens() { -// // let mut deps = mock_dependencies(); -// // let curve_type = CurveType::Linear { -// // slope: Uint128::new(1), -// // scale: 1, -// // }; -// // setup_test(deps.as_mut(), 2, 8, curve_type.clone()); - -// // // succeeds with proper token (5 BTC = 5*10^8 satoshi) -// // let info = mock_info(INVESTOR, &coins(500_000_000, DENOM)); -// // let buy = ExecuteMsg::Buy {}; -// // execute(deps.as_mut(), mock_env(), info, buy.clone()).unwrap(); - -// // // bob got 1000 EPOXY (10.00) -// // assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(1000)); -// // assert_eq!(get_balance(deps.as_ref(), BUYER), Uint128::zero()); - -// // // send them all to buyer -// // let info = mock_info(INVESTOR, &[]); -// // let send = ExecuteMsg::Transfer { -// // recipient: BUYER.into(), -// // amount: Uint128::new(1000), -// // }; -// // execute(deps.as_mut(), mock_env(), info, send).unwrap(); - -// // // ensure balances updated -// // assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::zero()); -// // assert_eq!(get_balance(deps.as_ref(), BUYER), Uint128::new(1000)); - -// // // second stake needs more to get next 1000 EPOXY -// // let info = mock_info(INVESTOR, &coins(1_500_000_000, DENOM)); -// // execute(deps.as_mut(), mock_env(), info, buy).unwrap(); - -// // // ensure balances updated -// // assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(1000)); -// // assert_eq!(get_balance(deps.as_ref(), BUYER), Uint128::new(1000)); - -// // // check curve info updated -// // let curve = query_curve_info(deps.as_ref(), curve_type.to_curve_fn()).unwrap(); -// // assert_eq!(curve.reserve, Uint128::new(2_000_000_000)); -// // assert_eq!(curve.supply, Uint128::new(2000)); -// // assert_eq!(curve.spot_price, Decimal::percent(200)); - -// // // check token info updated -// // let token = query_token_info(deps.as_ref()).unwrap(); -// // assert_eq!(token.decimals, 2); -// // assert_eq!(token.total_supply, Uint128::new(2000)); -// // } - -// // #[test] -// // fn bonding_fails_with_wrong_denom() { -// // let mut deps = mock_dependencies(); -// // let curve_type = CurveType::Linear { -// // slope: Uint128::new(1), -// // scale: 1, -// // }; -// // setup_test(deps.as_mut(), 2, 8, curve_type); - -// // // fails when no tokens sent -// // let info = mock_info(INVESTOR, &[]); -// // let buy = ExecuteMsg::Buy {}; -// // let err = execute(deps.as_mut(), mock_env(), info, buy.clone()).unwrap_err(); -// // assert_eq!(err, PaymentError::NoFunds {}.into()); - -// // // fails when wrong tokens sent -// // let info = mock_info(INVESTOR, &coins(1234567, "wei")); -// // let err = execute(deps.as_mut(), mock_env(), info, buy.clone()).unwrap_err(); -// // assert_eq!(err, PaymentError::MissingDenom(DENOM.into()).into()); - -// // // fails when too many tokens sent -// // let info = mock_info(INVESTOR, &[coin(3400022, DENOM), coin(1234567, "wei")]); -// // let err = execute(deps.as_mut(), mock_env(), info, buy).unwrap_err(); -// // assert_eq!(err, PaymentError::MultipleDenoms {}.into()); -// // } - -// // #[test] -// // fn burning_sends_reserve() { -// // let mut deps = mock_dependencies(); -// // let curve_type = CurveType::Linear { -// // slope: Uint128::new(1), -// // scale: 1, -// // }; -// // setup_test(deps.as_mut(), 2, 8, curve_type.clone()); - -// // // succeeds with proper token (20 BTC = 20*10^8 satoshi) -// // let info = mock_info(INVESTOR, &coins(2_000_000_000, DENOM)); -// // let buy = ExecuteMsg::Buy {}; -// // execute(deps.as_mut(), mock_env(), info, buy).unwrap(); - -// // // bob got 2000 EPOXY (20.00) -// // assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(2000)); - -// // // cannot burn too much -// // let info = mock_info(INVESTOR, &[]); -// // let burn = ExecuteMsg::Burn { -// // amount: Uint128::new(3000), -// // }; -// // let err = execute(deps.as_mut(), mock_env(), info, burn).unwrap_err(); -// // // TODO check error - -// // // burn 1000 EPOXY to get back 15BTC (*10^8) -// // let info = mock_info(INVESTOR, &[]); -// // let burn = ExecuteMsg::Burn { -// // amount: Uint128::new(1000), -// // }; -// // let res = execute(deps.as_mut(), mock_env(), info, burn).unwrap(); - -// // // balance is lower -// // assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(1000)); - -// // // ensure we got our money back -// // assert_eq!(1, res.messages.len()); -// // assert_eq!( -// // &res.messages[0], -// // &SubMsg::new(BankMsg::Send { -// // to_address: INVESTOR.into(), -// // amount: coins(1_500_000_000, DENOM), -// // }) -// // ); - -// // // check curve info updated -// // let curve = query_curve_info(deps.as_ref(), curve_type.to_curve_fn()).unwrap(); -// // assert_eq!(curve.reserve, Uint128::new(500_000_000)); -// // assert_eq!(curve.supply, Uint128::new(1000)); -// // assert_eq!(curve.spot_price, Decimal::percent(100)); - -// // // check token info updated -// // let token = query_token_info(deps.as_ref()).unwrap(); -// // assert_eq!(token.decimals, 2); -// // assert_eq!(token.total_supply, Uint128::new(1000)); -// // } -// } diff --git a/contracts/external/cw-abc/src/testing.rs b/contracts/external/cw-abc/src/testing.rs index 3a54efc7e..8efad0961 100644 --- a/contracts/external/cw-abc/src/testing.rs +++ b/contracts/external/cw-abc/src/testing.rs @@ -1,18 +1,24 @@ -use crate::abc::{ - ClosedConfig, CommonsPhaseConfig, CurveType, HatchConfig, MinMax, OpenConfig, ReserveToken, - SupplyToken, -}; -use crate::msg::InstantiateMsg; use cosmwasm_std::{ testing::{mock_env, mock_info, MockApi, MockQuerier, MockStorage}, - Decimal, OwnedDeps, Uint128, + CosmosMsg, Decimal, DepsMut, OwnedDeps, Uint128, }; +use speculoos::prelude::*; +use std::marker::PhantomData; +use token_bindings::{Metadata, TokenFactoryMsg, TokenFactoryQuery}; -use crate::contract; use crate::contract::CwAbcResult; -use cosmwasm_std::DepsMut; -use std::marker::PhantomData; -use token_bindings::{Metadata, TokenFactoryQuery}; +use crate::msg::InstantiateMsg; +use crate::queries::query_curve_info; +use crate::{ + abc::{ + ClosedConfig, CommonsPhaseConfig, CurveType, HatchConfig, MinMax, OpenConfig, ReserveToken, + SupplyToken, + }, + contract::instantiate, +}; +use crate::{contract, state::CURVE_TYPE}; + +const CREATOR: &str = "creator"; pub(crate) mod prelude { pub use super::{ @@ -93,3 +99,202 @@ pub fn mock_tf_dependencies( custom_query_type: PhantomData::, } } + +// fn setup_test( +// deps: DepsMut, +// decimals: u8, +// reserve_decimals: u8, +// curve_type: CurveType, +// ) { +// // this matches `linear_curve` test case from curves.rs +// let creator = String::from(CREATOR); +// let msg = default_instantiate_msg(decimals, reserve_decimals, curve_type); +// let info = mock_info(&creator, &[]); + +// // make sure we can instantiate with this +// let res = instantiate(deps, mock_env(), info, msg).unwrap(); +// assert_eq!(0, res.messages.len()); +// } + +// Mock token factory querier dependencies +#[test] +fn proper_instantiation() -> CwAbcResult<()> { + let mut deps = mock_tf_dependencies(); + + // this matches `linear_curve` test case from curves.rs + let creator = String::from("creator"); + let curve_type = CurveType::SquareRoot { + slope: Uint128::new(1), + scale: 1, + }; + let msg = default_instantiate_msg(2, 8, curve_type.clone()); + let info = mock_info(&creator, &[]); + + // make sure we can instantiate with this + let res = instantiate(deps.as_mut(), mock_env(), info, msg)?; + assert_that!(res.messages.len()).is_equal_to(1); + let submsg = res.messages.get(0).unwrap(); + assert_that!(submsg.msg).is_equal_to(CosmosMsg::Custom(WasmMsg::Execute { + contract_addr: (), + msg: (), + funds: (), + })); + + // TODO! + // // token info is proper + // let token = query_token_info(deps.as_ref()).unwrap(); + // assert_that!(&token.name, &msg.name); + // assert_that!(&token.symbol, &msg.symbol); + // assert_that!(token.decimals, 2); + // assert_that!(token.total_supply, Uint128::zero()); + + // curve state is sensible + let state = query_curve_info(deps.as_ref(), curve_type.to_curve_fn())?; + assert_that!(state.reserve).is_equal_to(Uint128::zero()); + assert_that!(state.supply).is_equal_to(Uint128::zero()); + assert_that!(state.reserve_denom.as_str()).is_equal_to(TEST_RESERVE_DENOM); + // spot price 0 as supply is 0 + assert_that!(state.spot_price).is_equal_to(Decimal::zero()); + + // curve type is stored properly + let curve = CURVE_TYPE.load(&deps.storage).unwrap(); + assert_eq!(curve_type, curve); + + // no balance + // assert_eq!(get_balance(deps.as_ref(), &creator), Uint128::zero()); + + Ok(()) +} + +// #[test] +// fn buy_issues_tokens() { +// let mut deps = mock_dependencies(); +// let curve_type = CurveType::Linear { +// slope: Uint128::new(1), +// scale: 1, +// }; +// setup_test(deps.as_mut(), 2, 8, curve_type.clone()); + +// // succeeds with proper token (5 BTC = 5*10^8 satoshi) +// let info = mock_info(INVESTOR, &coins(500_000_000, DENOM)); +// let buy = ExecuteMsg::Buy {}; +// execute(deps.as_mut(), mock_env(), info, buy.clone()).unwrap(); + +// // bob got 1000 EPOXY (10.00) +// assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(1000)); +// assert_eq!(get_balance(deps.as_ref(), BUYER), Uint128::zero()); + +// // send them all to buyer +// let info = mock_info(INVESTOR, &[]); +// let send = ExecuteMsg::Transfer { +// recipient: BUYER.into(), +// amount: Uint128::new(1000), +// }; +// execute(deps.as_mut(), mock_env(), info, send).unwrap(); + +// // ensure balances updated +// assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::zero()); +// assert_eq!(get_balance(deps.as_ref(), BUYER), Uint128::new(1000)); + +// // second stake needs more to get next 1000 EPOXY +// let info = mock_info(INVESTOR, &coins(1_500_000_000, DENOM)); +// execute(deps.as_mut(), mock_env(), info, buy).unwrap(); + +// // ensure balances updated +// assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(1000)); +// assert_eq!(get_balance(deps.as_ref(), BUYER), Uint128::new(1000)); + +// // check curve info updated +// let curve = query_curve_info(deps.as_ref(), curve_type.to_curve_fn()).unwrap(); +// assert_eq!(curve.reserve, Uint128::new(2_000_000_000)); +// assert_eq!(curve.supply, Uint128::new(2000)); +// assert_eq!(curve.spot_price, Decimal::percent(200)); + +// // check token info updated +// let token = query_token_info(deps.as_ref()).unwrap(); +// assert_eq!(token.decimals, 2); +// assert_eq!(token.total_supply, Uint128::new(2000)); +// } + +// #[test] +// fn bonding_fails_with_wrong_denom() { +// let mut deps = mock_dependencies(); +// let curve_type = CurveType::Linear { +// slope: Uint128::new(1), +// scale: 1, +// }; +// setup_test(deps.as_mut(), 2, 8, curve_type); + +// // fails when no tokens sent +// let info = mock_info(INVESTOR, &[]); +// let buy = ExecuteMsg::Buy {}; +// let err = execute(deps.as_mut(), mock_env(), info, buy.clone()).unwrap_err(); +// assert_eq!(err, PaymentError::NoFunds {}.into()); + +// // fails when wrong tokens sent +// let info = mock_info(INVESTOR, &coins(1234567, "wei")); +// let err = execute(deps.as_mut(), mock_env(), info, buy.clone()).unwrap_err(); +// assert_eq!(err, PaymentError::MissingDenom(DENOM.into()).into()); + +// // fails when too many tokens sent +// let info = mock_info(INVESTOR, &[coin(3400022, DENOM), coin(1234567, "wei")]); +// let err = execute(deps.as_mut(), mock_env(), info, buy).unwrap_err(); +// assert_eq!(err, PaymentError::MultipleDenoms {}.into()); +// } + +// #[test] +// fn burning_sends_reserve() { +// let mut deps = mock_dependencies(); +// let curve_type = CurveType::Linear { +// slope: Uint128::new(1), +// scale: 1, +// }; +// setup_test(deps.as_mut(), 2, 8, curve_type.clone()); + +// // succeeds with proper token (20 BTC = 20*10^8 satoshi) +// let info = mock_info(INVESTOR, &coins(2_000_000_000, DENOM)); +// let buy = ExecuteMsg::Buy {}; +// execute(deps.as_mut(), mock_env(), info, buy).unwrap(); + +// // bob got 2000 EPOXY (20.00) +// assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(2000)); + +// // cannot burn too much +// let info = mock_info(INVESTOR, &[]); +// let burn = ExecuteMsg::Burn { +// amount: Uint128::new(3000), +// }; +// let err = execute(deps.as_mut(), mock_env(), info, burn).unwrap_err(); +// // TODO check error + +// // burn 1000 EPOXY to get back 15BTC (*10^8) +// let info = mock_info(INVESTOR, &[]); +// let burn = ExecuteMsg::Burn { +// amount: Uint128::new(1000), +// }; +// let res = execute(deps.as_mut(), mock_env(), info, burn).unwrap(); + +// // balance is lower +// assert_eq!(get_balance(deps.as_ref(), INVESTOR), Uint128::new(1000)); + +// // ensure we got our money back +// assert_eq!(1, res.messages.len()); +// assert_eq!( +// &res.messages[0], +// &SubMsg::new(BankMsg::Send { +// to_address: INVESTOR.into(), +// amount: coins(1_500_000_000, DENOM), +// }) +// ); + +// // check curve info updated +// let curve = query_curve_info(deps.as_ref(), curve_type.to_curve_fn()).unwrap(); +// assert_eq!(curve.reserve, Uint128::new(500_000_000)); +// assert_eq!(curve.supply, Uint128::new(1000)); +// assert_eq!(curve.spot_price, Decimal::percent(100)); + +// // check token info updated +// let token = query_token_info(deps.as_ref()).unwrap(); +// assert_eq!(token.decimals, 2); +// assert_eq!(token.total_supply, Uint128::new(1000)); +// }