-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Single party pol v2 #146
Single party pol v2 #146
Changes from 20 commits
8392a5c
9a6de7b
fb7ae90
77a3abf
420effb
8378771
bc72622
c2ef5ab
351c8ea
cf7b77e
ead3eda
006d7cc
0f4977e
9536181
46eb6b0
41c1067
75324ad
d0411d5
c6f2a85
838fd3d
1ad473c
78b225e
f030ee4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,20 @@ | ||
#[cfg(not(feature = "library"))] | ||
use cosmwasm_std::entry_point; | ||
use cosmwasm_std::{ | ||
to_json_binary, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, MessageInfo, | ||
ensure, to_json_binary, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, MessageInfo, | ||
QuerierWrapper, Reply, Response, StdError, StdResult, SubMsg, Uint128, WasmMsg, | ||
}; | ||
use covenant_clock::helpers::{enqueue_msg, verify_clock}; | ||
use covenant_utils::{query_astro_pool_token, withdraw_lp_helper::WithdrawLPMsgs}; | ||
use cw2::set_contract_version; | ||
|
||
use astroport::{ | ||
asset::{Asset, PairInfo}, | ||
factory::PairType, | ||
pair::{ExecuteMsg::ProvideLiquidity, PoolResponse}, | ||
pair::{Cw20HookMsg, ExecuteMsg::ProvideLiquidity, PoolResponse}, | ||
DecimalCheckedOps, | ||
}; | ||
use cw20::Cw20ExecuteMsg; | ||
use cw_utils::parse_reply_instantiate_data; | ||
|
||
use crate::{ | ||
|
@@ -94,9 +96,80 @@ pub fn execute( | |
) -> Result<Response, ContractError> { | ||
match msg { | ||
ExecuteMsg::Tick {} => try_tick(deps, env, info), | ||
ExecuteMsg::Withdraw { percentage } => try_withdraw(deps, env, info, percentage), | ||
} | ||
} | ||
|
||
fn try_withdraw( | ||
deps: DepsMut, | ||
env: Env, | ||
info: MessageInfo, | ||
percent: Option<Decimal>, | ||
) -> Result<Response, ContractError> { | ||
let percent = percent.unwrap_or(Decimal::one()); | ||
// Verify percentage is < 1 and > 0 | ||
let holder_addr = HOLDER_ADDRESS | ||
.load(deps.storage) | ||
.map_err(|_| ContractError::MissingHolderError {})?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can skip this map err as in the instantiation we already do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are probably right, this error should never be reached in practice. |
||
|
||
ensure!(info.sender == holder_addr, ContractError::NotHolder {}); | ||
|
||
// Query LP position of the LPer | ||
let lp_config = LP_CONFIG.load(deps.storage)?; | ||
let lp_token_info = query_astro_pool_token( | ||
deps.querier, | ||
lp_config.pool_address.to_string(), | ||
env.contract.address.to_string(), | ||
)?; | ||
|
||
// If percentage is 100%, use the whole balance | ||
// If percentage is less than 100%, calculate the percentage of share we want to withdraw | ||
let withdraw_shares_amount = if percent == Decimal::one() { | ||
lp_token_info.balance_response.balance | ||
} else { | ||
Decimal::from_atomics(lp_token_info.balance_response.balance, 0)? | ||
.checked_mul(percent)? | ||
.to_uint_floor() | ||
}; | ||
|
||
// Clculate the withdrawn amount of A and B tokens from the shares we have | ||
let withdrawn_coins = deps | ||
.querier | ||
.query_wasm_smart::<Vec<Asset>>( | ||
lp_config.pool_address.to_string(), | ||
&astroport::pair::QueryMsg::Share { | ||
amount: withdraw_shares_amount, | ||
}, | ||
)? | ||
.iter() | ||
.map(|asset| asset.to_coin()) | ||
.collect::<Result<Vec<Coin>, _>>()?; | ||
|
||
// exit pool and withdraw funds with the shares calculated | ||
let withdraw_liquidity_hook = &Cw20HookMsg::WithdrawLiquidity { assets: vec![] }; | ||
let withdraw_msg = WasmMsg::Execute { | ||
contract_addr: lp_token_info.pair_info.liquidity_token.to_string(), | ||
msg: to_json_binary(&Cw20ExecuteMsg::Send { | ||
contract: lp_config.pool_address.to_string(), | ||
amount: withdraw_shares_amount, | ||
msg: to_json_binary(withdraw_liquidity_hook)?, | ||
})?, | ||
funds: vec![], | ||
}; | ||
|
||
// send message to holder that we finished with the withdrawal | ||
// with the funds we withdrew from the pool | ||
let to_holder_msg = WasmMsg::Execute { | ||
contract_addr: holder_addr.to_string(), | ||
msg: to_json_binary(&WithdrawLPMsgs::Distribute {})?, | ||
funds: withdrawn_coins, | ||
}; | ||
|
||
Ok(Response::default() | ||
.add_message(withdraw_msg) | ||
.add_message(to_holder_msg)) | ||
} | ||
|
||
/// attempts to advance the state machine. performs `info.sender` validation. | ||
fn try_tick(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> { | ||
// Verify caller is the clock | ||
|
@@ -165,7 +238,7 @@ fn try_lp(mut deps: DepsMut, env: Env) -> Result<Response, ContractError> { | |
// exactly one balance is non-zero, we attempt single-side | ||
(true, false) | (false, true) => { | ||
let single_sided_submsg = | ||
try_get_single_side_lp_submsg(deps.branch(), coin_a, coin_b, lp_config)?; | ||
try_get_single_side_lp_submsg(deps.branch(), env, (coin_a, coin_b), lp_config)?; | ||
if let Some(msg) = single_sided_submsg { | ||
return Ok(Response::default() | ||
.add_submessage(msg) | ||
|
@@ -176,11 +249,10 @@ fn try_lp(mut deps: DepsMut, env: Env) -> Result<Response, ContractError> { | |
(false, false) => { | ||
let double_sided_submsg = try_get_double_side_lp_submsg( | ||
deps.branch(), | ||
coin_a, | ||
coin_b, | ||
env, | ||
(coin_a, coin_b), | ||
a_to_b_ratio, | ||
pool_token_a_bal, | ||
pool_token_b_bal, | ||
(pool_token_a_bal, pool_token_b_bal), | ||
lp_config, | ||
)?; | ||
if let Some(msg) = double_sided_submsg { | ||
|
@@ -205,18 +277,12 @@ fn try_lp(mut deps: DepsMut, env: Env) -> Result<Response, ContractError> { | |
/// the existing pool ratio. | ||
fn try_get_double_side_lp_submsg( | ||
deps: DepsMut, | ||
token_a: Coin, | ||
token_b: Coin, | ||
env: Env, | ||
(token_a, token_b): (Coin, Coin), | ||
pool_token_ratio: Decimal, | ||
pool_token_a_bal: Uint128, | ||
pool_token_b_bal: Uint128, | ||
(pool_token_a_bal, pool_token_b_bal): (Uint128, Uint128), | ||
lp_config: LpConfig, | ||
) -> Result<Option<SubMsg>, ContractError> { | ||
let holder_address = match HOLDER_ADDRESS.may_load(deps.storage)? { | ||
Some(addr) => addr, | ||
None => return Err(ContractError::MissingHolderError {}), | ||
}; | ||
|
||
// we thus find the required token amount to enter into the position using all available b tokens: | ||
let required_token_a_amount = pool_token_ratio.checked_mul_uint128(token_b.amount)?; | ||
|
||
|
@@ -248,7 +314,7 @@ fn try_get_double_side_lp_submsg( | |
assets: vec![asset_a_double_sided, asset_b_double_sided], | ||
slippage_tolerance: lp_config.slippage_tolerance, | ||
auto_stake: Some(false), | ||
receiver: Some(holder_address.to_string()), | ||
receiver: Some(env.contract.address.to_string()), | ||
}; | ||
|
||
// update the provided amounts and leftover assets | ||
|
@@ -277,15 +343,10 @@ fn try_get_double_side_lp_submsg( | |
/// single-side liquidity limits, we provide it. | ||
fn try_get_single_side_lp_submsg( | ||
deps: DepsMut, | ||
coin_a: Coin, | ||
coin_b: Coin, | ||
env: Env, | ||
(coin_a, coin_b): (Coin, Coin), | ||
lp_config: LpConfig, | ||
) -> Result<Option<SubMsg>, ContractError> { | ||
let holder_address = match HOLDER_ADDRESS.may_load(deps.storage)? { | ||
Some(addr) => addr, | ||
None => return Err(ContractError::MissingHolderError {}), | ||
}; | ||
|
||
let assets = lp_config | ||
.asset_data | ||
.to_asset_vec(coin_a.amount, coin_b.amount); | ||
|
@@ -295,7 +356,7 @@ fn try_get_single_side_lp_submsg( | |
assets, | ||
slippage_tolerance: lp_config.slippage_tolerance, | ||
auto_stake: Some(false), | ||
receiver: Some(holder_address.to_string()), | ||
receiver: Some(env.contract.address.to_string()), | ||
}; | ||
|
||
// now we try to submit the message for either B or A token single side liquidity | ||
|
@@ -439,8 +500,7 @@ fn handle_double_sided_reply_id( | |
_env: Env, | ||
msg: Reply, | ||
) -> Result<Response, ContractError> { | ||
let parsed_data = parse_reply_instantiate_data(msg); | ||
match parsed_data { | ||
match parse_reply_instantiate_data(msg) { | ||
Ok(response) => Ok(Response::default() | ||
.add_attribute("method", "handle_double_sided_reply_id") | ||
.add_attribute( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment seems outdated/out of place