Skip to content

Commit

Permalink
Merge pull request #12 from oraichain/feat/pool-status
Browse files Browse the repository at this point in the history
feat: add pool status
  • Loading branch information
trung2891 authored Oct 23, 2024
2 parents 9017c39 + 7e081f4 commit d65b165
Show file tree
Hide file tree
Showing 11 changed files with 815 additions and 8 deletions.
3 changes: 3 additions & 0 deletions contracts/oraiswap-v3/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ pub fn execute(
start_timestamp,
reward_per_sec,
),
ExecuteMsg::UpdatePoolStatus { pool_key, status } => {
update_pool_status(deps, info, pool_key, status)
}
}
}

Expand Down
47 changes: 46 additions & 1 deletion contracts/oraiswap-v3/src/entrypoints/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use oraiswap_v3_common::math::sqrt_price::SqrtPrice;
use oraiswap_v3_common::math::token_amount::TokenAmount;
use oraiswap_v3_common::math::{calculate_min_amount_out, check_tick};
use oraiswap_v3_common::storage::incentive::IncentiveRecord;
use oraiswap_v3_common::storage::{FeeTier, Pool, PoolKey, Position};
use oraiswap_v3_common::storage::{FeeTier, Pool, PoolKey, PoolStatus, Position};

use super::{
check_can_send, create_tick, remove_tick_and_flip_bitmap, swap_internal, swap_route_internal,
Expand Down Expand Up @@ -284,6 +284,11 @@ pub fn create_position(
let pool_key_db = pool_key.key();
let mut pool = POOLS.load(deps.storage, &pool_key_db)?;

// check pool is opening for lp
if !pool.can_lp() {
return Err(ContractError::PoolPaused {});
}

// update global incentives
pool.update_global_incentives(env.block.time.seconds())?;

Expand Down Expand Up @@ -386,6 +391,10 @@ pub fn swap(
) -> Result<Response, ContractError> {
// update incentives first
let mut pool = state::get_pool(deps.storage, &pool_key)?;
// check pool is opening for swap
if !pool.can_swap() {
return Err(ContractError::PoolPaused {});
}
pool.update_global_incentives(env.block.time.seconds())?;
POOLS.save(deps.storage, &pool_key.key(), &pool)?;

Expand Down Expand Up @@ -464,6 +473,10 @@ pub fn swap_route(
// update incentives first
for hop in &swaps {
let mut pool = state::get_pool(deps.storage, &hop.pool_key)?;
// check pool is opening for swap
if !pool.can_swap() {
return Err(ContractError::PoolPaused {});
}
pool.update_global_incentives(env.block.time.seconds())?;
POOLS.save(deps.storage, &hop.pool_key.key(), &pool)?;
}
Expand Down Expand Up @@ -697,6 +710,10 @@ pub fn remove_position(

let pool_key_db = position.pool_key.key();
let mut pool = POOLS.load(deps.storage, &pool_key_db)?;
// check pool is opening for lp
if !pool.can_lp() {
return Err(ContractError::PoolPaused {});
}

// update global incentives first
pool.update_global_incentives(env.block.time.seconds())?;
Expand Down Expand Up @@ -1254,3 +1271,31 @@ pub fn update_incentive(
),
]))
}

// only owner can execute
pub fn update_pool_status(
deps: DepsMut,
info: MessageInfo,
pool_key: PoolKey,
status: Option<PoolStatus>,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
if info.sender != config.admin {
return Err(ContractError::Unauthorized {});
}

let pool_key_db = pool_key.key();
let mut pool = POOLS.load(deps.storage, &pool_key_db)?;
pool.status = status.clone();

POOLS.save(deps.storage, &pool_key_db, &pool)?;

Ok(Response::new().add_attributes(vec![
("action", "update_pool_status"),
("pool", &pool_key.to_string()),
(
"pool_status",
&format!("{:?}", &status.unwrap_or(PoolStatus::Opening)),
),
]))
}
22 changes: 21 additions & 1 deletion contracts/oraiswap-v3/src/tests/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ use oraiswap_v3_common::math::percentage::Percentage;
use oraiswap_v3_common::math::sqrt_price::SqrtPrice;
use oraiswap_v3_common::math::token_amount::TokenAmount;
use oraiswap_v3_common::oraiswap_v3_msg;
use oraiswap_v3_common::storage::{FeeTier, LiquidityTick, Pool, PoolKey, Position, Tick};
use oraiswap_v3_common::storage::{
FeeTier, LiquidityTick, Pool, PoolKey, PoolStatus, Position, Tick,
};

use crate::state::MAX_LIMIT;

Expand Down Expand Up @@ -548,6 +550,24 @@ impl MockApp {

Ok(tickmaps.into_iter().map(|(k, v)| (k, v.u64())).collect())
}

pub fn update_pool_status(
&mut self,
sender: &str,
dex: &str,
pool_key: &PoolKey,
status: Option<PoolStatus>,
) -> MockResult<ExecuteResponse> {
self.execute(
Addr::unchecked(sender),
Addr::unchecked(dex),
&oraiswap_v3_msg::ExecuteMsg::UpdatePoolStatus {
pool_key: pool_key.clone(),
status,
},
&[],
)
}
}

