Skip to content

Commit

Permalink
two party holder op mode (#298)
Browse files Browse the repository at this point in the history
  • Loading branch information
bekauz authored Jul 4, 2024
1 parent f3631e6 commit 47388d9
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 117 deletions.
41 changes: 21 additions & 20 deletions contracts/two-party-pol-covenant/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,15 @@ pub fn instantiate(
msg.contract_codes.liquid_pooler_code,
)?;

let mut clock_whitelist: Vec<String> = Vec::with_capacity(6);
clock_whitelist.push(holder_instantiate2_config.addr.to_string());

let mut clock_initial_queue = vec![];
clock_initial_queue.push(liquid_pooler_instantiate2_config.addr.to_string());
clock_initial_queue.push(party_a_router_instantiate2_config.addr.to_string());
clock_initial_queue.push(party_b_router_instantiate2_config.addr.to_string());
let mut clock_initial_queue = vec![
liquid_pooler_instantiate2_config.addr.to_string(),
party_a_router_instantiate2_config.addr.to_string(),
party_b_router_instantiate2_config.addr.to_string(),
holder_instantiate2_config.addr.to_string(),
];

let holder_instantiate2_msg = valence_two_party_pol_holder::msg::InstantiateMsg {
clock_address: clock_instantiate2_config.addr.to_string(),
op_mode_cfg: op_mode_cfg.clone(),
lockup_config: msg.lockup_config,
next_contract: liquid_pooler_instantiate2_config.addr.to_string(),
ragequit_config: msg.ragequit_config.unwrap_or(RagequitConfig::Disabled),
Expand Down Expand Up @@ -247,18 +246,20 @@ pub fn instantiate(
);
}

let clock_instantiate2_msg = valence_clock::msg::InstantiateMsg {
tick_max_gas: msg.clock_tick_max_gas,
whitelist: clock_whitelist,
initial_queue: clock_initial_queue,
}
.to_instantiate2_msg(
clock_instantiate2_config.code,
clock_instantiate2_config.salt,
env.contract.address.to_string(),
format!("{}-clock", msg.label),
)?;
messages.insert(0, clock_instantiate2_msg);
messages.insert(
0,
valence_clock::msg::InstantiateMsg {
tick_max_gas: msg.clock_tick_max_gas,
whitelist: vec![],
initial_queue: clock_initial_queue,
}
.to_instantiate2_msg(
clock_instantiate2_config.code,
clock_instantiate2_config.salt,
env.contract.address.to_string(),
format!("{}-clock", msg.label),
)?,
);

CONTRACT_CODES.save(
deps.storage,
Expand Down
80 changes: 43 additions & 37 deletions contracts/two-party-pol-holder/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ use std::collections::BTreeMap;

use cosmwasm_std::{
ensure, to_json_binary, BankMsg, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env,
MessageInfo, Response, StdError, StdResult,
MessageInfo, Reply, Response, StdError, StdResult, SubMsg,
};

#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;

use covenant_utils::clock::{enqueue_msg, verify_clock};
use covenant_utils::op_mode::{verify_caller, ContractOperationMode};
use covenant_utils::split::SplitConfig;
use covenant_utils::withdraw_lp_helper::{generate_withdraw_msg, EMERGENCY_COMMITTEE_ADDR};
use cw2::set_contract_version;

use crate::msg::CovenantType;
use crate::state::{WithdrawState, LIQUID_POOLER_ADDRESS, WITHDRAW_STATE};
use crate::state::{WithdrawState, CONTRACT_OP_MODE, LIQUID_POOLER_ADDRESS, WITHDRAW_STATE};
use crate::{
error::ContractError,
msg::{
ContractState, DenomSplits, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg,
RagequitConfig, RagequitState, TwoPartyPolCovenantConfig, TwoPartyPolCovenantParty,
},
state::{
CLOCK_ADDRESS, CONTRACT_STATE, COVENANT_CONFIG, DENOM_SPLITS, DEPOSIT_DEADLINE,
LOCKUP_CONFIG, RAGEQUIT_CONFIG,
CONTRACT_STATE, COVENANT_CONFIG, DENOM_SPLITS, DEPOSIT_DEADLINE, LOCKUP_CONFIG,
RAGEQUIT_CONFIG,
},
};

Expand All @@ -41,7 +41,7 @@ pub fn instantiate(
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

let next_contract = deps.api.addr_validate(&msg.next_contract)?;
let clock_addr = deps.api.addr_validate(&msg.clock_address)?;
let op_mode = ContractOperationMode::try_init(deps.api, msg.op_mode_cfg.clone())?;

// ensure that the deposit deadline is in the future
ensure!(
Expand Down Expand Up @@ -103,15 +103,14 @@ pub fn instantiate(
},
)?;
LIQUID_POOLER_ADDRESS.save(deps.storage, &next_contract)?;
CLOCK_ADDRESS.save(deps.storage, &clock_addr)?;
CONTRACT_OP_MODE.save(deps.storage, &op_mode)?;
LOCKUP_CONFIG.save(deps.storage, &msg.lockup_config)?;
RAGEQUIT_CONFIG.save(deps.storage, &msg.ragequit_config)?;
CONTRACT_STATE.save(deps.storage, &ContractState::Instantiated)?;
COVENANT_CONFIG.save(deps.storage, &msg.covenant_config)?;
DEPOSIT_DEADLINE.save(deps.storage, &msg.deposit_deadline)?;

Ok(Response::default()
.add_message(enqueue_msg(clock_addr.as_str())?)
.add_attribute("method", "two_party_pol_holder_instantiate")
.add_attributes(msg.get_response_attributes()))
}
Expand Down Expand Up @@ -195,13 +194,12 @@ fn try_claim(deps: DepsMut, info: MessageInfo) -> Result<Response, ContractError

// if both parties already claimed everything we complete early
if claim_party.allocation.is_zero() && counterparty.allocation.is_zero() {
let clock_address = CLOCK_ADDRESS.load(deps.storage)?;
let dequeue_message = ContractState::complete_and_dequeue(deps, clock_address.as_str())?;
let dequeue_messages = ContractState::complete_and_get_dequeue_msgs(deps)?;

return Ok(Response::default()
.add_attribute("method", "try_claim")
.add_attribute("contract_state", "complete")
.add_message(dequeue_message));
.add_submessages(dequeue_messages));
}

// set WithdrawState to include original data
Expand Down Expand Up @@ -341,20 +339,18 @@ fn try_claim_share_based(
mut covenant_config: TwoPartyPolCovenantConfig,
denom_splits: DenomSplits,
) -> Result<Response, ContractError> {
let mut messages = denom_splits
let messages = denom_splits
.get_single_receiver_distribution_messages(funds, claim_party.router.to_string());
let mut submsgs: Vec<SubMsg> = vec![];

claim_party.allocation = Decimal::zero();

// if other party had not claimed yet, we assign it the full position
if !counterparty.allocation.is_zero() {
counterparty.allocation = Decimal::one();
} else {
// otherwise both parties claimed everything and we can complete
let clock_address = CLOCK_ADDRESS.load(deps.storage)?;
let dequeue_message =
ContractState::complete_and_dequeue(deps.branch(), clock_address.as_str())?;
messages.push(dequeue_message.into());
let dequeue_msgs = ContractState::complete_and_get_dequeue_msgs(deps.branch())?;
submsgs.extend(dequeue_msgs);
};

covenant_config.update_parties(claim_party, counterparty);
Expand All @@ -363,7 +359,8 @@ fn try_claim_share_based(

Ok(Response::default()
.add_attribute("method", "claim_share_based")
.add_messages(messages))
.add_messages(messages)
.add_submessages(submsgs))
}

#[allow(clippy::too_many_arguments)]
Expand All @@ -381,23 +378,21 @@ fn try_claim_side_based(
counterparty.allocation = Decimal::zero();
covenant_config.update_parties(claim_party, counterparty);

// update the states and dequeue from the clock
// update the states and dequeue from any clocks
COVENANT_CONFIG.save(deps.storage, &covenant_config)?;
let clock_address = CLOCK_ADDRESS.load(deps.storage)?;
let dequeue_message = ContractState::complete_and_dequeue(deps, clock_address.as_str())?;
let dequeue_messages = ContractState::complete_and_get_dequeue_msgs(deps)?;

Ok(Response::default()
.add_attribute("method", "claim_side_based")
.add_messages(messages)
.add_message(dequeue_message))
.add_submessages(dequeue_messages))
}