pub fn extract_amount(events: &[Event], key: &str) -> Option<TokenAmount> {
Expand Down
1 change: 1 addition & 0 deletions contracts/oraiswap-v3/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod max_tick_cross;
// mod migration;
mod multiple_swap;
mod nft;
mod pool_status;
mod position;
mod position_list;
mod position_slippage;
Expand Down
80 changes: 80 additions & 0 deletions contracts/oraiswap-v3/src/tests/pool_status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use cosmwasm_std::coins;
use decimal::*;

use crate::tests::helper::{macros::*, MockApp};
use oraiswap_v3_common::{
error::ContractError,
math::{percentage::Percentage, sqrt_price::calculate_sqrt_price},
storage::{FeeTier, PoolKey, PoolStatus},
};

use super::helper::FEE_DENOM;

#[test]
fn test_update_pool_status() {
let (mut app, accounts) = MockApp::new(&[
("alice", &coins(100_000_000_000, FEE_DENOM)),
("bob", &coins(100_000_000_000, FEE_DENOM)),
]);
let alice = &accounts[0];
let bob = &accounts[1];

let dex = create_dex!(app, Percentage::new(0), alice);
let (token_x, token_y) = create_tokens!(app, 500, 500, alice);

let fee_tier = FeeTier::new(Percentage::new(0), 1).unwrap();

add_fee_tier!(app, dex, fee_tier, alice).unwrap();

let init_tick = 0;
let init_sqrt_price = calculate_sqrt_price(init_tick).unwrap();
create_pool!(
app,
dex,
token_x,
token_y,
fee_tier,
init_sqrt_price,
init_tick,
alice
)
.unwrap();
let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier).unwrap();

// after create, poolStatus = none
let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap();
assert_eq!(pool.status, None);

// only admin can update pool status
let error = app
.update_pool_status(&bob, dex.as_str(), &pool_key, None)
.unwrap_err();
assert!(error
.root_cause()
.to_string()
.contains(&ContractError::Unauthorized {}.to_string()));

// update pool status to opening
app.update_pool_status(&alice, dex.as_str(), &pool_key, Some(PoolStatus::Opening))
.unwrap();
let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap();
assert_eq!(pool.status, Some(PoolStatus::Opening));

// update pool status to paused
app.update_pool_status(&alice, dex.as_str(), &pool_key, Some(PoolStatus::Paused))
.unwrap();
let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap();
assert_eq!(pool.status, Some(PoolStatus::Paused));

// update pool status to LpOnly
app.update_pool_status(&alice, dex.as_str(), &pool_key, Some(PoolStatus::LpOnly))
.unwrap();
let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap();
assert_eq!(pool.status, Some(PoolStatus::LpOnly));

// update pool status to SwapOnly
app.update_pool_status(&alice, dex.as_str(), &pool_key, Some(PoolStatus::SwapOnly))
.unwrap();
let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap();
assert_eq!(pool.status, Some(PoolStatus::SwapOnly));
}
Loading

0 comments on commit d65b165

Please sign in to comment.