/// attempts to route any available covenant party contribution denoms to
/// the parties that were responsible for contributing that denom.
fn try_refund(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
// Verify caller is the clock
verify_clock(&info.sender, &CLOCK_ADDRESS.load(deps.storage)?)
.map_err(|e| StdError::generic_err(e.to_string()))?;
// Verify caller is an authorized address
verify_caller(&info.sender, &CONTRACT_OP_MODE.load(deps.storage)?)?;

let config = COVENANT_CONFIG.load(deps.storage)?;
let contract_addr = env.contract.address.to_string();
Expand Down Expand Up @@ -434,9 +429,8 @@ fn try_refund(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, Co
}

fn try_deposit(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
// Verify caller is the clock
verify_clock(&info.sender, &CLOCK_ADDRESS.load(deps.storage)?)
.map_err(|e| StdError::generic_err(e.to_string()))?;
// Verify caller is an authorized address
verify_caller(&info.sender, &CONTRACT_OP_MODE.load(deps.storage)?)?;

let deposit_deadline = DEPOSIT_DEADLINE.load(deps.storage)?;
if deposit_deadline.is_expired(&env.block) {
Expand Down Expand Up @@ -481,9 +475,8 @@ fn try_deposit(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, C
}

fn check_expiration(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
// Verify caller is the clock
verify_clock(&info.sender, &CLOCK_ADDRESS.load(deps.storage)?)
.map_err(|e| StdError::generic_err(e.to_string()))?;
// Verify caller is an authorized address
verify_caller(&info.sender, &CONTRACT_OP_MODE.load(deps.storage)?)?;

let lockup_config = LOCKUP_CONFIG.load(deps.storage)?;

Expand Down Expand Up @@ -593,7 +586,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
QueryMsg::ContractState {} => Ok(to_json_binary(&CONTRACT_STATE.load(deps.storage)?)?),
QueryMsg::RagequitConfig {} => Ok(to_json_binary(&RAGEQUIT_CONFIG.load(deps.storage)?)?),
QueryMsg::LockupConfig {} => Ok(to_json_binary(&LOCKUP_CONFIG.load(deps.storage)?)?),
QueryMsg::ClockAddress {} => Ok(to_json_binary(&CLOCK_ADDRESS.load(deps.storage)?)?),
QueryMsg::OperationMode {} => Ok(to_json_binary(&CONTRACT_OP_MODE.load(deps.storage)?)?),
QueryMsg::NextContract {} => {
Ok(to_json_binary(&LIQUID_POOLER_ADDRESS.load(deps.storage)?)?)
}
Expand All @@ -617,7 +610,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> StdResult<Response> {
match msg {
MigrateMsg::UpdateConfig {
clock_addr,
op_mode,
next_contract,
lockup_config,
deposit_deadline,
Expand All @@ -629,10 +622,12 @@ pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> StdResult<Response>
} => {
let mut resp = Response::default().add_attribute("method", "update_config");

if let Some(addr) = clock_addr {
let clock_address = deps.api.addr_validate(&addr)?;
CLOCK_ADDRESS.save(deps.storage, &clock_address)?;
resp = resp.add_attribute("clock_addr", addr);
if let Some(op_mode_cfg) = op_mode {
let updated_op_mode = ContractOperationMode::try_init(deps.api, op_mode_cfg)
.map_err(|err| StdError::generic_err(err.to_string()))?;

CONTRACT_OP_MODE.save(deps.storage, &updated_op_mode)?;
resp = resp.add_attribute("op_mode", format!("{:?}", updated_op_mode));
}

if let Some(addr) = next_contract {
Expand Down Expand Up @@ -703,3 +698,14 @@ pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> StdResult<Response>
}
}
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> Result<Response, ContractError> {
// if we get a reply with id u64::MAX, we can assume it is a dequeue message
if msg.id == u64::MAX {
// Do nothing, whether it fails or not (dequeue messages are "fire & forget" style messages)
Ok(Response::default())
} else {
Err(ContractError::UnexpectedReplyId {})
}
}
7 changes: 7 additions & 0 deletions contracts/two-party-pol-holder/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use cosmwasm_std::StdError;
use covenant_utils::op_mode::ContractOperationError;
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),

#[error(transparent)]
ContractOperationError(#[from] ContractOperationError),

#[error("party allocations must add up to 1.0")]
AllocationValidationError {},

Expand All @@ -24,6 +28,9 @@ pub enum ContractError {
#[error("covenant is not in active state")]
NotActive {},

#[error("unexpected reply id")]
UnexpectedReplyId {},

#[error("covenant is active but expired; tick to proceed")]
Expired {},

Expand Down
Loading

0 comments on commit 47388d9

Please sign in to comment.