From 768885a830c2978a3e4785171d105321cd428690 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 17 Jul 2024 16:24:59 +0700 Subject: [PATCH 01/47] feat: incentives for position in range --- contracts/oraiswap-v3/src/contract.rs | 33 ++++ .../oraiswap-v3/src/entrypoints/execute.rs | 156 ++++++++++++++++++ contracts/oraiswap-v3/src/msg.rs | 22 ++- contracts/oraiswap-v3/src/state.rs | 3 + .../oraiswap-v3/src/storage/incentive.rs | 95 +++++++++++ contracts/oraiswap-v3/src/storage/mod.rs | 1 + contracts/oraiswap-v3/src/storage/pool.rs | 15 ++ contracts/oraiswap-v3/src/storage/position.rs | 102 +++++++++++- contracts/oraiswap-v3/src/storage/tick.rs | 44 ++++- 9 files changed, 467 insertions(+), 4 deletions(-) create mode 100644 contracts/oraiswap-v3/src/storage/incentive.rs diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index bf1ae82..8d58dd9 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -151,6 +151,39 @@ pub fn execute( extension.slippage_limit_lower, extension.slippage_limit_upper, ), + ExecuteMsg::CreateIncentive { + pool_key, + reward_token, + total_reward, + reward_per_sec, + start_timestamp, + } => create_incentive( + deps, + env, + info, + pool_key, + reward_token, + total_reward, + reward_per_sec, + start_timestamp, + ), + ExecuteMsg::ClaimIncentive { index } => claim_incentives(deps, env, info, index), + ExecuteMsg::UpdateIncentive { + pool_key, + incentive_id, + remaining_reward, + start_timestamp, + reward_per_sec, + } => update_incentive( + deps, + env, + info, + pool_key, + incentive_id, + remaining_reward, + start_timestamp, + reward_per_sec, + ), } } diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 63c6ca2..b702fd0 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -1,4 +1,6 @@ use crate::error::ContractError; +use crate::fee_growth::FeeGrowth; +use crate::incentive::IncentiveRecord; use crate::interface::{Asset, AssetInfo, CalculateSwapResult, Cw721ReceiveMsg, SwapHop}; use crate::liquidity::Liquidity; use crate::percentage::Percentage; @@ -181,6 +183,9 @@ pub fn create_position( let pool_key_db = pool_key.key(); let mut pool = POOLS.load(deps.storage, &pool_key_db)?; + // update global incentives + pool.update_global_incentives(env.block.time.seconds())?; + let mut lower_tick = match state::get_tick(deps.storage, &pool_key, lower_tick) { Ok(tick) => tick, _ => create_tick(deps.storage, current_timestamp, &pool_key, lower_tick)?, @@ -273,6 +278,11 @@ pub fn swap( by_amount_in: bool, sqrt_price_limit: SqrtPrice, ) -> Result { + // update incentives first + let mut pool = state::get_pool(deps.storage, &pool_key)?; + pool.update_global_incentives(env.block.time.seconds())?; + state::POOLS.save(deps.storage, &pool_key.key(), &pool)?; + let mut msgs = vec![]; let CalculateSwapResult { @@ -329,6 +339,13 @@ pub fn swap_route( slippage: Percentage, swaps: Vec, ) -> Result { + // update incentives first + for hop in &swaps { + let mut pool = state::get_pool(deps.storage, &hop.pool_key)?; + pool.update_global_incentives(env.block.time.seconds())?; + state::POOLS.save(deps.storage, &hop.pool_key.key(), &pool)?; + } + let mut msgs = vec![]; let amount_out = swap_route_internal( deps.storage, @@ -443,6 +460,44 @@ pub fn claim_fee( .add_attribute("amount_y", y.to_string())) } +/// Allows an authorized user (owner of the position) to claim incentives. +/// +/// # Parameters +/// - `index`: The index of the user position from which fees will be claimed. +/// +/// # Errors +/// - Fails if the position cannot be found. +pub fn claim_incentives( + deps: DepsMut, + env: Env, + info: MessageInfo, + index: u32, +) -> Result { + let mut position = state::get_position(deps.storage, &info.sender, index)?; + + let lower_tick = state::get_tick(deps.storage, &position.pool_key, position.lower_tick_index)?; + let upper_tick = state::get_tick(deps.storage, &position.pool_key, position.upper_tick_index)?; + let pool_key_db = position.pool_key.key(); + let mut pool = POOLS.load(deps.storage, &pool_key_db)?; + + // update global incentive + pool.update_global_incentives(env.block.time.seconds())?; + + let incentives = position.claim_incentives(&pool, &upper_tick, &lower_tick)?; + + state::update_position(deps.storage, &position)?; + POOLS.save(deps.storage, &pool_key_db, &pool)?; + + let mut msgs = vec![]; + for asset in incentives { + asset.transfer(&mut msgs, &info)?; + } + + Ok(Response::new() + .add_messages(msgs) + .add_attribute("action", "claim_incentives")) +} + /// Removes a position. Sends tokens associated with specified position to the owner. /// /// # Parameters @@ -471,6 +526,12 @@ pub fn remove_position( let pool_key_db = position.pool_key.key(); let mut pool = POOLS.load(deps.storage, &pool_key_db)?; + // update global incentives first + pool.update_global_incentives(env.block.time.seconds())?; + + // calculate pending incentives + let incentives = position.claim_incentives(&pool, &upper_tick, &lower_tick)?; + let (amount_x, amount_y, deinitialize_lower_tick, deinitialize_upper_tick) = position.remove( &mut pool, current_timestamp, @@ -502,6 +563,7 @@ pub fn remove_position( &upper_tick, )?; } + let position = state::remove_position(deps.storage, &info.sender, index)?; let asset_0 = Asset { @@ -517,6 +579,9 @@ pub fn remove_position( let mut msgs = vec![]; asset_0.transfer(&mut msgs, &info)?; asset_1.transfer(&mut msgs, &info)?; + for asset in incentives { + asset.transfer(&mut msgs, &info)?; + } let event_attributes = vec![ attr("action", "remove_position"), @@ -822,3 +887,94 @@ pub fn handle_mint( slippage_limit_upper, ) } + +// only owner can execute +pub fn create_incentive( + deps: DepsMut, + env: Env, + info: MessageInfo, + pool_key: PoolKey, + reward_token: AssetInfo, + total_reward: TokenAmount, + reward_per_sec: TokenAmount, + start_timestamp: Option, +) -> Result { + 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.update_global_incentives(env.block.time.seconds())?; + + let id = pool.incentives.len() as u64; + let incentive = IncentiveRecord { + id, + reward_per_sec, + reward_token: reward_token.clone(), + remaining: total_reward, + start_timestamp: start_timestamp.unwrap_or(env.block.time.seconds()), + liquidity: pool.liquidity, + incentive_growth_global: FeeGrowth(0), + last_updated: env.block.time.seconds(), + }; + pool.incentives.push(incentive); + + POOLS.save(deps.storage, &pool_key_db, &pool)?; + + Ok(Response::new().add_attributes(vec![ + ("action", "create_incentive"), + ("pool", &format!("{:?}", pool_key)), + ("reward_token", &format!("{:?}", reward_token)), + ("total_reward", &total_reward.to_string()), + ("reward_per_sec", &reward_per_sec.to_string()), + ( + "reward_per_sec", + &start_timestamp + .unwrap_or(env.block.time.seconds()) + .to_string(), + ), + ])) +} + +// only owner can execute +pub fn update_incentive( + deps: DepsMut, + env: Env, + info: MessageInfo, + pool_key: PoolKey, + record_id: u64, + remaining_reward: Option, + start_timestamp: Option, + reward_per_sec: Option, +) -> Result { + 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.update_global_incentives(env.block.time.seconds())?; + + if let Some(record) = pool.incentives.iter_mut().find(|i| i.id == record_id) { + if let Some(remaining_reward) = remaining_reward { + record.remaining = remaining_reward; + } + if let Some(start_timestamp) = start_timestamp { + record.start_timestamp = start_timestamp; + } + if let Some(reward_per_sec) = reward_per_sec { + record.reward_per_sec = reward_per_sec; + } + } + + POOLS.save(deps.storage, &pool_key_db, &pool)?; + + Ok(Response::new().add_attributes(vec![ + ("action", "update_incentive"), + ("pool", &format!("{:?}", pool_key)), + ("record_id", &record_id.to_string()), + ])) +} diff --git a/contracts/oraiswap-v3/src/msg.rs b/contracts/oraiswap-v3/src/msg.rs index a611c0a..553d11c 100644 --- a/contracts/oraiswap-v3/src/msg.rs +++ b/contracts/oraiswap-v3/src/msg.rs @@ -4,7 +4,7 @@ use cosmwasm_std::{Addr, Binary}; use cw20::Expiration; use crate::interface::{ - AllNftInfoResponse, ApprovedForAllResponse, NftInfoResponse, NumTokensResponse, + AllNftInfoResponse, ApprovedForAllResponse, AssetInfo, NftInfoResponse, NumTokensResponse, OwnerOfResponse, PoolWithPoolKey, PositionTick, QuoteResult, TokensResponse, }; #[allow(unused_imports)] @@ -130,6 +130,26 @@ pub enum ExecuteMsg { RevokeAll { operator: Addr, }, + // create incentives for specific pool + CreateIncentive { + pool_key: PoolKey, + reward_token: AssetInfo, + total_reward: TokenAmount, + reward_per_sec: TokenAmount, + start_timestamp: Option, + }, + // update for specific pool + UpdateIncentive { + pool_key: PoolKey, + incentive_id: u64, + remaining_reward: Option, + start_timestamp: Option, + reward_per_sec: Option, + }, + // Claim Incentives + ClaimIncentive { + index: u32, + }, } #[cw_serde] diff --git a/contracts/oraiswap-v3/src/state.rs b/contracts/oraiswap-v3/src/state.rs index 8109d0b..ce9fd9d 100644 --- a/contracts/oraiswap-v3/src/state.rs +++ b/contracts/oraiswap-v3/src/state.rs @@ -4,6 +4,7 @@ use cw_storage_plus::{Bound, Item, Map}; use crate::{ flip_bit_at_position, get_bit_at_position, get_search_limit, + incentive::IncentiveRecord, interface::PoolWithPoolKey, sqrt_price::{calculate_sqrt_price, SqrtPrice}, tick_to_position, Config, ContractError, Pool, PoolKey, Position, Tick, CHUNK_SIZE, MAX_TICK, @@ -29,6 +30,8 @@ pub const POSITION_KEYS_BY_TOKEN_ID: Map, u32)> = Map::new("positi pub const TOKEN_COUNT: Item = Item::new("num_tokens"); pub const OPERATORS: Map<(&[u8], &[u8]), Expiration> = Map::new("operators"); +pub const INCENTIVE_RECORD: Map = Map::new("incentive_record"); + pub const MAX_LIMIT: u32 = 100; pub fn num_tokens(storage: &dyn Storage) -> StdResult { diff --git a/contracts/oraiswap-v3/src/storage/incentive.rs b/contracts/oraiswap-v3/src/storage/incentive.rs new file mode 100644 index 0000000..635dc2d --- /dev/null +++ b/contracts/oraiswap-v3/src/storage/incentive.rs @@ -0,0 +1,95 @@ +use cosmwasm_schema::cw_serde; + +use crate::{ + fee_growth::FeeGrowth, interface::AssetInfo, liquidity::Liquidity, token_amount::TokenAmount, + ContractError, +}; + +#[cw_serde] +pub struct IncentiveRecord { + pub id: u64, + pub reward_per_sec: TokenAmount, + pub reward_token: AssetInfo, + pub remaining: TokenAmount, + pub start_timestamp: u64, + pub liquidity: Liquidity, + pub incentive_growth_global: FeeGrowth, + pub last_updated: u64, +} + +#[cw_serde] +#[derive(Eq, Copy, Default)] +pub struct TickIncentive { + pub incentive_id: u64, + pub incentive_growth_outside: FeeGrowth, +} + +#[cw_serde] +pub struct PositionIncentives { + pub incentive_id: u64, + pub pending_rewards: TokenAmount, + pub incentive_growth_inside: FeeGrowth, +} + +impl IncentiveRecord { + pub fn update_global_incentive_growth( + &mut self, + current_timestamp: u64, + ) -> Result<(), ContractError> { + if current_timestamp.lt(&self.start_timestamp) || current_timestamp.lt(&self.last_updated) { + return Ok(()); + } + + let pass_time = current_timestamp - self.last_updated; + + let mut total_emit = self.reward_per_sec * TokenAmount(pass_time.into()); + if total_emit > self.remaining { + total_emit = self.remaining; + }; + + let incentive_growth = FeeGrowth::from_fee(self.liquidity, total_emit); + match incentive_growth { + Ok(value) => self.incentive_growth_global += value, + Err(_) => { + // Do nothing if there is an error when converting the amount to FeeGrowth + } + } + self.last_updated = current_timestamp; + self.remaining = self.remaining - total_emit; + Ok(()) + } +} + +pub fn calculate_incentive_growth_inside( + tick_lower: i32, + tick_lower_incentive_growth_outside: FeeGrowth, + tick_upper: i32, + tick_upper_incentive_growth_outside: FeeGrowth, + tick_current: i32, + incentive_growth_global: FeeGrowth, +) -> FeeGrowth { + // determine position relative to current tick + let current_above_lower = tick_current >= tick_lower; + let current_below_upper = tick_current < tick_upper; + + // calculate fee growth below + let incentive_growth_below = if current_above_lower { + tick_lower_incentive_growth_outside + } else { + incentive_growth_global.unchecked_sub(tick_lower_incentive_growth_outside) + }; + + // calculate fee growth above + let incentive_growth_above = if current_below_upper { + tick_upper_incentive_growth_outside + } else { + incentive_growth_global.unchecked_sub(tick_upper_incentive_growth_outside) + }; + + // calculate fee growth inside + let incentive_growth_inside = incentive_growth_global + .unchecked_sub(incentive_growth_below) + .unchecked_sub(incentive_growth_above); + + incentive_growth_inside +} diff --git a/contracts/oraiswap-v3/src/storage/mod.rs b/contracts/oraiswap-v3/src/storage/mod.rs index 200c16c..f9b89bb 100644 --- a/contracts/oraiswap-v3/src/storage/mod.rs +++ b/contracts/oraiswap-v3/src/storage/mod.rs @@ -1,5 +1,6 @@ pub mod config; pub mod fee_tier; +pub mod incentive; pub mod pool; pub mod pool_key; pub mod position; diff --git a/contracts/oraiswap-v3/src/storage/pool.rs b/contracts/oraiswap-v3/src/storage/pool.rs index e44faa1..bee48e8 100644 --- a/contracts/oraiswap-v3/src/storage/pool.rs +++ b/contracts/oraiswap-v3/src/storage/pool.rs @@ -1,4 +1,5 @@ use super::{FeeTier, Tick}; +use crate::incentive::IncentiveRecord; use crate::math::types::sqrt_price::check_tick_to_sqrt_price_relationship; use crate::{ math::{ @@ -29,6 +30,9 @@ pub struct Pool { pub start_timestamp: u64, pub last_timestamp: u64, pub fee_receiver: String, + + #[serde(default)] + pub incentives: Vec, } #[derive(PartialEq, Eq, Debug, Clone)] @@ -185,6 +189,17 @@ impl Pool { (fee_protocol_token_x, fee_protocol_token_y) } + + pub fn update_global_incentives( + &mut self, + current_timestamp: u64, + ) -> Result<(), ContractError> { + for record in &mut self.incentives { + record.update_global_incentive_growth(current_timestamp)?; + } + + Ok(()) + } } #[cfg(test)] diff --git a/contracts/oraiswap-v3/src/storage/position.rs b/contracts/oraiswap-v3/src/storage/position.rs index 4c8f8a9..e3ba714 100644 --- a/contracts/oraiswap-v3/src/storage/position.rs +++ b/contracts/oraiswap-v3/src/storage/position.rs @@ -1,6 +1,7 @@ use super::{Pool, PoolKey, Tick}; use crate::{ - interface::Approval, + incentive::{calculate_incentive_growth_inside, PositionIncentives}, + interface::{Approval, Asset}, math::{ clamm::*, types::{ @@ -32,6 +33,8 @@ pub struct Position { pub approvals: Vec, #[serde(default)] pub token_id: u64, + #[serde(default)] + pub incentives: Vec, } impl Position { @@ -80,6 +83,61 @@ impl Position { pool.update_liquidity(liquidity_delta, add, upper_tick.index, lower_tick.index) } + pub fn update_incentives( + &mut self, + pool: &Pool, + upper_tick: &Tick, + lower_tick: &Tick, + ) -> Result<(), ContractError> { + // try update incentives + for record in &pool.incentives { + let tick_lower_incentive_growth_outside = lower_tick + .incentives + .iter() + .find(|i| i.incentive_id == record.id) + .map_or(FeeGrowth::new(0), |incentive| { + incentive.incentive_growth_outside + }); + + let tick_upper_incentive_growth_outside = upper_tick + .incentives + .iter() + .find(|i| i.incentive_id == record.id) + .map_or(FeeGrowth::new(0), |incentive| { + incentive.incentive_growth_outside + }); + + let incentive_growth_inside = calculate_incentive_growth_inside( + lower_tick.index, + tick_lower_incentive_growth_outside, + upper_tick.index, + tick_upper_incentive_growth_outside, + pool.current_tick_index, + record.incentive_growth_global, + ); + + if let Some(incentive) = self + .incentives + .iter_mut() + .find(|i| i.incentive_id == record.id) + { + incentive.pending_rewards += incentive_growth_inside + .unchecked_sub(incentive.incentive_growth_inside) + .to_fee(self.liquidity)?; + incentive.incentive_growth_inside = incentive_growth_inside; + } else { + let incentive = PositionIncentives { + incentive_id: record.id, + pending_rewards: incentive_growth_inside.to_fee(self.liquidity)?, + incentive_growth_inside, + }; + self.incentives.push(incentive); + } + } + + Ok(()) + } + pub fn update( &mut self, sign: bool, @@ -149,6 +207,34 @@ impl Position { Ok((tokens_owed_x, tokens_owed_y)) } + + pub fn claim_incentives( + &mut self, + pool: &Pool, + upper_tick: &Tick, + lower_tick: &Tick, + ) -> Result, ContractError> { + self.update_incentives(pool, upper_tick, lower_tick)?; + let mut incentives: Vec = vec![]; + + for incentive in &mut self.incentives { + if incentive.pending_rewards.gt(&TokenAmount::new(0)) { + if let Some(record) = pool + .incentives + .iter() + .find(|i| i.id == incentive.incentive_id) + { + incentives.push(Asset { + info: record.reward_token.clone(), + amount: incentive.pending_rewards.into(), + }); + incentive.pending_rewards = TokenAmount::new(0); + } + } + } + + Ok(incentives) + } #[allow(clippy::too_many_arguments)] pub fn create( pool: &mut Pool, @@ -166,6 +252,16 @@ impl Position { return Err(ContractError::PriceLimitReached); } + let incentives: Vec = pool + .incentives + .iter() + .map(|record| PositionIncentives { + incentive_id: record.id, + pending_rewards: TokenAmount::new(0), + incentive_growth_inside: FeeGrowth::new(0), + }) + .collect(); + // init position let mut position = Self { token_id: 0, @@ -179,8 +275,12 @@ impl Position { tokens_owed_x: TokenAmount::new(0), tokens_owed_y: TokenAmount::new(0), approvals: vec![], + incentives, }; + // try update incentives first + position.update_incentives(pool, upper_tick, lower_tick)?; + let (required_x, required_y) = position.modify( pool, upper_tick, diff --git a/contracts/oraiswap-v3/src/storage/tick.rs b/contracts/oraiswap-v3/src/storage/tick.rs index c8055b9..a3ca649 100644 --- a/contracts/oraiswap-v3/src/storage/tick.rs +++ b/contracts/oraiswap-v3/src/storage/tick.rs @@ -1,5 +1,6 @@ use super::Pool; use crate::{ + incentive::TickIncentive, math::types::{ fee_growth::FeeGrowth, liquidity::Liquidity, @@ -11,7 +12,7 @@ use cosmwasm_schema::cw_serde; use decimal::*; #[cw_serde] -#[derive(Eq, Copy, Default)] +#[derive(Eq, Default)] pub struct Tick { pub index: i32, pub sign: bool, @@ -21,6 +22,9 @@ pub struct Tick { pub fee_growth_outside_x: FeeGrowth, pub fee_growth_outside_y: FeeGrowth, pub seconds_outside: u64, + + #[serde(default)] + pub incentives: Vec, } pub const MAX_RESULT_SIZE: usize = 16 * 1024 * 8; @@ -60,6 +64,19 @@ impl Tick { pub fn create(index: i32, pool: &Pool, current_timestamp: u64) -> Self { let below_current_tick = index <= pool.current_tick_index; + // ensure update global incentive before + let incentives: Vec = pool + .incentives + .iter() + .map(|record| TickIncentive { + incentive_id: record.id, + incentive_growth_outside: match below_current_tick { + true => record.incentive_growth_global, + false => FeeGrowth::new(0), + }, + }) + .collect(); + Self { index, sign: true, @@ -76,6 +93,7 @@ impl Tick { true => current_timestamp - pool.start_timestamp, false => 0, }, + incentives, ..Self::default() } } @@ -95,6 +113,28 @@ impl Tick { pool.last_timestamp = current_timestamp; + // ensure update global incentive before + // Iterate through the pool incentives + for record in &pool.incentives { + // Check if the incentive ID exists in the existing set + if let Some(incentive) = self + .incentives + .iter_mut() + .find(|i| i.incentive_id == record.id) + { + // Update the incentive growth if it exists + incentive.incentive_growth_outside = record + .incentive_growth_global + .unchecked_sub(incentive.incentive_growth_outside); + } else { + // If the incentive ID doesn't exist, add a new incentive + self.incentives.push(TickIncentive { + incentive_id: record.id, + incentive_growth_outside: record.incentive_growth_global, + }); + } + } + // When going to higher tick net_liquidity should be added and for going lower subtracted if (pool.current_tick_index >= self.index) ^ self.sign { pool.liquidity = pool.liquidity.checked_add(self.liquidity_change)?; @@ -141,7 +181,7 @@ impl Tick { } fn calculate_new_liquidity_gross( - self, + &self, sign: bool, liquidity_delta: Liquidity, max_liquidity_per_tick: Liquidity, From a1933490a27d9b6db77a04c04a0f140472f04f9f Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 17 Jul 2024 16:42:47 +0700 Subject: [PATCH 02/47] chore: use liquidity from pool to update global incentive --- contracts/oraiswap-v3/src/storage/incentive.rs | 14 ++++++++++---- contracts/oraiswap-v3/src/storage/pool.rs | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/contracts/oraiswap-v3/src/storage/incentive.rs b/contracts/oraiswap-v3/src/storage/incentive.rs index 635dc2d..91bf6fb 100644 --- a/contracts/oraiswap-v3/src/storage/incentive.rs +++ b/contracts/oraiswap-v3/src/storage/incentive.rs @@ -12,7 +12,6 @@ pub struct IncentiveRecord { pub reward_token: AssetInfo, pub remaining: TokenAmount, pub start_timestamp: u64, - pub liquidity: Liquidity, pub incentive_growth_global: FeeGrowth, pub last_updated: u64, } @@ -34,6 +33,7 @@ pub struct PositionIncentives { impl IncentiveRecord { pub fn update_global_incentive_growth( &mut self, + pool_liquidity: Liquidity, current_timestamp: u64, ) -> Result<(), ContractError> { if current_timestamp.lt(&self.start_timestamp) || current_timestamp.lt(&self.last_updated) { @@ -47,15 +47,21 @@ impl IncentiveRecord { total_emit = self.remaining; }; - let incentive_growth = FeeGrowth::from_fee(self.liquidity, total_emit); + let incentive_growth = FeeGrowth::from_fee(pool_liquidity, total_emit); match incentive_growth { - Ok(value) => self.incentive_growth_global += value, + Ok(value) => { + self.incentive_growth_global += value; + self.remaining = self.remaining - total_emit; + } Err(_) => { // Do nothing if there is an error when converting the amount to FeeGrowth + // Potential errors in calculating incentive growth: + // - overflow + // - liquidity is zero } } self.last_updated = current_timestamp; - self.remaining = self.remaining - total_emit; + Ok(()) } } diff --git a/contracts/oraiswap-v3/src/storage/pool.rs b/contracts/oraiswap-v3/src/storage/pool.rs index bee48e8..ff32080 100644 --- a/contracts/oraiswap-v3/src/storage/pool.rs +++ b/contracts/oraiswap-v3/src/storage/pool.rs @@ -195,7 +195,7 @@ impl Pool { current_timestamp: u64, ) -> Result<(), ContractError> { for record in &mut self.incentives { - record.update_global_incentive_growth(current_timestamp)?; + record.update_global_incentive_growth(self.liquidity, current_timestamp)?; } Ok(()) From 62268a0f8d9cf251ec31035b758258ca5030d6a4 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 17 Jul 2024 16:44:28 +0700 Subject: [PATCH 03/47] fix: init incentive_record error --- contracts/oraiswap-v3/src/entrypoints/execute.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index b702fd0..bdaa933 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -281,7 +281,7 @@ pub fn swap( // update incentives first let mut pool = state::get_pool(deps.storage, &pool_key)?; pool.update_global_incentives(env.block.time.seconds())?; - state::POOLS.save(deps.storage, &pool_key.key(), &pool)?; + POOLS.save(deps.storage, &pool_key.key(), &pool)?; let mut msgs = vec![]; @@ -343,7 +343,7 @@ pub fn swap_route( for hop in &swaps { let mut pool = state::get_pool(deps.storage, &hop.pool_key)?; pool.update_global_incentives(env.block.time.seconds())?; - state::POOLS.save(deps.storage, &hop.pool_key.key(), &pool)?; + POOLS.save(deps.storage, &hop.pool_key.key(), &pool)?; } let mut msgs = vec![]; @@ -915,7 +915,6 @@ pub fn create_incentive( reward_token: reward_token.clone(), remaining: total_reward, start_timestamp: start_timestamp.unwrap_or(env.block.time.seconds()), - liquidity: pool.liquidity, incentive_growth_global: FeeGrowth(0), last_updated: env.block.time.seconds(), }; From 4948e97a2a5e8c428b96230498d28c6cedc4ae46 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 17 Jul 2024 16:55:10 +0700 Subject: [PATCH 04/47] chore: add test for calculate_incentive_growth_inside func --- .../oraiswap-v3/src/storage/incentive.rs | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/contracts/oraiswap-v3/src/storage/incentive.rs b/contracts/oraiswap-v3/src/storage/incentive.rs index 91bf6fb..8ec1c01 100644 --- a/contracts/oraiswap-v3/src/storage/incentive.rs +++ b/contracts/oraiswap-v3/src/storage/incentive.rs @@ -99,3 +99,195 @@ pub fn calculate_incentive_growth_inside( incentive_growth_inside } + +#[cfg(test)] +mod tests { + use decimal::*; + + use super::*; + + #[test] + fn test_calculate_incentive_growth_inside() { + // <────────────── ──────────────> + // incentive_outside_t0| incentive_growth_inside |incentive_outside_t1 + //<───────────── t0 ────── C ────── t1 ───────────────────> + + // incentive_growth_inside = incentive_growth_global - t0.incentive_outside - t1.incentive_outside + + let incentive_growth_global = FeeGrowth::from_integer(15); + + let tick_lower_index = -2; + let tick_lower_incentive_growth_outside = FeeGrowth::new(0); + + let tick_upper_index = 2; + let tick_upper_incentive_growth_outside = FeeGrowth::from_integer(0); + + // current tick inside range + // lower current upper + // | | | + // -2 0 2 + { + // index and fee global + let tick_current = 0; + let incentive_growth_inside = calculate_incentive_growth_inside( + tick_lower_index, + tick_lower_incentive_growth_outside, + tick_upper_index, + tick_upper_incentive_growth_outside, + tick_current, + incentive_growth_global, + ); + + assert_eq!(incentive_growth_inside, FeeGrowth::from_integer(15)); // x incentive growth inside + } + // ───────incentive_outside_t0──────────> + // |incentive_growth_inside| incentive_outside_t1 + // ─────── c ─────── t0 ──────────────> t1 ───────────> + // + // incentive_growth_inside = t0.incentive_outisde - t1.incentive_outside + // + // current tick below range + // current lower upper + // | | | + // -4 2 2 + { + let tick_current = -4; + let incentive_growth_inside = calculate_incentive_growth_inside( + tick_lower_index, + tick_lower_incentive_growth_outside, + tick_upper_index, + tick_upper_incentive_growth_outside, + tick_current, + incentive_growth_global, + ); + + assert_eq!(incentive_growth_inside, FeeGrowth::new(0)); // incentive growth inside + } + + // <──────────incentive_outside_t0────────── + // incentive_outside_t1 | incentive_growth_inside| + // ────────────── t1 ──────────────── t0 ─────── c ───────────> + + // incentive_growth_inside = t0.incentive_outisde - t1.incentive_outside + + // current tick upper range + // lower upper current + // | | | + // -2 2 4 + { + let tick_current = 4; + let incentive_growth_inside = calculate_incentive_growth_inside( + tick_lower_index, + tick_lower_incentive_growth_outside, + tick_upper_index, + tick_upper_incentive_growth_outside, + tick_current, + incentive_growth_global, + ); + + assert_eq!(incentive_growth_inside, FeeGrowth::new(0)); // incentive growth inside + } + + // current tick upper range + // lower upper current + // | | | + // -2 2 3 + { + let tick_lower_index = -2; + let tick_lower_incentive_growth_outside = FeeGrowth::new(0); + + let tick_upper_index = 2; + let tick_upper_incentive_growth_outside = FeeGrowth::new(1); + + let incentive_growth_global = FeeGrowth::from_integer(5); + + let tick_current = 3; + let incentive_growth_inside = calculate_incentive_growth_inside( + tick_lower_index, + tick_lower_incentive_growth_outside, + tick_upper_index, + tick_upper_incentive_growth_outside, + tick_current, + incentive_growth_global, + ); + + assert_eq!(incentive_growth_inside, FeeGrowth::new(1)); // incentive growth inside + } + + // subtracts upper tick if below + let tick_upper_index = 2; + let tick_upper_incentive_growth_outside = FeeGrowth::from_integer(2); + + // lower current upper + // | | | + // -2 0 2 + { + let tick_current = 0; + let incentive_growth_inside = calculate_incentive_growth_inside( + tick_lower_index, + tick_lower_incentive_growth_outside, + tick_upper_index, + tick_upper_incentive_growth_outside, + tick_current, + incentive_growth_global, + ); + + assert_eq!(incentive_growth_inside, FeeGrowth::from_integer(13)); // incentive growth inside + } + + // subtracts lower tick if above + let tick_upper_index = 2; + let tick_upper_incentive_growth_outside = FeeGrowth::new(0); + + let tick_lower_index = -2; + let tick_lower_incentive_growth_outside = FeeGrowth::from_integer(2); + + // current tick inside range + // lower current upper + // | | | + // -2 0 2 + { + let tick_current = 0; + let incentive_growth_inside = calculate_incentive_growth_inside( + tick_lower_index, + tick_lower_incentive_growth_outside, + tick_upper_index, + tick_upper_incentive_growth_outside, + tick_current, + incentive_growth_global, + ); + + assert_eq!(incentive_growth_inside, FeeGrowth::from_integer(13)); // incentive growth inside + } + } + + #[test] + fn test_domain_calculate_incentive_growth_inside() { + let tick_current = 0; + let incentive_growth_global = FeeGrowth::from_integer(20); + + let tick_lower_index = -20; + let tick_lower_incentive_growth_outside = FeeGrowth::from_integer(20); + + let tick_upper_index = -10; + let tick_upper_incentive_growth_outside = FeeGrowth::from_integer(15); + + let incentive_growth_inside = calculate_incentive_growth_inside( + tick_lower_index, + tick_lower_incentive_growth_outside, + tick_upper_index, + tick_upper_incentive_growth_outside, + tick_current, + incentive_growth_global, + ); + + assert_eq!( + incentive_growth_inside, + FeeGrowth::max_instance() - FeeGrowth::from_integer(5) + FeeGrowth::new(1) + ); + assert_eq!( + incentive_growth_inside, + FeeGrowth::max_instance() - FeeGrowth::from_integer(5) + FeeGrowth::new(1) + ); + } +} From 3ffec59271c71d7d4d02c8899cb6c0828f0cfbe1 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 17 Jul 2024 17:29:56 +0700 Subject: [PATCH 05/47] chore: add unit test for update_global_incentive_growth --- .../oraiswap-v3/src/storage/incentive.rs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/contracts/oraiswap-v3/src/storage/incentive.rs b/contracts/oraiswap-v3/src/storage/incentive.rs index 8ec1c01..8acaa55 100644 --- a/contracts/oraiswap-v3/src/storage/incentive.rs +++ b/contracts/oraiswap-v3/src/storage/incentive.rs @@ -106,6 +106,94 @@ mod tests { use super::*; + #[test] + fn test_update_global_incentive_growth() { + let mut record = IncentiveRecord { + id: 0, + reward_per_sec: TokenAmount(0), + reward_token: AssetInfo::NativeToken { + denom: "orai".to_string(), + }, + remaining: TokenAmount(1000000), + start_timestamp: 1000, + incentive_growth_global: FeeGrowth(0), + last_updated: 1000, + }; + let mut pool_liquidity = Liquidity::new(1000000); + + // case 1: CurrentTimestamp < start_timestamp => no update + record + .update_global_incentive_growth(pool_liquidity, 900) + .unwrap(); + assert_eq!(record.last_updated, 1000); + assert_eq!(record.incentive_growth_global, FeeGrowth(0)); + + // case 2: CurrentTimestamp < last_updated => no update + record.last_updated = 1100; + record + .update_global_incentive_growth(pool_liquidity, 1099) + .unwrap(); + assert_eq!(record.last_updated, 1100); + assert_eq!(record.incentive_growth_global, FeeGrowth(0)); + + // case 3: liquidity = 0 => still success, but don;t update incentive_growth_global + pool_liquidity = Liquidity::new(0); + record.reward_per_sec = TokenAmount(100); + record + .update_global_incentive_growth(pool_liquidity, 1200) + .unwrap(); + assert_eq!(record.last_updated, 1200); + assert_eq!(record.remaining, TokenAmount(1000000)); + assert_eq!(record.incentive_growth_global, FeeGrowth(0)); + + // case 4: overflow => still success, but don;t update incentive_growth_global + pool_liquidity = Liquidity::new(1); + record.reward_per_sec = TokenAmount(1000); + record + .update_global_incentive_growth(pool_liquidity, 1300) + .unwrap(); + assert_eq!(record.last_updated, 1300); + assert_eq!(record.remaining, TokenAmount(1000000)); + assert_eq!(record.incentive_growth_global, FeeGrowth(0)); + + // case 4: happy case + pool_liquidity = Liquidity::new(1000); + record.reward_per_sec = TokenAmount(100); + record + .update_global_incentive_growth(pool_liquidity, 1400) + .unwrap(); + assert_eq!(record.last_updated, 1400); + assert_eq!(record.remaining, TokenAmount(990000)); + assert_eq!( + record.incentive_growth_global, + FeeGrowth(100000000000000000000000000000000000) + ); + + // case 5: total emit > remaining reward + pool_liquidity = Liquidity::new(100000); + record.reward_per_sec = TokenAmount(10000); + record + .update_global_incentive_growth(pool_liquidity, 1500) + .unwrap(); + assert_eq!(record.last_updated, 1500); + assert_eq!(record.remaining, TokenAmount(0)); + assert_eq!( + record.incentive_growth_global, + FeeGrowth(199000000000000000000000000000000000) + ); + + // case 6: no reward remaining + record + .update_global_incentive_growth(pool_liquidity, 1600) + .unwrap(); + assert_eq!(record.last_updated, 1600); + assert_eq!(record.remaining, TokenAmount(0)); + assert_eq!( + record.incentive_growth_global, + FeeGrowth(199000000000000000000000000000000000) + ); + } + #[test] fn test_calculate_incentive_growth_inside() { // <────────────── ──────────────> From 52a2c26a3f659b1ffa5ae1d5cb8c99927921cc99 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 17 Jul 2024 18:14:42 +0700 Subject: [PATCH 06/47] chore: init test incentive --- contracts/oraiswap-v3/src/tests/helper.rs | 44 +++++++++++- contracts/oraiswap-v3/src/tests/incentive.rs | 73 ++++++++++++++++++++ contracts/oraiswap-v3/src/tests/mod.rs | 1 + contracts/oraiswap-v3/src/tests/swap.rs | 2 +- 4 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 contracts/oraiswap-v3/src/tests/incentive.rs diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index 8e32ad4..04c2041 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -11,8 +11,7 @@ use std::collections::HashMap; use cw_multi_test::{next_block, App, AppResponse, Contract, Executor}; use crate::{ - interface::SwapHop, - interface::{PoolWithPoolKey, QuoteResult}, + interface::{AssetInfo, PoolWithPoolKey, QuoteResult, SwapHop}, liquidity::Liquidity, msg::{self}, percentage::Percentage, @@ -34,7 +33,7 @@ macro_rules! create_entry_points_testing { } pub struct MockApp { - app: App, + pub app: App, token_map: HashMap, // map token name to address token_id: u64, dex_id: u64, @@ -670,6 +669,30 @@ impl MockApp { None => panic!("Must return generic error"), } } + + pub fn create_incentive( + &mut self, + sender: &str, + dex: &str, + pool_key: &PoolKey, + reward_token: AssetInfo, + total_reward: TokenAmount, + reward_per_sec: TokenAmount, + start_timestamp: Option, + ) -> Result { + self.execute( + Addr::unchecked(sender), + Addr::unchecked(dex), + &msg::ExecuteMsg::CreateIncentive { + pool_key: pool_key.clone(), + reward_token, + total_reward, + reward_per_sec, + start_timestamp, + }, + &[], + ) + } } pub fn extract_amount(events: &[Event], key: &str) -> Option { @@ -776,6 +799,21 @@ pub mod macros { } pub(crate) use fee_tier_exist; + macro_rules! create_incentive { + ($app:ident, $dex_address:expr, $pool_key:expr, $reward_token:expr, $total_reward:expr, $reward_per_sec:expr, $start_timestamp:expr, $caller:tt) => {{ + $app.create_incentive( + $caller, + $dex_address.as_str(), + &$pool_key, + $reward_token, + $total_reward, + $reward_per_sec, + $start_timestamp, + ) + }}; + } + pub(crate) use create_incentive; + macro_rules! create_position { ($app:ident, $dex_address:expr, $pool_key:expr, $lower_tick:expr, $upper_tick:expr, $liquidity_delta:expr, $slippage_limit_lower:expr, $slippage_limit_upper:expr, $caller:tt) => {{ $app.create_position( diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs new file mode 100644 index 0000000..85c7bfd --- /dev/null +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -0,0 +1,73 @@ +use decimal::*; + +use crate::{ + fee_growth::FeeGrowth, + incentive::IncentiveRecord, + interface::AssetInfo, + liquidity::Liquidity, + percentage::Percentage, + sqrt_price::{calculate_sqrt_price, SqrtPrice}, + tests::helper::{macros::*, MockApp}, + token_amount::TokenAmount, + FeeTier, PoolKey, MIN_SQRT_PRICE, +}; + +#[test] +pub fn test_create_incentive() { + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(app, 500, 500); + + let fee_tier = FeeTier::new(Percentage::new(0), 1).unwrap(); + + add_fee_tier!(app, dex, fee_tier, "alice").unwrap(); + + let init_tick = 10; + 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(); + + let reward_token = AssetInfo::NativeToken { + denom: "orai".to_string(), + }; + let total_reward = TokenAmount(1000000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + let current_time = app.app.block_info().time.seconds(); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!( + pool.incentives, + vec![IncentiveRecord { + id: 0, + reward_per_sec, + reward_token, + remaining: total_reward, + start_timestamp: current_time, + incentive_growth_global: FeeGrowth(0), + last_updated: current_time + }] + ); +} diff --git a/contracts/oraiswap-v3/src/tests/mod.rs b/contracts/oraiswap-v3/src/tests/mod.rs index d781a16..b8514a0 100644 --- a/contracts/oraiswap-v3/src/tests/mod.rs +++ b/contracts/oraiswap-v3/src/tests/mod.rs @@ -10,6 +10,7 @@ mod get_liquidity_ticks; mod get_position_ticks; mod get_tickmap; mod helper; +mod incentive; mod interaction_with_pool_on_removed_fee_tier; mod limits; mod liquidity_gap; diff --git a/contracts/oraiswap-v3/src/tests/swap.rs b/contracts/oraiswap-v3/src/tests/swap.rs index 35852da..902d63e 100644 --- a/contracts/oraiswap-v3/src/tests/swap.rs +++ b/contracts/oraiswap-v3/src/tests/swap.rs @@ -301,7 +301,7 @@ fn test_swap_y_to_x() { #[test] fn test_swap_not_enough_liquidity_token_x() { - let protocol_fee = Percentage::from_scale(6, 3); + let protocol_fee: Percentage = Percentage::from_scale(6, 3); let mut app = MockApp::new(&[]); let dex = create_dex!(app, protocol_fee); From 89ba18fac6b49d96adcb7420c05e3bc22cc0e366 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 17 Jul 2024 22:28:47 +0700 Subject: [PATCH 07/47] fix: test case create multi incentive --- contracts/oraiswap-v3/src/tests/incentive.rs | 40 +++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 85c7bfd..2baa9be 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -63,11 +63,49 @@ pub fn test_create_incentive() { vec![IncentiveRecord { id: 0, reward_per_sec, - reward_token, + reward_token: reward_token.clone(), remaining: total_reward, start_timestamp: current_time, incentive_growth_global: FeeGrowth(0), last_updated: current_time }] ); + + // create other incentives + let new_timestamp_time = app.app.block_info().time.seconds(); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!( + pool.incentives, + vec![ + IncentiveRecord { + id: 0, + reward_per_sec, + reward_token: reward_token.clone(), + remaining: total_reward, + start_timestamp: current_time, + incentive_growth_global: FeeGrowth(0), + last_updated: new_timestamp_time + }, + IncentiveRecord { + id: 1, + reward_per_sec, + reward_token: reward_token.clone(), + remaining: total_reward, + start_timestamp: new_timestamp_time, + incentive_growth_global: FeeGrowth(0), + last_updated: new_timestamp_time + } + ] + ); } From 78d873d1ee357031e3aabd876c07527a30b069ec Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 01:10:44 +0700 Subject: [PATCH 08/47] chore: add query_incentives & more test case --- contracts/oraiswap-v3/src/contract.rs | 3 + .../oraiswap-v3/src/entrypoints/query.rs | 31 +- contracts/oraiswap-v3/src/msg.rs | 7 +- contracts/oraiswap-v3/src/tests/helper.rs | 24 +- contracts/oraiswap-v3/src/tests/incentive.rs | 306 +++++++++++++++++- 5 files changed, 363 insertions(+), 8 deletions(-) diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index 8d58dd9..77c2434 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -301,6 +301,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { to_binary(&query_all_tokens(deps, start_after, limit)?) } QueryMsg::NumTokens {} => to_binary(&query_num_tokens(deps)?), + QueryMsg::PositionIncentives { owner_id, index } => { + to_binary(&query_position_incentives(deps, env, owner_id, index)?) + } } } diff --git a/contracts/oraiswap-v3/src/entrypoints/query.rs b/contracts/oraiswap-v3/src/entrypoints/query.rs index bdc865c..1efe054 100644 --- a/contracts/oraiswap-v3/src/entrypoints/query.rs +++ b/contracts/oraiswap-v3/src/entrypoints/query.rs @@ -4,8 +4,8 @@ use cw_storage_plus::Bound; use crate::{ get_max_chunk, get_min_chunk, interface::{ - AllNftInfoResponse, Approval, ApprovedForAllResponse, NftInfoResponse, NumTokensResponse, - OwnerOfResponse, PoolWithPoolKey, QuoteResult, SwapHop, TokensResponse, + AllNftInfoResponse, Approval, ApprovedForAllResponse, Asset, NftInfoResponse, + NumTokensResponse, OwnerOfResponse, PoolWithPoolKey, QuoteResult, SwapHop, TokensResponse, }, percentage::Percentage, sqrt_price::{get_max_tick, get_min_tick, SqrtPrice}, @@ -513,3 +513,30 @@ pub fn query_num_tokens(deps: Deps) -> Result let count = state::num_tokens(deps.storage)?; Ok(NumTokensResponse { count }) } + +/// Retrieves incentives information of a single position. +/// +/// # Parameters +/// - `owner_id`: An `Addr` identifying the user who owns the position. +/// - `index`: The index of the user position. +/// +/// # Errors +/// - Fails if position cannot be found +pub fn query_position_incentives( + deps: Deps, + env: Env, + owner_id: Addr, + index: u32, +) -> Result, ContractError> { + let mut position = state::get_position(deps.storage, &owner_id, index)?; + let mut pool = state::get_pool(deps.storage, &position.pool_key)?; + let lower_tick = state::get_tick(deps.storage, &position.pool_key, position.lower_tick_index)?; + let upper_tick = state::get_tick(deps.storage, &position.pool_key, position.upper_tick_index)?; + // update global incentive + pool.update_global_incentives(env.block.time.seconds())?; + position.update_incentives(&pool, &upper_tick, &lower_tick)?; + + let incentives = position.claim_incentives(&pool, &upper_tick, &lower_tick)?; + + Ok(incentives) +} diff --git a/contracts/oraiswap-v3/src/msg.rs b/contracts/oraiswap-v3/src/msg.rs index 553d11c..82e170b 100644 --- a/contracts/oraiswap-v3/src/msg.rs +++ b/contracts/oraiswap-v3/src/msg.rs @@ -4,8 +4,8 @@ use cosmwasm_std::{Addr, Binary}; use cw20::Expiration; use crate::interface::{ - AllNftInfoResponse, ApprovedForAllResponse, AssetInfo, NftInfoResponse, NumTokensResponse, - OwnerOfResponse, PoolWithPoolKey, PositionTick, QuoteResult, TokensResponse, + AllNftInfoResponse, ApprovedForAllResponse, Asset, AssetInfo, NftInfoResponse, + NumTokensResponse, OwnerOfResponse, PoolWithPoolKey, PositionTick, QuoteResult, TokensResponse, }; #[allow(unused_imports)] use crate::{ @@ -301,4 +301,7 @@ pub enum QueryMsg { start_after: Option, limit: Option, }, + + #[returns(Vec)] + PositionIncentives { owner_id: Addr, index: u32 }, } diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index 04c2041..15b3dda 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -11,7 +11,7 @@ use std::collections::HashMap; use cw_multi_test::{next_block, App, AppResponse, Contract, Executor}; use crate::{ - interface::{AssetInfo, PoolWithPoolKey, QuoteResult, SwapHop}, + interface::{Asset, AssetInfo, PoolWithPoolKey, QuoteResult, SwapHop}, liquidity::Liquidity, msg::{self}, percentage::Percentage, @@ -619,6 +619,21 @@ impl MockApp { ) } + pub fn get_position_incentives( + &self, + dex: &str, + owner_id: &str, + index: u32, + ) -> StdResult> { + self.query( + Addr::unchecked(dex), + &msg::QueryMsg::PositionIncentives { + owner_id: Addr::unchecked(owner_id), + index, + }, + ) + } + pub fn get_all_positions(&self, dex: &str, owner_id: &str) -> StdResult> { self.query( Addr::unchecked(dex), @@ -856,6 +871,13 @@ pub mod macros { } pub(crate) use get_position; + macro_rules! get_position_incentives { + ($app:ident, $dex_address:expr, $index:expr, $owner:tt) => {{ + $app.get_position_incentives($dex_address.as_str(), $owner, $index) + }}; + } + pub(crate) use get_position_incentives; + macro_rules! get_tick { ($app:ident, $dex_address:expr, $key:expr, $index:expr) => {{ $app.get_tick($dex_address.as_str(), &$key, $index) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 2baa9be..37c13a9 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -1,15 +1,16 @@ +use cosmwasm_std::{Addr, Timestamp, Uint128}; use decimal::*; use crate::{ fee_growth::FeeGrowth, - incentive::IncentiveRecord, - interface::AssetInfo, + incentive::{IncentiveRecord, PositionIncentives}, + interface::{Asset, AssetInfo}, liquidity::Liquidity, percentage::Percentage, sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, MIN_SQRT_PRICE, + FeeTier, PoolKey, }; #[test] @@ -108,4 +109,303 @@ pub fn test_create_incentive() { } ] ); + + // create fail, unauthorized + let res = create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "bob" + ); + assert!(res.is_err()); +} + +#[test] +pub fn test_single_incentive_with_single_position() { + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(app, 500, 500); + + 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(); + + let reward_token = AssetInfo::NativeToken { + denom: "orai".to_string(), + }; + let total_reward = TokenAmount(1000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + // create position + approve!(app, token_x, dex, 5000, "alice").unwrap(); + approve!(app, token_y, dex, 5000, "alice").unwrap(); + + let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier).unwrap(); + + let block_info = app.app.block_info(); + create_position!( + app, + dex, + pool_key, + -10, + 10, + Liquidity::new(1000), + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // No incentive available after creating the position + let position_state = get_position!(app, dex, 0, "alice").unwrap(); + + assert_eq!( + position_state.incentives, + vec![PositionIncentives { + incentive_id: 0, + pending_rewards: TokenAmount(0), + incentive_growth_inside: FeeGrowth(0) + }] + ); + // set block_info to ensure after create position, block time not change + app.app.set_block(block_info); + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentives, vec![]); + + // try increase block time to 1000s + // => totalReward for position = 100 * 1000 = 100000; + let mut block_info = app.app.block_info(); + block_info.time = Timestamp::from_seconds(block_info.time.seconds() + 1000); + app.app.set_block(block_info); + + // get position + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentives, + vec![Asset { + info: reward_token.clone(), + amount: Uint128::from(100000u128) + }] + ); + + // reach limit of total reward + block_info = app.app.block_info(); + block_info.time = Timestamp::from_seconds(block_info.time.seconds() + 1000000); + app.app.set_block(block_info); + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentives, + vec![Asset { + info: reward_token.clone(), + amount: Uint128::from(1000000u128) + }] + ); +} + +#[test] +pub fn test_multi_incentives_with_single_position() { + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(app, 500, 500); + + 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(); + + let reward_token = AssetInfo::NativeToken { + denom: "orai".to_string(), + }; + let reward_token_2 = AssetInfo::Token { + contract_addr: Addr::unchecked("usdt"), + }; + let total_reward = TokenAmount(1000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + create_incentive!( + app, + dex, + pool_key, + reward_token_2.clone(), + TokenAmount(1000000000), + TokenAmount(200), + start_timestamp, + "alice" + ) + .unwrap(); + + // create position + approve!(app, token_x, dex, 5000, "alice").unwrap(); + approve!(app, token_y, dex, 5000, "alice").unwrap(); + + let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier).unwrap(); + + let block_info = app.app.block_info(); + create_position!( + app, + dex, + pool_key, + -10, + 10, + Liquidity::new(1000), + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // No incentive available after creating the position + let position_state = get_position!(app, dex, 0, "alice").unwrap(); + + assert_eq!( + position_state.incentives, + vec![ + PositionIncentives { + incentive_id: 0, + pending_rewards: TokenAmount(0), + incentive_growth_inside: FeeGrowth(0) + }, + PositionIncentives { + incentive_id: 1, + pending_rewards: TokenAmount(0), + incentive_growth_inside: FeeGrowth(0) + } + ] + ); + // set block_info to ensure after create position, block time not change + app.app.set_block(block_info); + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentives, vec![]); + + // try increase block time to 1000s + // => totalReward for position = 100 * 1000 = 100000; + let mut block_info = app.app.block_info(); + block_info.time = Timestamp::from_seconds(block_info.time.seconds() + 1000); + app.app.set_block(block_info); + + // get position + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentives, + vec![ + Asset { + info: reward_token.clone(), + amount: Uint128::from(100000u128) + }, + Asset { + info: reward_token_2.clone(), + amount: Uint128::from(200000u128) + } + ] + ); + + // Reached the limit of the total reward for the first incentive, + // and the calculation for the second incentive is impacted by overflow. + block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000000); + app.app.set_block(block_info.clone()); + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentives, + vec![Asset { + info: reward_token.clone(), + amount: Uint128::from(1000000u128) + }] + ); + + // success + block_info.time = Timestamp::from_seconds(current_timestamp + 20000); + app.app.set_block(block_info); + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentives, + vec![ + Asset { + info: reward_token.clone(), + amount: Uint128::from(1000000u128) + }, + Asset { + info: reward_token_2.clone(), + amount: Uint128::from(4200000u128) + } + ] + ); +} + +#[test] +pub fn test_multi_incentives_with_multi_positions() { + //TODO +} +#[test] +pub fn test_incentive_with_position_cross_out_of_range() { + // TODO +} + +#[test] +pub fn test_incentive_with_position_cross_in_range() { + // TODO +} + +#[test] +pub fn test_remove_position() { + // TODO } From 5baf857c1392e43e8d50e690410d8874a6cad661 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 10:25:16 +0700 Subject: [PATCH 09/47] chore: add test multi incentive with multi positions --- contracts/oraiswap-v3/src/tests/incentive.rs | 170 ++++++++++++++++++- 1 file changed, 169 insertions(+), 1 deletion(-) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 37c13a9..bcbe1ae 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -393,7 +393,175 @@ pub fn test_multi_incentives_with_single_position() { #[test] pub fn test_multi_incentives_with_multi_positions() { - //TODO + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(app, 500, 500); + + 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(); + + let reward_token = AssetInfo::NativeToken { + denom: "orai".to_string(), + }; + let reward_token_2 = AssetInfo::Token { + contract_addr: Addr::unchecked("usdt"), + }; + let total_reward = TokenAmount(1000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + create_incentive!( + app, + dex, + pool_key, + reward_token_2.clone(), + TokenAmount(1000000000), + TokenAmount(200), + start_timestamp, + "alice" + ) + .unwrap(); + + // create position + approve!(app, token_x, dex, 5000, "alice").unwrap(); + approve!(app, token_y, dex, 5000, "alice").unwrap(); + + let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier).unwrap(); + + let block_info = app.app.block_info(); + create_position!( + app, + dex, + pool_key, + -10, + 10, + Liquidity::new(1000), + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // No incentive available after creating the position + let position_state = get_position!(app, dex, 0, "alice").unwrap(); + + assert_eq!( + position_state.incentives, + vec![ + PositionIncentives { + incentive_id: 0, + pending_rewards: TokenAmount(0), + incentive_growth_inside: FeeGrowth(0) + }, + PositionIncentives { + incentive_id: 1, + pending_rewards: TokenAmount(0), + incentive_growth_inside: FeeGrowth(0) + } + ] + ); + // set block_info to ensure after create position, block time not change + app.app.set_block(block_info); + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentives, vec![]); + + // try increase block time to 1000s + // => totalReward for position = 100 * 1000 = 100000; + let mut block_info = app.app.block_info(); + block_info.time = Timestamp::from_seconds(block_info.time.seconds() + 1000); + app.app.set_block(block_info); + + // get position + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentives, + vec![ + Asset { + info: reward_token.clone(), + amount: Uint128::from(100000u128) + }, + Asset { + info: reward_token_2.clone(), + amount: Uint128::from(200000u128) + } + ] + ); + + // try create other position, with the same range, but double liquidity + create_position!( + app, + dex, + pool_key, + -10, + 10, + Liquidity::new(2000), + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // try increase 1000s + block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentives, + vec![ + Asset { + info: reward_token.clone(), + amount: Uint128::from(133500u128) + }, + Asset { + info: reward_token_2.clone(), + amount: Uint128::from(267000u128) + } + ] + ); + let incentives_2 = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!( + incentives_2, + vec![ + Asset { + info: reward_token.clone(), + amount: Uint128::from(67000u128) + }, + Asset { + info: reward_token_2.clone(), + amount: Uint128::from(134000u128) + } + ] + ); } #[test] pub fn test_incentive_with_position_cross_out_of_range() { From b9b0091a382979a4f55d63dcbf4b3ec653945583 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 10:33:17 +0700 Subject: [PATCH 10/47] chore: refactor --- contracts/oraiswap-v3/src/contract.rs | 46 +++++++++---------- .../oraiswap-v3/src/entrypoints/common.rs | 4 +- .../oraiswap-v3/src/entrypoints/execute.rs | 3 ++ .../oraiswap-v3/src/storage/incentive.rs | 8 ++-- 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index 77c2434..db5510b 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -312,30 +312,30 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result = crate::state::POSITIONS - .range_raw(deps.storage, None, None, cosmwasm_std::Order::Ascending) - .collect(); - let mut token_id = 0; - for item in positions { - if let Ok((key, mut position)) = item { - token_id += 1; - position.token_id = token_id; - let account_id = &key[..key.len() - 4]; - let index = u32::from_be_bytes(key[key.len() - 4..].try_into().unwrap()); - // update position and its index - crate::state::POSITIONS.save(deps.storage, &key, &position)?; - crate::state::POSITION_KEYS_BY_TOKEN_ID.save( - deps.storage, - position.token_id, - &(account_id.to_vec(), index), - )?; - } - } + // // query all position, then update token id + // let positions: Vec<_> = crate::state::POSITIONS + // .range_raw(deps.storage, None, None, cosmwasm_std::Order::Ascending) + // .collect(); + // let mut token_id = 0; + // for item in positions { + // if let Ok((key, mut position)) = item { + // token_id += 1; + // position.token_id = token_id; + // let account_id = &key[..key.len() - 4]; + // let index = u32::from_be_bytes(key[key.len() - 4..].try_into().unwrap()); + // // update position and its index + // crate::state::POSITIONS.save(deps.storage, &key, &position)?; + // crate::state::POSITION_KEYS_BY_TOKEN_ID.save( + // deps.storage, + // position.token_id, + // &(account_id.to_vec(), index), + // )?; + // } + // } - // update total token id, first time token count is total token ids - crate::state::TOKEN_COUNT.save(deps.storage, &token_id)?; - crate::state::TOKEN_ID.save(deps.storage, &token_id)?; + // // update total token id, first time token count is total token ids + // crate::state::TOKEN_COUNT.save(deps.storage, &token_id)?; + // crate::state::TOKEN_ID.save(deps.storage, &token_id)?; Ok(Response::new().add_attribute("new_version", original_version.to_string())) } diff --git a/contracts/oraiswap-v3/src/entrypoints/common.rs b/contracts/oraiswap-v3/src/entrypoints/common.rs index fe7dd17..efd8788 100644 --- a/contracts/oraiswap-v3/src/entrypoints/common.rs +++ b/contracts/oraiswap-v3/src/entrypoints/common.rs @@ -232,8 +232,8 @@ pub fn swap_internal( amount: calculate_swap_result.amount_out.into(), }; - asset_0.transfer_from(msgs, &info, contract_address.to_string())?; - asset_1.transfer(msgs, &info)?; + asset_0.transfer_from(msgs, info, contract_address.to_string())?; + asset_1.transfer(msgs, info)?; Ok(calculate_swap_result) } diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index bdaa933..5ee4809 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -863,6 +863,7 @@ pub fn handle_send_nft( ])) } +#[allow(clippy::too_many_arguments)] pub fn handle_mint( deps: DepsMut, env: Env, @@ -889,6 +890,7 @@ pub fn handle_mint( } // only owner can execute +#[allow(clippy::too_many_arguments)] pub fn create_incentive( deps: DepsMut, env: Env, @@ -938,6 +940,7 @@ pub fn create_incentive( } // only owner can execute +#[allow(clippy::too_many_arguments)] pub fn update_incentive( deps: DepsMut, env: Env, diff --git a/contracts/oraiswap-v3/src/storage/incentive.rs b/contracts/oraiswap-v3/src/storage/incentive.rs index 8acaa55..9d78457 100644 --- a/contracts/oraiswap-v3/src/storage/incentive.rs +++ b/contracts/oraiswap-v3/src/storage/incentive.rs @@ -51,7 +51,7 @@ impl IncentiveRecord { match incentive_growth { Ok(value) => { self.incentive_growth_global += value; - self.remaining = self.remaining - total_emit; + self.remaining -= total_emit; } Err(_) => { // Do nothing if there is an error when converting the amount to FeeGrowth @@ -93,11 +93,9 @@ pub fn calculate_incentive_growth_inside( }; // calculate fee growth inside - let incentive_growth_inside = incentive_growth_global + incentive_growth_global .unchecked_sub(incentive_growth_below) - .unchecked_sub(incentive_growth_above); - - incentive_growth_inside + .unchecked_sub(incentive_growth_above) } #[cfg(test)] From 5b0c41c32437a035a60e1e29523ab87b0d8cbb1c Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 10:36:41 +0700 Subject: [PATCH 11/47] chore: remove migration test --- contracts/oraiswap-v3/src/tests/migration.rs | 184 +++++++++---------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/contracts/oraiswap-v3/src/tests/migration.rs b/contracts/oraiswap-v3/src/tests/migration.rs index fa0d75e..7bbae61 100644 --- a/contracts/oraiswap-v3/src/tests/migration.rs +++ b/contracts/oraiswap-v3/src/tests/migration.rs @@ -1,107 +1,107 @@ -use cosmwasm_std::{ - testing::{mock_dependencies, mock_env, mock_info}, - Order, -}; -use decimal::Decimal; +// use cosmwasm_std::{ +// testing::{mock_dependencies, mock_env, mock_info}, +// Order, +// }; +// use decimal::Decimal; -use crate::{ - contract::{instantiate, migrate}, - entrypoints::{self}, - liquidity::Liquidity, - msg::{self, InstantiateMsg}, - percentage::Percentage, - sqrt_price::{calculate_sqrt_price, SqrtPrice}, - state::{self}, - FeeTier, PoolKey, -}; +// use crate::{ +// contract::{instantiate, migrate}, +// entrypoints::{self}, +// liquidity::Liquidity, +// msg::{self, InstantiateMsg}, +// percentage::Percentage, +// sqrt_price::{calculate_sqrt_price, SqrtPrice}, +// state::{self}, +// FeeTier, PoolKey, +// }; -#[test] -fn test_migrate_contract() { - // fixture - let mut deps = mock_dependencies(); +// #[test] +// fn test_migrate_contract() { +// // fixture +// let mut deps = mock_dependencies(); - let info = mock_info("alice", &[]); +// let info = mock_info("alice", &[]); - instantiate( - deps.as_mut(), - mock_env(), - info.clone(), - InstantiateMsg { - protocol_fee: Percentage::new(0), - }, - ) - .unwrap(); +// instantiate( +// deps.as_mut(), +// mock_env(), +// info.clone(), +// InstantiateMsg { +// protocol_fee: Percentage::new(0), +// }, +// ) +// .unwrap(); - let fee_tier = FeeTier::new(Percentage::new(0), 1).unwrap(); +// let fee_tier = FeeTier::new(Percentage::new(0), 1).unwrap(); - entrypoints::add_fee_tier(deps.as_mut(), mock_env(), info.clone(), fee_tier).unwrap(); +// entrypoints::add_fee_tier(deps.as_mut(), mock_env(), info.clone(), fee_tier).unwrap(); - let init_tick = 10; - let init_sqrt_price = calculate_sqrt_price(init_tick).unwrap(); - entrypoints::create_pool( - deps.as_mut(), - mock_env(), - "token_x".to_string(), - "token_y".to_string(), - fee_tier, - init_sqrt_price, - init_tick, - ) - .unwrap(); +// let init_tick = 10; +// let init_sqrt_price = calculate_sqrt_price(init_tick).unwrap(); +// entrypoints::create_pool( +// deps.as_mut(), +// mock_env(), +// "token_x".to_string(), +// "token_y".to_string(), +// fee_tier, +// init_sqrt_price, +// init_tick, +// ) +// .unwrap(); - let pool_key = PoolKey::new("token_x".to_string(), "token_y".to_string(), fee_tier).unwrap(); - let tick_indexes = [-9780, -42, 0, 9, 276, 32343, 50001]; - for i in 0..tick_indexes.len() - 1 { - entrypoints::create_position( - deps.as_mut(), - mock_env(), - info.clone(), - pool_key.clone(), - tick_indexes[i], - tick_indexes[i + 1], - Liquidity::new(10), - SqrtPrice::new(0), - SqrtPrice::max_instance(), - ) - .unwrap(); - } +// let pool_key = PoolKey::new("token_x".to_string(), "token_y".to_string(), fee_tier).unwrap(); +// let tick_indexes = [-9780, -42, 0, 9, 276, 32343, 50001]; +// for i in 0..tick_indexes.len() - 1 { +// entrypoints::create_position( +// deps.as_mut(), +// mock_env(), +// info.clone(), +// pool_key.clone(), +// tick_indexes[i], +// tick_indexes[i + 1], +// Liquidity::new(10), +// SqrtPrice::new(0), +// SqrtPrice::max_instance(), +// ) +// .unwrap(); +// } - // now can query first NFT info - let nft_info = entrypoints::query_nft_info(deps.as_ref(), 1).unwrap(); - assert_eq!(nft_info.extension.token_id, 1); +// // now can query first NFT info +// let nft_info = entrypoints::query_nft_info(deps.as_ref(), 1).unwrap(); +// assert_eq!(nft_info.extension.token_id, 1); - // we will reset to old storage - state::POSITION_KEYS_BY_TOKEN_ID.clear(deps.as_mut().storage); - state::TOKEN_COUNT.remove(deps.as_mut().storage); - state::TOKEN_ID.remove(deps.as_mut().storage); +// // we will reset to old storage +// state::POSITION_KEYS_BY_TOKEN_ID.clear(deps.as_mut().storage); +// state::TOKEN_COUNT.remove(deps.as_mut().storage); +// state::TOKEN_ID.remove(deps.as_mut().storage); - // and also reset all token_id in positions - let positions: Vec<_> = state::POSITIONS - .range_raw(deps.as_mut().storage, None, None, Order::Ascending) - .collect(); - for item in positions { - if let Ok((key, mut position)) = item { - position.token_id = 0; - // update position and its index - crate::state::POSITIONS - .save(deps.as_mut().storage, &key, &position) - .unwrap(); - } - } +// // and also reset all token_id in positions +// let positions: Vec<_> = state::POSITIONS +// .range_raw(deps.as_mut().storage, None, None, Order::Ascending) +// .collect(); +// for item in positions { +// if let Ok((key, mut position)) = item { +// position.token_id = 0; +// // update position and its index +// crate::state::POSITIONS +// .save(deps.as_mut().storage, &key, &position) +// .unwrap(); +// } +// } - // must return error - entrypoints::query_nft_info(deps.as_ref(), 1).unwrap_err(); - let num_tokens = entrypoints::query_num_tokens(deps.as_ref()).unwrap(); - assert_eq!(num_tokens.count, 0); +// // must return error +// entrypoints::query_nft_info(deps.as_ref(), 1).unwrap_err(); +// let num_tokens = entrypoints::query_num_tokens(deps.as_ref()).unwrap(); +// assert_eq!(num_tokens.count, 0); - // then migrate contract - migrate(deps.as_mut(), mock_env(), msg::MigrateMsg {}).unwrap(); +// // then migrate contract +// migrate(deps.as_mut(), mock_env(), msg::MigrateMsg {}).unwrap(); - // now can query first NFT info again - let nft_info = entrypoints::query_nft_info(deps.as_ref(), 1).unwrap(); - assert_eq!(nft_info.extension.token_id, 1); +// // now can query first NFT info again +// let nft_info = entrypoints::query_nft_info(deps.as_ref(), 1).unwrap(); +// assert_eq!(nft_info.extension.token_id, 1); - // total tokens is total ranges in tick_indexes - let num_tokens = entrypoints::query_num_tokens(deps.as_ref()).unwrap(); - assert_eq!(num_tokens.count as usize, tick_indexes.len() - 1); -} +// // total tokens is total ranges in tick_indexes +// let num_tokens = entrypoints::query_num_tokens(deps.as_ref()).unwrap(); +// assert_eq!(num_tokens.count as usize, tick_indexes.len() - 1); +// } From 2c6947f839eddf9ff59e9cf195aaa7a9f491444b Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 12:06:56 +0700 Subject: [PATCH 12/47] chore: test incentive with position cross out of range --- contracts/oraiswap-v3/src/tests/helper.rs | 21 ++ contracts/oraiswap-v3/src/tests/incentive.rs | 223 ++++++++++++++++++- 2 files changed, 238 insertions(+), 6 deletions(-) diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index 15b3dda..2d07f98 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -532,6 +532,20 @@ impl MockApp { ) } + pub fn claim_incentives( + &mut self, + sender: &str, + dex: &str, + index: u32, + ) -> Result { + self.execute( + Addr::unchecked(sender), + Addr::unchecked(dex), + &msg::ExecuteMsg::ClaimIncentive { index }, + &[], + ) + } + pub fn quote_route( &mut self, dex: &str, @@ -972,6 +986,13 @@ pub mod macros { } pub(crate) use claim_fee; + macro_rules! claim_incentives { + ($app:ident, $dex_address:expr, $index:expr, $caller:tt) => {{ + $app.claim_incentives($caller, $dex_address.as_str(), $index) + }}; + } + pub(crate) use claim_incentives; + macro_rules! init_slippage_pool_with_liquidity { ($app:ident, $dex_address:ident, $token_x_address:ident, $token_y_address:ident) => {{ let fee_tier = FeeTier { diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index bcbe1ae..4b70243 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -10,7 +10,7 @@ use crate::{ sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, + FeeTier, PoolKey, MAX_SQRT_PRICE, MIN_SQRT_PRICE, }; #[test] @@ -565,12 +565,223 @@ pub fn test_multi_incentives_with_multi_positions() { } #[test] pub fn test_incentive_with_position_cross_out_of_range() { - // TODO -} + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); -#[test] -pub fn test_incentive_with_position_cross_in_range() { - // TODO + let initial_amount = 10u128.pow(10); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = TokenAmount(1000000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + let liquidity = Liquidity::from_integer(1000000); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + + // create 2 position + // first_pos: range (-20, 20) + // second_pos: range (10, 50) + create_position!( + app, + dex, + pool_key, + -20, + 20, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + create_position!( + app, + dex, + pool_key, + 10, + 50, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // increase 1000s, the second position does not have incentive + let mut block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + + let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentives.len(), 1); + let incentives_2 = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!(incentives_2, vec![]); + + // try swap to cross tick + + let amount = 1000; + let swap_amount = TokenAmount(amount); + + mint!(app, token_y, "bob", amount, "alice").unwrap(); + approve!(app, token_y, dex, amount, "bob").unwrap(); + + let target_sqrt_price = SqrtPrice::new(MAX_SQRT_PRICE); + + let target_sqrt_price = quote!( + app, + dex, + pool_key, + false, + swap_amount, + true, + target_sqrt_price + ) + .unwrap() + .target_sqrt_price; + + swap!( + app, + dex, + pool_key, + false, + swap_amount, + true, + target_sqrt_price, + "bob" + ) + .unwrap(); + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.current_tick_index, 14); + + // currently, the both position in range + let incentive_1_before = get_position_incentives!(app, dex, 0, "alice").unwrap()[0].amount; + let incentive_2_before = get_position_incentives!(app, dex, 1, "alice").unwrap()[0].amount; + + // try increase 1000s + let mut block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + + let incentive_1_after = get_position_incentives!(app, dex, 0, "alice").unwrap()[0].amount; + let incentive_2_after = get_position_incentives!(app, dex, 1, "alice").unwrap()[0].amount; + + assert!(incentive_1_before.lt(&incentive_1_after)); + assert!(incentive_2_before.lt(&incentive_2_after)); + let emit = Uint128::new(100 * 1000); + assert!( + (incentive_1_after - incentive_1_before + incentive_2_after - incentive_2_before).le(&emit) + ); + + //try swap to out of range of fist position + let amount = 1000; + let swap_amount = TokenAmount(amount); + + mint!(app, token_y, "bob", amount, "alice").unwrap(); + approve!(app, token_y, dex, amount, "bob").unwrap(); + + let target_sqrt_price = SqrtPrice::new(MAX_SQRT_PRICE); + + let target_sqrt_price = quote!( + app, + dex, + pool_key, + false, + swap_amount, + true, + target_sqrt_price + ) + .unwrap() + .target_sqrt_price; + + swap!( + app, + dex, + pool_key, + false, + swap_amount, + true, + target_sqrt_price, + "bob" + ) + .unwrap(); + + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.current_tick_index, 29); + + // currently, the first position is out_of_range, but the second position still in range + let incentive_1_before = get_position_incentives!(app, dex, 0, "alice").unwrap()[0].amount; + let incentive_2_before = get_position_incentives!(app, dex, 1, "alice").unwrap()[0].amount; + + // try increase 1000s + let mut block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + + let incentive_1_after = get_position_incentives!(app, dex, 0, "alice").unwrap()[0].amount; + let incentive_2_after = get_position_incentives!(app, dex, 1, "alice").unwrap()[0].amount; + + assert!(incentive_1_before.eq(&incentive_1_after)); + assert!(incentive_2_before.lt(&incentive_2_after)); + let emit = Uint128::new(100 * 1000); + assert!( + (incentive_1_after - incentive_1_before + incentive_2_after - incentive_2_before).le(&emit) + ); + + // try claim incentives + let before_dex_balance = balance_of!(app, token_z, dex); + let before_user_balance = balance_of!(app, token_z, "alice"); + + claim_incentives!(app, dex, 0, "alice").unwrap(); + claim_incentives!(app, dex, 1, "alice").unwrap(); + + let after_dex_balance = balance_of!(app, token_z, dex); + let after_user_balance = balance_of!(app, token_z, "alice"); + assert!(before_dex_balance.gt(&after_dex_balance)); + assert!(before_user_balance.lt(&after_user_balance)); + assert!( + (before_user_balance + before_dex_balance).eq(&(after_user_balance + after_dex_balance)) + ); } #[test] From d18c3530c149159fcf2765e3e836c3addc8a4098 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 14:47:23 +0700 Subject: [PATCH 13/47] chore: test incentive in remove_position --- contracts/oraiswap-v3/src/tests/incentive.rs | 87 +++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 4b70243..cfbc1a2 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -786,5 +786,90 @@ pub fn test_incentive_with_position_cross_out_of_range() { #[test] pub fn test_remove_position() { - // TODO + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); + + let initial_amount = 10u128.pow(10); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = TokenAmount(1000000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + let liquidity = Liquidity::from_integer(1000000); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + // create position in range + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + + create_position!( + app, + dex, + pool_key, + -20, + 20, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // increase block time + let mut block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + + let before_dex_balance = balance_of!(app, token_z, dex); + let before_user_balance = balance_of!(app, token_z, "alice"); + + // try remove position + remove_position!(app, dex, 0, "alice").unwrap(); + + let after_dex_balance = balance_of!(app, token_z, dex); + let after_user_balance = balance_of!(app, token_z, "alice"); + + assert!(before_dex_balance.gt(&after_dex_balance)); + assert!(before_user_balance.lt(&after_user_balance)); + assert!( + (before_user_balance + before_dex_balance).eq(&(after_user_balance + after_dex_balance)) + ); } From c05be7b50e77886659fc92a398d8644449d36aeb Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Thu, 18 Jul 2024 15:55:47 +0700 Subject: [PATCH 14/47] add: event attribute --- .../oraiswap-v3/src/entrypoints/execute.rs | 18 ++++++++++++++---- contracts/oraiswap-v3/src/storage/pool_key.rs | 8 ++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 5ee4809..c2bf2b2 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -83,7 +83,9 @@ pub fn withdraw_protocol_fee( Ok(Response::new() .add_messages(msgs) - .add_attribute("action", "withdraw_protocol_fee")) + .add_attribute("action", "withdraw_protocol_fee") + .add_attribute("token_x", fee_protocol_token_x.to_string()) + .add_attribute("token_y", fee_protocol_token_y.to_string())) } /// Allows an admin to adjust the protocol fee. @@ -240,6 +242,8 @@ pub fn create_position( attr("lower_tick", lower_tick.index.to_string()), attr("upper_tick", upper_tick.index.to_string()), attr("current_sqrt_price", pool.sqrt_price.to_string()), + attr("amount_x", x.to_string()), + attr("amount_y", y.to_string()), ]; Ok(Response::new() @@ -288,6 +292,7 @@ pub fn swap( let CalculateSwapResult { amount_in, amount_out, + fee, .. } = swap_internal( deps.storage, @@ -306,8 +311,12 @@ pub fn swap( Ok(Response::new() .add_messages(msgs) .add_attribute("action", "swap") + .add_attribute("pool_key", pool_key.to_string()) .add_attribute("amount_in", amount_in.to_string()) - .add_attribute("amount_out", amount_out.to_string())) + .add_attribute("amount_out", amount_out.to_string()) + .add_attribute("amount_out", amount_out.to_string()) + .add_attribute("fee", fee.to_string()) + .add_attribute("x_to_y", x_to_y.to_string())) } /// Performs atomic swap involving several pools based on the provided parameters. @@ -354,7 +363,7 @@ pub fn swap_route( &info, &mut msgs, amount_in, - swaps, + swaps.clone(), )?; let min_amount_out = calculate_min_amount_out(expected_amount_out, slippage); @@ -366,7 +375,8 @@ pub fn swap_route( Ok(Response::new() .add_messages(msgs) .add_attribute("action", "swap_route") - .add_attribute("amount_out", amount_out.to_string())) + .add_attribute("amount_out", amount_out.to_string()) + .add_attribute("swap_hop", swaps.iter().map(|x| x.pool_key.to_string()).collect::>().join(","))) } /// Transfers a position between users. diff --git a/contracts/oraiswap-v3/src/storage/pool_key.rs b/contracts/oraiswap-v3/src/storage/pool_key.rs index 3d4161b..ff1c19f 100644 --- a/contracts/oraiswap-v3/src/storage/pool_key.rs +++ b/contracts/oraiswap-v3/src/storage/pool_key.rs @@ -63,6 +63,14 @@ impl PoolKey { }) } } + + pub fn to_string(&self) -> String { + // tokenx-tokeny-fee-tick_spacing + format!( + "{}-{}-{}-{}", + self.token_x, self.token_y, self.fee_tier.fee.0, self.fee_tier.tick_spacing + ) + } } #[cfg(test)] From 913a45357af2cc7d0cb01478df6390162361dcb5 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 16:03:13 +0700 Subject: [PATCH 15/47] chore: stress test incentives --- contracts/oraiswap-v3/src/tests/incentive.rs | 138 +++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index cfbc1a2..ae164f3 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -873,3 +873,141 @@ pub fn test_remove_position() { (before_user_balance + before_dex_balance).eq(&(after_user_balance + after_dex_balance)) ); } + +#[test] +pub fn incentive_stress_test() { + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); + + let initial_amount = 10u128.pow(20); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = TokenAmount(1000000000); + let start_timestamp: Option = None; + + let rps: Vec = vec![ + TokenAmount(1), + TokenAmount(5), + TokenAmount(10), + TokenAmount(49), + TokenAmount(99), + TokenAmount(10000), + ]; + + for i in 0..rps.len() { + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + rps[i], + start_timestamp, + "alice" + ) + .unwrap(); + } + + // create multi position + let liq = vec![3233322, 54343223, 3223135, 2431323, 1322339, 53283, 123293]; + let ranges = vec![ + -10000, -1000, -500, -90, -40, -20, -5, 4, 12, 23, 35, 42, 63, 120, 1000, 10000, + ]; + for i in 0..1000 { + let liquidity = Liquidity::from_integer(liq[i % liq.len()]); + let tick_index = i % (ranges.len() - 1); + let lower_tick = ranges[tick_index]; + let upper_tick = ranges[tick_index + 1]; + create_position!( + app, + dex, + pool_key, + lower_tick, + upper_tick, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + } + + // try swap + + mint!(app, token_y, "bob", initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "bob").unwrap(); + mint!(app, token_x, "bob", initial_amount, "alice").unwrap(); + approve!(app, token_x, dex, initial_amount, "bob").unwrap(); + + let swap_amounts: Vec = vec![2323, 233, 321, 5353, 12, 932, 42, 3123, 5438]; + let x_to_y_list = vec![true, false, false, true, true, false, false, true]; + + for i in 0..1000 { + let x_to_y = x_to_y_list[i % x_to_y_list.len()]; + let swap_amount = TokenAmount(swap_amounts[i % swap_amounts.len()]); + let target_sqrt_price = if x_to_y { + SqrtPrice::new(MIN_SQRT_PRICE) + } else { + SqrtPrice::new(MAX_SQRT_PRICE) + }; + + swap!( + app, + dex, + pool_key, + x_to_y, + swap_amount, + true, + target_sqrt_price, + "bob" + ) + .unwrap(); + } + + let before_dex_balance = balance_of!(app, token_z, dex); + let before_user_balance = balance_of!(app, token_z, "alice"); + + // claim all incentives + for _ in 0..1000 { + // try remove position + remove_position!(app, dex, 0, "alice").unwrap(); + } + + let after_dex_balance = balance_of!(app, token_z, dex); + let after_user_balance = balance_of!(app, token_z, "alice"); + + assert!(before_dex_balance.gt(&after_dex_balance)); + assert!(before_user_balance.lt(&after_user_balance)); + assert!( + (before_user_balance + before_dex_balance).eq(&(after_user_balance + after_dex_balance)) + ); +} From 505d25ad8cdc604db8f09cbfa05f05d60a67357f Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 16:13:58 +0700 Subject: [PATCH 16/47] chore: pump cosmwasm-testing-util --- Cargo.lock | 8 ++++---- contracts/oraiswap-v3/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d70558..e9b22a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -290,7 +290,7 @@ dependencies = [ [[package]] name = "cosmwasm-testing-util" version = "0.1.0" -source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=aaa09cf#aaa09cfe66da9e32dbc0627be575ff20e34a8e3a" +source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=53c270e573172f475eb2586b8fdeb3798ef9b599#53c270e573172f475eb2586b8fdeb3798ef9b599" dependencies = [ "bech32", "cosmwasm-crypto", @@ -1993,7 +1993,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "token-bindings" version = "0.11.0" -source = "git+https://github.com/oraichain/token-bindings.git?rev=e85d734#e85d7348b07c3d0403c60435c0a7d291af81f987" +source = "git+https://github.com/oraichain/token-bindings.git?rev=d379675#d3796751981e64da4b6917090c500a45bf6c072f" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2004,7 +2004,7 @@ dependencies = [ [[package]] name = "token-bindings-test" version = "0.11.0" -source = "git+https://github.com/oraichain/token-bindings.git?rev=e85d734#e85d7348b07c3d0403c60435c0a7d291af81f987" +source = "git+https://github.com/oraichain/token-bindings.git?rev=d379675#d3796751981e64da4b6917090c500a45bf6c072f" dependencies = [ "anyhow", "cosmwasm-std", @@ -2020,7 +2020,7 @@ dependencies = [ [[package]] name = "tokenfactory" version = "0.11.0" -source = "git+https://github.com/oraichain/token-bindings.git?rev=e85d734#e85d7348b07c3d0403c60435c0a7d291af81f987" +source = "git+https://github.com/oraichain/token-bindings.git?rev=d379675#d3796751981e64da4b6917090c500a45bf6c072f" dependencies = [ "cosmwasm-schema", "cosmwasm-std", diff --git a/contracts/oraiswap-v3/Cargo.toml b/contracts/oraiswap-v3/Cargo.toml index dcbea90..b17b50d 100644 --- a/contracts/oraiswap-v3/Cargo.toml +++ b/contracts/oraiswap-v3/Cargo.toml @@ -33,4 +33,4 @@ derive_more = { workspace = true } [dev-dependencies] cw-multi-test = { workspace = true } cw20-base = { workspace = true, features = ["library"] } -cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "aaa09cf" } +cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "53c270e573172f475eb2586b8fdeb3798ef9b599" } From e1567457e275ddad790eab6884d55e16ddfd8b32 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 18 Jul 2024 18:19:19 +0700 Subject: [PATCH 17/47] chore: remove duplicate event --- contracts/oraiswap-v3/src/entrypoints/execute.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index c2bf2b2..ddbad09 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -292,7 +292,7 @@ pub fn swap( let CalculateSwapResult { amount_in, amount_out, - fee, + fee, .. } = swap_internal( deps.storage, @@ -314,7 +314,6 @@ pub fn swap( .add_attribute("pool_key", pool_key.to_string()) .add_attribute("amount_in", amount_in.to_string()) .add_attribute("amount_out", amount_out.to_string()) - .add_attribute("amount_out", amount_out.to_string()) .add_attribute("fee", fee.to_string()) .add_attribute("x_to_y", x_to_y.to_string())) } @@ -376,7 +375,14 @@ pub fn swap_route( .add_messages(msgs) .add_attribute("action", "swap_route") .add_attribute("amount_out", amount_out.to_string()) - .add_attribute("swap_hop", swaps.iter().map(|x| x.pool_key.to_string()).collect::>().join(","))) + .add_attribute( + "swap_hop", + swaps + .iter() + .map(|x| x.pool_key.to_string()) + .collect::>() + .join(","), + )) } /// Transfers a position between users. From 7cc9845a81fcea1d7eaaa867961f74a39aecbbda Mon Sep 17 00:00:00 2001 From: ducphamle2 Date: Thu, 18 Jul 2024 17:53:06 -0700 Subject: [PATCH 18/47] optimize claim incentives & avoid pushing empty incentives --- .../oraiswap-v3/src/storage/incentive.rs | 1 + contracts/oraiswap-v3/src/storage/position.rs | 50 +++++++++++-------- contracts/oraiswap-v3/src/storage/tick.rs | 3 ++ contracts/oraiswap-v3/src/tests/incentive.rs | 1 + 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/contracts/oraiswap-v3/src/storage/incentive.rs b/contracts/oraiswap-v3/src/storage/incentive.rs index 9d78457..6046336 100644 --- a/contracts/oraiswap-v3/src/storage/incentive.rs +++ b/contracts/oraiswap-v3/src/storage/incentive.rs @@ -66,6 +66,7 @@ impl IncentiveRecord { } } +// reference: https://uniswap.org/whitepaper-v3.pdf (6.17) and (6.18) pub fn calculate_incentive_growth_inside( tick_lower: i32, tick_lower_incentive_growth_outside: FeeGrowth, diff --git a/contracts/oraiswap-v3/src/storage/position.rs b/contracts/oraiswap-v3/src/storage/position.rs index e3ba714..77b06a7 100644 --- a/contracts/oraiswap-v3/src/storage/position.rs +++ b/contracts/oraiswap-v3/src/storage/position.rs @@ -125,14 +125,18 @@ impl Position { .unchecked_sub(incentive.incentive_growth_inside) .to_fee(self.liquidity)?; incentive.incentive_growth_inside = incentive_growth_inside; - } else { - let incentive = PositionIncentives { - incentive_id: record.id, - pending_rewards: incentive_growth_inside.to_fee(self.liquidity)?, - incentive_growth_inside, - }; - self.incentives.push(incentive); + continue; } + let pending_rewards = incentive_growth_inside.to_fee(self.liquidity)?; + if pending_rewards.is_zero() { + continue; + } + let incentive = PositionIncentives { + incentive_id: record.id, + pending_rewards, + incentive_growth_inside, + }; + self.incentives.push(incentive); } Ok(()) @@ -216,22 +220,24 @@ impl Position { ) -> Result, ContractError> { self.update_incentives(pool, upper_tick, lower_tick)?; let mut incentives: Vec = vec![]; - - for incentive in &mut self.incentives { - if incentive.pending_rewards.gt(&TokenAmount::new(0)) { - if let Some(record) = pool - .incentives - .iter() - .find(|i| i.id == incentive.incentive_id) - { - incentives.push(Asset { - info: record.reward_token.clone(), - amount: incentive.pending_rewards.into(), - }); - incentive.pending_rewards = TokenAmount::new(0); - } + // remove all incentives that has no pending rewards to keep the incentives list short. + self.incentives.retain(|incentive| { + if incentive.pending_rewards.is_zero() { + return false; } - } + if let Some(record) = pool + .incentives + .iter() + .find(|i| i.id == incentive.incentive_id) + { + incentives.push(Asset { + info: record.reward_token.clone(), + amount: incentive.pending_rewards.into(), + }); + return false; + } + true + }); Ok(incentives) } diff --git a/contracts/oraiswap-v3/src/storage/tick.rs b/contracts/oraiswap-v3/src/storage/tick.rs index a3ca649..3fc2f38 100644 --- a/contracts/oraiswap-v3/src/storage/tick.rs +++ b/contracts/oraiswap-v3/src/storage/tick.rs @@ -65,6 +65,7 @@ impl Tick { let below_current_tick = index <= pool.current_tick_index; // ensure update global incentive before + // reference: https://uniswap.org/whitepaper-v3.pdf (6.21) let incentives: Vec = pool .incentives .iter() @@ -99,6 +100,7 @@ impl Tick { } pub fn cross(&mut self, pool: &mut Pool, current_timestamp: u64) -> Result<(), ContractError> { + // reference: https://uniswap.org/whitepaper-v3.pdf (6.20) self.fee_growth_outside_x = pool .fee_growth_global_x .unchecked_sub(self.fee_growth_outside_x); @@ -122,6 +124,7 @@ impl Tick { .iter_mut() .find(|i| i.incentive_id == record.id) { + // reference: https://uniswap.org/whitepaper-v3.pdf (6.20) // Update the incentive growth if it exists incentive.incentive_growth_outside = record .incentive_growth_global diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index ae164f3..37e103d 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -653,6 +653,7 @@ pub fn test_incentive_with_position_cross_out_of_range() { let incentives = get_position_incentives!(app, dex, 0, "alice").unwrap(); assert_eq!(incentives.len(), 1); + println!("incentives: {:?}", incentives); let incentives_2 = get_position_incentives!(app, dex, 1, "alice").unwrap(); assert_eq!(incentives_2, vec![]); From 488198b03acc5914de57cd0e071c63519b1bcc8c Mon Sep 17 00:00:00 2001 From: Pham Tu Date: Fri, 19 Jul 2024 08:38:10 +0700 Subject: [PATCH 19/47] using retain --- .../oraiswap-v3/src/entrypoints/common.rs | 22 ++----------------- .../oraiswap-v3/src/entrypoints/query.rs | 14 +++++++----- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/common.rs b/contracts/oraiswap-v3/src/entrypoints/common.rs index efd8788..ac47f1e 100644 --- a/contracts/oraiswap-v3/src/entrypoints/common.rs +++ b/contracts/oraiswap-v3/src/entrypoints/common.rs @@ -1,6 +1,4 @@ -use cosmwasm_std::{ - Addr, Api, BlockInfo, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Storage, Timestamp, -}; +use cosmwasm_std::{Addr, Api, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Storage, Timestamp}; use cw20::Expiration; use decimal::{CheckedOps, Decimal}; @@ -428,11 +426,7 @@ pub fn update_approvals( check_can_approve(deps.as_ref(), env, info, &owner_raw)?; // update the approval list (remove any for the same spender before adding) - pos.approvals = pos - .approvals - .into_iter() - .filter(|apr| apr.spender != spender) - .collect(); + pos.approvals.retain(|apr| apr.spender != spender); // only difference between approve and revoke if add { @@ -473,15 +467,3 @@ pub fn transfer_nft( Ok(()) } - -pub fn humanize_approvals( - block: &BlockInfo, - pos: &Position, - include_expired: bool, -) -> Vec { - pos.approvals - .iter() - .filter(|apr| include_expired || !apr.expires.is_expired(block)) - .map(|approval| approval.clone()) - .collect() -} diff --git a/contracts/oraiswap-v3/src/entrypoints/query.rs b/contracts/oraiswap-v3/src/entrypoints/query.rs index 1efe054..468b989 100644 --- a/contracts/oraiswap-v3/src/entrypoints/query.rs +++ b/contracts/oraiswap-v3/src/entrypoints/query.rs @@ -16,7 +16,7 @@ use crate::{ LIQUIDITY_TICK_LIMIT, POSITION_TICK_LIMIT, }; -use super::{calculate_swap, humanize_approvals, route, tickmap_slice, TimeStampExt}; +use super::{calculate_swap, route, tickmap_slice, TimeStampExt}; /// Retrieves the admin of contract. pub fn query_admin(deps: Deps) -> Result { @@ -412,10 +412,12 @@ pub fn query_owner_of( ) -> Result { let (owner_raw, index) = state::POSITION_KEYS_BY_TOKEN_ID.load(deps.storage, token_id)?; let owner = Addr::unchecked(String::from_utf8(owner_raw.to_vec())?); - let pos = state::get_position(deps.storage, &owner, index)?; + let mut pos = state::get_position(deps.storage, &owner, index)?; + pos.approvals + .retain(|apr| include_expired || !apr.expires.is_expired(&env.block)); Ok(OwnerOfResponse { owner, - approvals: humanize_approvals(&env.block, &pos, include_expired), + approvals: pos.approvals, }) } @@ -463,11 +465,13 @@ pub fn query_all_nft_info( ) -> Result { let (owner_raw, index) = state::POSITION_KEYS_BY_TOKEN_ID.load(deps.storage, token_id)?; let owner = Addr::unchecked(String::from_utf8(owner_raw.to_vec())?); - let pos = state::get_position(deps.storage, &owner, index)?; + let mut pos = state::get_position(deps.storage, &owner, index)?; + pos.approvals + .retain(|apr| include_expired || !apr.expires.is_expired(&env.block)); Ok(AllNftInfoResponse { access: OwnerOfResponse { owner, - approvals: humanize_approvals(&env.block, &pos, include_expired), + approvals: pos.approvals.clone(), }, info: NftInfoResponse { extension: pos }, }) From dfc23de6921e1b22b16631bd27fb0f364d24c453 Mon Sep 17 00:00:00 2001 From: ducphamle2 Date: Thu, 18 Jul 2024 18:51:50 -0700 Subject: [PATCH 20/47] fix: only filter map pos incentive, dont delete --- contracts/oraiswap-v3/src/storage/position.rs | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/contracts/oraiswap-v3/src/storage/position.rs b/contracts/oraiswap-v3/src/storage/position.rs index 77b06a7..ce1c138 100644 --- a/contracts/oraiswap-v3/src/storage/position.rs +++ b/contracts/oraiswap-v3/src/storage/position.rs @@ -128,7 +128,7 @@ impl Position { continue; } let pending_rewards = incentive_growth_inside.to_fee(self.liquidity)?; - if pending_rewards.is_zero() { + if pending_rewards.is_zero() && incentive_growth_inside.is_zero() { continue; } let incentive = PositionIncentives { @@ -219,25 +219,26 @@ impl Position { lower_tick: &Tick, ) -> Result, ContractError> { self.update_incentives(pool, upper_tick, lower_tick)?; - let mut incentives: Vec = vec![]; - // remove all incentives that has no pending rewards to keep the incentives list short. - self.incentives.retain(|incentive| { - if incentive.pending_rewards.is_zero() { - return false; - } - if let Some(record) = pool - .incentives - .iter() - .find(|i| i.id == incentive.incentive_id) - { - incentives.push(Asset { - info: record.reward_token.clone(), - amount: incentive.pending_rewards.into(), - }); - return false; - } - true - }); + let incentives: Vec = self + .incentives + .iter() + .filter_map(|incentive| { + if incentive.pending_rewards.is_zero() { + return None; + } + if let Some(record) = pool + .incentives + .iter() + .find(|i| i.id == incentive.incentive_id) + { + return Some(Asset { + info: record.reward_token.clone(), + amount: incentive.pending_rewards.into(), + }); + } + None + }) + .collect(); Ok(incentives) } From 28e211f1012c34cfc40596ad5bdd708d3a0b6a89 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Fri, 19 Jul 2024 09:54:31 +0700 Subject: [PATCH 21/47] fix: fix don't set reward to zero after claim and add test case claim_incentives --- contracts/oraiswap-v3/src/storage/position.rs | 6 +- contracts/oraiswap-v3/src/tests/incentive.rs | 99 +++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/contracts/oraiswap-v3/src/storage/position.rs b/contracts/oraiswap-v3/src/storage/position.rs index ce1c138..3a513da 100644 --- a/contracts/oraiswap-v3/src/storage/position.rs +++ b/contracts/oraiswap-v3/src/storage/position.rs @@ -221,7 +221,7 @@ impl Position { self.update_incentives(pool, upper_tick, lower_tick)?; let incentives: Vec = self .incentives - .iter() + .iter_mut() .filter_map(|incentive| { if incentive.pending_rewards.is_zero() { return None; @@ -231,9 +231,11 @@ impl Position { .iter() .find(|i| i.id == incentive.incentive_id) { + let reward = incentive.pending_rewards; + incentive.pending_rewards = TokenAmount::new(0); return Some(Asset { info: record.reward_token.clone(), - amount: incentive.pending_rewards.into(), + amount: reward.into(), }); } None diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 37e103d..bc0db36 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -1012,3 +1012,102 @@ pub fn incentive_stress_test() { (before_user_balance + before_dex_balance).eq(&(after_user_balance + after_dex_balance)) ); } + +#[test] +pub fn test_claim_incentive_with_single_position() { + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); + + let initial_amount = 10u128.pow(10); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = TokenAmount::from_integer(1000000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + let liquidity = Liquidity::from_integer(1000000); + + // create position in range + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + create_position!( + app, + dex, + pool_key, + -20, + 20, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + let timestamp_init = app.app.block_info().time.seconds(); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + let before_dex_balance = balance_of!(app, token_z, dex); + let before_user_balance = balance_of!(app, token_z, "alice"); + + // increase block time + for _ in 0..100 { + let mut block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + + // claim incentives + claim_incentives!(app, dex, 0, "alice").unwrap(); + let position_state = get_position!(app, dex, 0, "alice").unwrap(); + assert_eq!(position_state.incentives[0].pending_rewards, TokenAmount(0)); + } + let timestamp_after = app.app.block_info().time.seconds(); + let total_emit = (timestamp_after - timestamp_init) as u128 * reward_per_sec.0; + + let after_dex_balance = balance_of!(app, token_z, dex); + let after_user_balance = balance_of!(app, token_z, "alice"); + + assert!(before_dex_balance.gt(&after_dex_balance)); + assert!(before_user_balance.lt(&after_user_balance)); + assert!( + (before_user_balance + before_dex_balance).eq(&(after_user_balance + after_dex_balance)) + ); + // total claimed of user must be less than or equal total emit + assert!((after_user_balance - before_user_balance).le(&total_emit)); +} From 59d1863aa531e5887aa7f32c426f79e5a5390e83 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Fri, 19 Jul 2024 09:57:46 +0700 Subject: [PATCH 22/47] chore: use fmt:Display for PoolKet instead of to_string() --- contracts/oraiswap-v3/src/storage/pool_key.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/oraiswap-v3/src/storage/pool_key.rs b/contracts/oraiswap-v3/src/storage/pool_key.rs index ff1c19f..ff835ce 100644 --- a/contracts/oraiswap-v3/src/storage/pool_key.rs +++ b/contracts/oraiswap-v3/src/storage/pool_key.rs @@ -1,3 +1,5 @@ +use core::fmt; + use crate::{ContractError, FeeTier}; use cosmwasm_schema::cw_serde; use cosmwasm_storage::to_length_prefixed_nested; @@ -63,16 +65,18 @@ impl PoolKey { }) } } +} - pub fn to_string(&self) -> String { +impl fmt::Display for PoolKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // tokenx-tokeny-fee-tick_spacing - format!( + write!( + f, "{}-{}-{}-{}", self.token_x, self.token_y, self.fee_tier.fee.0, self.fee_tier.tick_spacing ) } } - #[cfg(test)] mod tests { use cosmwasm_std::Addr; @@ -96,5 +100,7 @@ mod tests { pool_key.key(), to_length_prefixed_nested(&[b"token_0", b"token_1", fee_tier.key().as_slice()]) ); + + println!("{:?}", pool_key.to_string()); } } From 7de5a3991ad6e89fcd5eacba78af3b563f5e7c20 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Fri, 19 Jul 2024 11:01:59 +0700 Subject: [PATCH 23/47] chore: add test claim incentive with multi position --- contracts/oraiswap-v3/src/tests/incentive.rs | 112 ++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index bc0db36..101f8e7 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -963,7 +963,6 @@ pub fn incentive_stress_test() { } // try swap - mint!(app, token_y, "bob", initial_amount, "alice").unwrap(); approve!(app, token_y, dex, initial_amount, "bob").unwrap(); mint!(app, token_x, "bob", initial_amount, "alice").unwrap(); @@ -1111,3 +1110,114 @@ pub fn test_claim_incentive_with_single_position() { // total claimed of user must be less than or equal total emit assert!((after_user_balance - before_user_balance).le(&total_emit)); } + +#[test] +pub fn test_claim_incentive_with_multi_position() { + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); + + let initial_amount = 10u128.pow(10); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = TokenAmount::from_integer(1000000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + + // create position in range + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + let timestamp_init = app.app.block_info().time.seconds(); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + // create multi position + let liq = vec![3233322, 54343223, 3223135, 2431323, 1322339, 53283, 123293]; + let ranges = vec![ + -10000, -1000, -500, -90, -40, -20, -5, 4, 12, 23, 35, 42, 63, 120, 1000, 10000, + ]; + for i in 0..100 { + let liquidity = Liquidity::from_integer(liq[i % liq.len()]); + let tick_index = i % (ranges.len() - 1); + let lower_tick = ranges[tick_index]; + let upper_tick = ranges[tick_index + 1]; + create_position!( + app, + dex, + pool_key, + lower_tick, + upper_tick, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + } + + let before_dex_balance = balance_of!(app, token_z, dex); + let before_user_balance = balance_of!(app, token_z, "alice"); + + // increase block time + for _ in 0..100 { + let mut block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + for i in 0..100 { + // claim incentives + claim_incentives!(app, dex, i, "alice").unwrap(); + let position_state = get_position!(app, dex, i, "alice").unwrap(); + assert_eq!(position_state.incentives[0].pending_rewards, TokenAmount(0)); + } + } + + let timestamp_after = app.app.block_info().time.seconds(); + let total_emit = (timestamp_after - timestamp_init) as u128 * reward_per_sec.0; + + let after_dex_balance = balance_of!(app, token_z, dex); + let after_user_balance = balance_of!(app, token_z, "alice"); + + assert!(before_dex_balance.gt(&after_dex_balance)); + assert!(before_user_balance.lt(&after_user_balance)); + assert!( + (before_user_balance + before_dex_balance).eq(&(after_user_balance + after_dex_balance)) + ); + // total claimed of user must be less than or equal total emit + assert!((after_user_balance - before_user_balance).le(&total_emit)); +} From 1615eb33e163bd9f48435b53c1edbb0691178d23 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Fri, 19 Jul 2024 15:04:09 +0700 Subject: [PATCH 24/47] chore: test inventive with tick move left to right and vice versa --- contracts/oraiswap-v3/src/tests/helper.rs | 8 +- contracts/oraiswap-v3/src/tests/incentive.rs | 306 +++++++++++++++++++ 2 files changed, 313 insertions(+), 1 deletion(-) diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index cc5739f..ce45214 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Addr, Coin, Event, StdResult}; +use cosmwasm_std::{Addr, Coin, Event, StdResult, Timestamp}; use cw_multi_test::{AppResponse, ContractWrapper}; use crate::{ @@ -440,6 +440,12 @@ impl MockApp { &[], ) } + + pub fn increase_block_time_by_seconds(&mut self, seconds: u64) { + let mut block_info = self.app.app.block_info(); + block_info.time = Timestamp::from_seconds(block_info.time.seconds() + seconds); + self.app.app.set_block(block_info); + } } pub fn extract_amount(events: &[Event], key: &str) -> Option { diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 101f8e7..4b3ae3d 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -1221,3 +1221,309 @@ pub fn test_claim_incentive_with_multi_position() { // total claimed of user must be less than or equal total emit assert!((after_user_balance - before_user_balance).le(&total_emit)); } + +#[test] +pub fn test_update_incentive_with_tick_move_left_to_right() { + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); + + let initial_amount = 10u128.pow(10); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = TokenAmount(1000000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + let liquidity = Liquidity::from_integer(1000000); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + + // create 2 position + // first_pos: range (10, 20) + // second_pos: range (30, 40) + create_position!( + app, + dex, + pool_key, + 10, + 20, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + create_position!( + app, + dex, + pool_key, + 30, + 40, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // Both positions do not have any incentives due to being out of range + app.increase_block_time_by_seconds(1000); + let incentive = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentive, vec![]); + let incentive = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!(incentive, vec![]); + + // swap y to x, tick move left -> right + let amount = 100; + let swap_amount = TokenAmount(amount); + mint!(app, token_y, "bob", amount, "alice").unwrap(); + approve!(app, token_y, dex, amount, "bob").unwrap(); + swap!( + app, + dex, + pool_key, + false, + swap_amount, + true, + SqrtPrice::new(MAX_SQRT_PRICE), + "bob" + ) + .unwrap(); + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.current_tick_index, 11); + // The first position has an incentive, but the second one does not have any. + app.increase_block_time_by_seconds(1000); + let incentive = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentive, + vec![Asset { + info: reward_token.clone(), + amount: Uint128::new(100500u128) + }] + ); + let incentive = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!(incentive, vec![]); + + // swap again + let amount = 700; + let swap_amount = TokenAmount(amount); + mint!(app, token_y, "bob", amount, "alice").unwrap(); + approve!(app, token_y, dex, amount, "bob").unwrap(); + swap!( + app, + dex, + pool_key, + false, + swap_amount, + true, + SqrtPrice::new(MAX_SQRT_PRICE), + "bob" + ) + .unwrap(); + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.current_tick_index, 35); + // the second position have incentive, + claim_incentives!(app, dex, 0, "alice").unwrap(); + app.increase_block_time_by_seconds(1000); + let incentive = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentive, vec![]); + let incentive = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!( + incentive, + vec![Asset { + info: reward_token.clone(), + amount: Uint128::new(101000u128) + }] + ); +} + +#[test] +pub fn test_update_incentive_with_tick_move_right_to_left() { + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); + + let initial_amount = 10u128.pow(10); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = TokenAmount(1000000000); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + let liquidity = Liquidity::from_integer(1000000); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + + // create 2 position + // first_pos: range (-20, -10) + // second_pos: range (-40, -30) + create_position!( + app, + dex, + pool_key, + -20, + -10, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + create_position!( + app, + dex, + pool_key, + -40, + -30, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + // Both positions do not have any incentives due to being out of range + app.increase_block_time_by_seconds(1000); + let incentive = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentive, vec![]); + let incentive = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!(incentive, vec![]); + + // swap x to y, tick move right -> left + let amount = 100; + let swap_amount = TokenAmount(amount); + mint!(app, token_x, "bob", amount, "alice").unwrap(); + approve!(app, token_x, dex, amount, "bob").unwrap(); + swap!( + app, + dex, + pool_key, + true, + swap_amount, + true, + SqrtPrice::new(MIN_SQRT_PRICE), + "bob" + ) + .unwrap(); + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.current_tick_index, -12); + // The first position has an incentive, but the second one does not have any. + app.increase_block_time_by_seconds(1000); + let incentive = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!( + incentive, + vec![Asset { + info: reward_token.clone(), + amount: Uint128::new(100500u128) + }] + ); + let incentive = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!(incentive, vec![]); + + // swap again + let amount = 700; + let swap_amount = TokenAmount(amount); + mint!(app, token_x, "bob", amount, "alice").unwrap(); + approve!(app, token_x, dex, amount, "bob").unwrap(); + swap!( + app, + dex, + pool_key, + true, + swap_amount, + true, + SqrtPrice::new(MIN_SQRT_PRICE), + "bob" + ) + .unwrap(); + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.current_tick_index, -36); + // the second position have incentive, + claim_incentives!(app, dex, 0, "alice").unwrap(); + app.increase_block_time_by_seconds(1000); + let incentive = get_position_incentives!(app, dex, 0, "alice").unwrap(); + assert_eq!(incentive, vec![]); + let incentive = get_position_incentives!(app, dex, 1, "alice").unwrap(); + assert_eq!( + incentive, + vec![Asset { + info: reward_token.clone(), + amount: Uint128::new(101000u128) + }] + ); +} From c226befefa58acdcfd8643eaaddcf94ad55c9eb6 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Sat, 20 Jul 2024 02:42:49 +0700 Subject: [PATCH 25/47] test --- .../oraiswap-v3/src/entrypoints/execute.rs | 7 ++-- contracts/oraiswap-v3/src/msg.rs | 2 +- contracts/oraiswap-v3/src/tests/helper.rs | 2 +- contracts/oraiswap-v3/src/tests/incentive.rs | 32 +++++++++---------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index ddbad09..932e813 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -913,7 +913,7 @@ pub fn create_incentive( info: MessageInfo, pool_key: PoolKey, reward_token: AssetInfo, - total_reward: TokenAmount, + total_reward: Option, reward_per_sec: TokenAmount, start_timestamp: Option, ) -> Result { @@ -927,11 +927,12 @@ pub fn create_incentive( pool.update_global_incentives(env.block.time.seconds())?; let id = pool.incentives.len() as u64; + let remaining = total_reward.unwrap_or(TokenAmount(u128::MAX)); let incentive = IncentiveRecord { id, reward_per_sec, reward_token: reward_token.clone(), - remaining: total_reward, + remaining: remaining, start_timestamp: start_timestamp.unwrap_or(env.block.time.seconds()), incentive_growth_global: FeeGrowth(0), last_updated: env.block.time.seconds(), @@ -944,7 +945,7 @@ pub fn create_incentive( ("action", "create_incentive"), ("pool", &format!("{:?}", pool_key)), ("reward_token", &format!("{:?}", reward_token)), - ("total_reward", &total_reward.to_string()), + ("total_reward", &remaining.to_string()), ("reward_per_sec", &reward_per_sec.to_string()), ( "reward_per_sec", diff --git a/contracts/oraiswap-v3/src/msg.rs b/contracts/oraiswap-v3/src/msg.rs index 82e170b..48282c3 100644 --- a/contracts/oraiswap-v3/src/msg.rs +++ b/contracts/oraiswap-v3/src/msg.rs @@ -134,7 +134,7 @@ pub enum ExecuteMsg { CreateIncentive { pool_key: PoolKey, reward_token: AssetInfo, - total_reward: TokenAmount, + total_reward: Option, reward_per_sec: TokenAmount, start_timestamp: Option, }, diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index ce45214..abe89b2 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -423,7 +423,7 @@ impl MockApp { dex: &str, pool_key: &PoolKey, reward_token: AssetInfo, - total_reward: TokenAmount, + total_reward: Option, reward_per_sec: TokenAmount, start_timestamp: Option, ) -> Result { diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 4b3ae3d..13e594e 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -42,7 +42,7 @@ pub fn test_create_incentive() { let reward_token = AssetInfo::NativeToken { denom: "orai".to_string(), }; - let total_reward = TokenAmount(1000000000); + let total_reward = Some(TokenAmount(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; let current_time = app.app.block_info().time.seconds(); @@ -65,7 +65,7 @@ pub fn test_create_incentive() { id: 0, reward_per_sec, reward_token: reward_token.clone(), - remaining: total_reward, + remaining: total_reward.unwrap(), start_timestamp: current_time, incentive_growth_global: FeeGrowth(0), last_updated: current_time @@ -93,7 +93,7 @@ pub fn test_create_incentive() { id: 0, reward_per_sec, reward_token: reward_token.clone(), - remaining: total_reward, + remaining: total_reward.unwrap(), start_timestamp: current_time, incentive_growth_global: FeeGrowth(0), last_updated: new_timestamp_time @@ -102,7 +102,7 @@ pub fn test_create_incentive() { id: 1, reward_per_sec, reward_token: reward_token.clone(), - remaining: total_reward, + remaining: total_reward.unwrap(), start_timestamp: new_timestamp_time, incentive_growth_global: FeeGrowth(0), last_updated: new_timestamp_time @@ -153,7 +153,7 @@ pub fn test_single_incentive_with_single_position() { let reward_token = AssetInfo::NativeToken { denom: "orai".to_string(), }; - let total_reward = TokenAmount(1000000); + let total_reward = Some(TokenAmount(1000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; create_incentive!( @@ -266,7 +266,7 @@ pub fn test_multi_incentives_with_single_position() { let reward_token_2 = AssetInfo::Token { contract_addr: Addr::unchecked("usdt"), }; - let total_reward = TokenAmount(1000000); + let total_reward = Some(TokenAmount(1000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; create_incentive!( @@ -285,7 +285,7 @@ pub fn test_multi_incentives_with_single_position() { dex, pool_key, reward_token_2.clone(), - TokenAmount(1000000000), + Some(TokenAmount(1000000000)), TokenAmount(200), start_timestamp, "alice" @@ -423,7 +423,7 @@ pub fn test_multi_incentives_with_multi_positions() { let reward_token_2 = AssetInfo::Token { contract_addr: Addr::unchecked("usdt"), }; - let total_reward = TokenAmount(1000000); + let total_reward = Some(TokenAmount(1000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; create_incentive!( @@ -442,7 +442,7 @@ pub fn test_multi_incentives_with_multi_positions() { dex, pool_key, reward_token_2.clone(), - TokenAmount(1000000000), + Some(TokenAmount(1000000000)), TokenAmount(200), start_timestamp, "alice" @@ -598,7 +598,7 @@ pub fn test_incentive_with_position_cross_out_of_range() { let reward_token = AssetInfo::Token { contract_addr: token_z.clone(), }; - let total_reward = TokenAmount(1000000000); + let total_reward = Some(TokenAmount(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; let liquidity = Liquidity::from_integer(1000000); @@ -820,7 +820,7 @@ pub fn test_remove_position() { let reward_token = AssetInfo::Token { contract_addr: token_z.clone(), }; - let total_reward = TokenAmount(1000000000); + let total_reward = Some(TokenAmount(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; let liquidity = Liquidity::from_integer(1000000); @@ -912,7 +912,7 @@ pub fn incentive_stress_test() { let reward_token = AssetInfo::Token { contract_addr: token_z.clone(), }; - let total_reward = TokenAmount(1000000000); + let total_reward = Some(TokenAmount(1000000000)); let start_timestamp: Option = None; let rps: Vec = vec![ @@ -1047,7 +1047,7 @@ pub fn test_claim_incentive_with_single_position() { let reward_token = AssetInfo::Token { contract_addr: token_z.clone(), }; - let total_reward = TokenAmount::from_integer(1000000000); + let total_reward = Some(TokenAmount::from_integer(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; let liquidity = Liquidity::from_integer(1000000); @@ -1146,7 +1146,7 @@ pub fn test_claim_incentive_with_multi_position() { let reward_token = AssetInfo::Token { contract_addr: token_z.clone(), }; - let total_reward = TokenAmount::from_integer(1000000000); + let total_reward = Some(TokenAmount::from_integer(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; @@ -1257,7 +1257,7 @@ pub fn test_update_incentive_with_tick_move_left_to_right() { let reward_token = AssetInfo::Token { contract_addr: token_z.clone(), }; - let total_reward = TokenAmount(1000000000); + let total_reward = Some(TokenAmount(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; let liquidity = Liquidity::from_integer(1000000); @@ -1410,7 +1410,7 @@ pub fn test_update_incentive_with_tick_move_right_to_left() { let reward_token = AssetInfo::Token { contract_addr: token_z.clone(), }; - let total_reward = TokenAmount(1000000000); + let total_reward = Some(TokenAmount(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; let liquidity = Liquidity::from_integer(1000000); From c4316cce328527ab71cb27e4275906f34a2fca11 Mon Sep 17 00:00:00 2001 From: ducphamle2 Date: Sat, 20 Jul 2024 10:53:39 -0700 Subject: [PATCH 26/47] fix: pump testing util to fix mem err & add test cases --- Cargo.lock | 2 +- contracts/oraiswap-v3/Cargo.toml | 2 +- .../oraiswap-v3/src/tests/add_fee_tier.rs | 4 +- contracts/oraiswap-v3/src/tests/admin.rs | 2 +- .../src/tests/change_fee_receiver.rs | 2 +- .../src/tests/change_protocol_fee.rs | 2 +- contracts/oraiswap-v3/src/tests/helper.rs | 22 +++++++++ contracts/oraiswap-v3/src/tests/incentive.rs | 47 +++++++++++++++++++ 8 files changed, 76 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9b22a3..9fb8b54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -290,7 +290,7 @@ dependencies = [ [[package]] name = "cosmwasm-testing-util" version = "0.1.0" -source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=53c270e573172f475eb2586b8fdeb3798ef9b599#53c270e573172f475eb2586b8fdeb3798ef9b599" +source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=0c9c4d82719ab8e0b51192858c7744a77c5cf0b1#0c9c4d82719ab8e0b51192858c7744a77c5cf0b1" dependencies = [ "bech32", "cosmwasm-crypto", diff --git a/contracts/oraiswap-v3/Cargo.toml b/contracts/oraiswap-v3/Cargo.toml index b17b50d..b849436 100644 --- a/contracts/oraiswap-v3/Cargo.toml +++ b/contracts/oraiswap-v3/Cargo.toml @@ -33,4 +33,4 @@ derive_more = { workspace = true } [dev-dependencies] cw-multi-test = { workspace = true } cw20-base = { workspace = true, features = ["library"] } -cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "53c270e573172f475eb2586b8fdeb3798ef9b599" } +cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "0c9c4d82719ab8e0b51192858c7744a77c5cf0b1" } diff --git a/contracts/oraiswap-v3/src/tests/add_fee_tier.rs b/contracts/oraiswap-v3/src/tests/add_fee_tier.rs index 0b4bb43..c7a9b5b 100644 --- a/contracts/oraiswap-v3/src/tests/add_fee_tier.rs +++ b/contracts/oraiswap-v3/src/tests/add_fee_tier.rs @@ -31,7 +31,7 @@ fn test_add_fee_tier_not_admin() { let fee_tier = FeeTier::new(Percentage::new(1), 1).unwrap(); let result = add_fee_tier!(app, dex, fee_tier, "bob").unwrap_err(); - assert!(result.contains("error executing WasmMsg")); + assert!(result.to_string().contains("error executing WasmMsg")); } #[test] @@ -55,7 +55,7 @@ fn test_add_fee_tier_tick_spacing_zero() { }; let result = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); - assert!(result.contains("error executing WasmMsg")); + assert!(result.to_string().contains("error executing WasmMsg")); } #[test] diff --git a/contracts/oraiswap-v3/src/tests/admin.rs b/contracts/oraiswap-v3/src/tests/admin.rs index 2549961..03bf34f 100644 --- a/contracts/oraiswap-v3/src/tests/admin.rs +++ b/contracts/oraiswap-v3/src/tests/admin.rs @@ -47,5 +47,5 @@ fn test_change_admin_not_admin() { ) .unwrap_err(); - assert!(result.contains("error executing WasmMsg")); + assert!(result.to_string().contains("error executing WasmMsg")); } diff --git a/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs b/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs index 8720be6..025eda0 100644 --- a/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs +++ b/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs @@ -67,5 +67,5 @@ fn test_not_admin_change_fee_reciever() { let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier.clone()).unwrap(); let result = change_fee_receiver!(app, dex, pool_key, "bob", "bob").unwrap_err(); - assert!(result.contains("error executing WasmMsg")); + assert!(result.to_string().contains("error executing WasmMsg")); } diff --git a/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs b/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs index 9ddb4f6..57084af 100644 --- a/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs +++ b/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs @@ -46,5 +46,5 @@ fn test_change_protocol_fee_not_admin() { ) .unwrap_err(); - assert!(result.contains("error executing WasmMsg")); + assert!(result.to_string().contains("error executing WasmMsg")); } diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index abe89b2..eebed45 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -46,6 +46,21 @@ impl MockApp { ) } + pub fn add_fee_tier_string( + &mut self, + sender: String, + dex: String, + fee_tier: FeeTier, + ) -> Result { + println!("in add fee tier string"); + self.execute( + Addr::unchecked(sender), + Addr::unchecked(dex), + &msg::ExecuteMsg::AddFeeTier { fee_tier }, + &[], + ) + } + pub fn add_fee_tier( &mut self, sender: &str, @@ -530,6 +545,13 @@ pub mod macros { } pub(crate) use add_fee_tier; + macro_rules! add_fee_tier_string { + ($app:ident, $dex_address:expr, $fee_tier:expr, $caller:expr) => {{ + $app.add_fee_tier_string($caller, $dex_address, $fee_tier) + }}; + } + pub(crate) use add_fee_tier_string; + macro_rules! remove_fee_tier { ($app:ident, $dex_address:expr, $fee_tier:expr, $caller:tt) => {{ $app.remove_fee_tier($caller, $dex_address.as_str(), $fee_tier) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index 13e594e..f19c62d 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -110,6 +110,53 @@ pub fn test_create_incentive() { ] ); + // create incentive with no total reward -> fallback to max:u128 + let latest_timestamp_time = app.app.block_info().time.seconds(); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + None, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!( + pool.incentives, + vec![ + IncentiveRecord { + id: 0, + reward_per_sec, + reward_token: reward_token.clone(), + remaining: total_reward.unwrap(), + start_timestamp: current_time, + incentive_growth_global: FeeGrowth(0), + last_updated: latest_timestamp_time + }, + IncentiveRecord { + id: 1, + reward_per_sec, + reward_token: reward_token.clone(), + remaining: total_reward.unwrap(), + start_timestamp: new_timestamp_time, + incentive_growth_global: FeeGrowth(0), + last_updated: latest_timestamp_time + }, + IncentiveRecord { + id: 2, + reward_per_sec, + reward_token: reward_token.clone(), + remaining: TokenAmount(u128::MAX), + start_timestamp: latest_timestamp_time, + incentive_growth_global: FeeGrowth(0), + last_updated: latest_timestamp_time + } + ] + ); + // create fail, unauthorized let res = create_incentive!( app, From 1475dab624faced57719f015d06ba38bb2b4a3a9 Mon Sep 17 00:00:00 2001 From: Pham Tu Date: Mon, 22 Jul 2024 10:30:47 +0700 Subject: [PATCH 27/47] update version --- Cargo.lock | 943 +++++++----------- Cargo.toml | 13 +- contracts/oraiswap-v3/Cargo.toml | 4 +- contracts/oraiswap-v3/src/contract.rs | 60 +- contracts/oraiswap-v3/src/error.rs | 2 +- contracts/oraiswap-v3/src/interface.rs | 8 +- .../oraiswap-v3/src/tests/add_fee_tier.rs | 30 +- .../src/tests/change_fee_receiver.rs | 13 +- .../src/tests/change_protocol_fee.rs | 7 +- contracts/oraiswap-v3/src/tests/helper.rs | 65 +- contracts/oraiswap-v3/src/tests/nft.rs | 2 +- 11 files changed, 463 insertions(+), 684 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9fb8b54..4adf093 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,6 +34,12 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "autocfg" version = "1.3.0" @@ -51,16 +57,10 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.1", + "object", "rustc-demangle", ] -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - [[package]] name = "base16ct" version = "0.2.0" @@ -69,9 +69,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.13.1" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -85,6 +85,12 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "bitflags" version = "1.3.2" @@ -127,6 +133,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bnum" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" + [[package]] name = "bumpalo" version = "3.16.0" @@ -181,9 +193,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clru" -version = "0.4.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "591ff76ca0691bd91c1b0b5b987e5cf93b21ec810ad96665c5a569c60846dd93" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" [[package]] name = "const-oid" @@ -212,14 +224,14 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.5.2" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6aa9f904de106fa16443ad14ec2abe75e94ba003bb61c681c0e43d4c58d2a" +checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" dependencies = [ "digest 0.10.7", - "ecdsa 0.16.9", + "ecdsa", "ed25519-zebra", - "k256 0.13.3", + "k256", "rand_core 0.6.4", "thiserror", ] @@ -235,9 +247,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema" -version = "1.2.8" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0864db0a1e0ba2abd35d1105d0487e779538f616daa0338697315cc1601bf24" +checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -248,9 +260,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.2.8" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd0f686ff907612ed63fdff97906b3eafe169d560ebd428e92ef400fb56479f" +checksum = "0bb57855fbfc83327f8445ae0d413b1a05ac0d68c396ab4d122b2abd7bb82cb6" dependencies = [ "proc-macro2", "quote", @@ -259,11 +271,13 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.2.8" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197ed654c41885e2d76b23bff8db11b0f9745bfdede0909de9daa564edb19187" +checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ "base64", + "bech32 0.9.1", + "bnum", "cosmwasm-crypto", "cosmwasm-derive", "derivative", @@ -273,15 +287,15 @@ dependencies = [ "serde", "serde-json-wasm", "sha2 0.10.8", + "static_assertions", "thiserror", - "uint", ] [[package]] name = "cosmwasm-storage" -version = "1.2.8" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a2997bbb57c24c7ca9f745799c8839c08b7cde0be3f6c43127d25a7f03f2fe" +checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" dependencies = [ "cosmwasm-std", "serde", @@ -290,9 +304,10 @@ dependencies = [ [[package]] name = "cosmwasm-testing-util" version = "0.1.0" -source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=0c9c4d82719ab8e0b51192858c7744a77c5cf0b1#0c9c4d82719ab8e0b51192858c7744a77c5cf0b1" +source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=33a262f#33a262f3aeca4b46ada3213a5e60edb0585418ad" dependencies = [ - "bech32", + "anyhow", + "bech32 0.9.1", "cosmwasm-crypto", "cosmwasm-schema", "cosmwasm-std", @@ -307,19 +322,20 @@ dependencies = [ [[package]] name = "cosmwasm-vm" -version = "1.2.8" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613a3a96581b476b0b0a2fead0c970f9e8c844b7aa41bc45648ebcaa84d6b8ab" +checksum = "9897b46059d68ade608fbdcec33e02b0de0ca4b32ee787a83b8a3eb31b754c85" dependencies = [ "bitflags 1.3.2", "bytecheck", + "bytes", "clru", "cosmwasm-crypto", "cosmwasm-std", + "crc32fast", + "derivative", "enumset", "hex", - "loupe", - "parity-wasm", "schemars", "serde", "serde_json", @@ -340,56 +356,74 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ + "arrayvec", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", + "cranelift-egraph", "cranelift-entity", + "cranelift-isle", "gimli 0.26.2", "log", - "regalloc", + "regalloc2", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap", + "log", + "smallvec", +] [[package]] name = "cranelift-entity" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" [[package]] name = "cranelift-frontend" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" dependencies = [ "cranelift-codegen", "log", @@ -397,6 +431,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cranelift-isle" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" + [[package]] name = "crc32fast" version = "1.4.2" @@ -425,6 +465,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -437,18 +486,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-bigint" version = "0.5.5" @@ -486,69 +523,44 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.16.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a9d62dba95ab262438dfd403bffdca647c6615ef1aa431cdc94c262b09643a" +checksum = "91fc33b1d65c102d72f46548c64dca423c337e528d6747d0c595316aa65f887b" dependencies = [ "anyhow", + "bech32 0.11.0", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", + "cw-storage-plus", + "cw-utils", "derivative", - "itertools 0.10.5", - "k256 0.11.6", + "itertools 0.13.0", "prost", "schemars", "serde", + "sha2 0.10.8", "thiserror", ] [[package]] name = "cw-storage-plus" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-storage-plus" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-utils" -version = "0.16.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6a84c6c1c0acc3616398eba50783934bd6c964bad6974241eaee3460c8f5b26" +checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" dependencies = [ - "cosmwasm-schema", "cosmwasm-std", - "cw2 0.16.0", "schemars", - "semver", "serde", - "thiserror", ] [[package]] name = "cw-utils" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" +checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2 1.1.0", + "cw2", "schemars", "semver", "serde", @@ -557,27 +569,15 @@ dependencies = [ [[package]] name = "cw2" -version = "0.16.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91398113b806f4d2a8d5f8d05684704a20ffd5968bf87e3473e1973710b884ad" +checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 0.16.0", - "schemars", - "serde", -] - -[[package]] -name = "cw2" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus 1.1.0", + "cw-storage-plus", "schemars", + "semver", "serde", "thiserror", ] @@ -590,7 +590,7 @@ checksum = "011c45920f8200bd5d32d4fe52502506f64f2f75651ab408054d4cfc75ca3a9b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils 1.0.1", + "cw-utils", "schemars", "serde", ] @@ -603,9 +603,9 @@ checksum = "0b3ad456059901a36cfa68b596d85d579c3df2b797dae9950dc34c27e14e995f" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.1.0", + "cw-storage-plus", + "cw-utils", + "cw2", "cw20", "schemars", "semver", @@ -647,6 +647,19 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "decimal" version = "0.1.0" @@ -667,16 +680,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - [[package]] name = "der" version = "0.7.9" @@ -761,19 +764,7 @@ checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2", -] - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", + "memmap2 0.5.10", ] [[package]] @@ -782,12 +773,12 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.9", + "der", "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.3", + "elliptic-curve", + "rfc6979", + "signature", + "spki", ] [[package]] @@ -811,41 +802,21 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] - [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", + "base16ct", + "crypto-bigint", "digest 0.10.7", - "ff 0.13.0", + "ff", "generic-array", - "group 0.13.0", - "pkcs8 0.10.2", + "group", + "pkcs8", "rand_core 0.6.4", - "sec1 0.7.3", + "sec1", "subtle", "zeroize", ] @@ -891,38 +862,12 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "ff" version = "0.13.0" @@ -939,6 +884,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "forward_ref" version = "1.0.0" @@ -951,6 +905,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1003,45 +966,31 @@ dependencies = [ "web-sys", ] -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff 0.13.0", + "ff", "rand_core 0.6.4", "subtle", ] [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hex" @@ -1058,21 +1007,22 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1081,7 +1031,6 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde", ] [[package]] @@ -1095,18 +1044,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -1128,28 +1077,16 @@ dependencies = [ [[package]] name = "k256" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" -dependencies = [ - "cfg-if", - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.8", -] - -[[package]] -name = "k256" -version = "0.13.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", + "ecdsa", + "elliptic-curve", "once_cell", "sha2 0.10.8", - "signature 2.2.0", + "signature", ] [[package]] @@ -1171,48 +1108,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] -name = "libloading" -version = "0.7.4" +name = "lock_api" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "cfg-if", - "winapi", + "autocfg", + "scopeguard", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "loupe" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" -dependencies = [ - "indexmap", - "loupe-derive", - "rustversion", -] - -[[package]] -name = "loupe-derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "mach" version = "0.3.2" @@ -1246,11 +1156,20 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" -version = "0.6.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -1279,18 +1198,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "object" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" -dependencies = [ - "crc32fast", - "hashbrown 0.11.2", - "indexmap", - "memchr", -] - [[package]] name = "object" version = "0.36.1" @@ -1320,10 +1227,8 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "cosmwasm-testing-util", - "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 0.16.0", - "cw2 1.1.0", + "cw-storage-plus", + "cw2", "cw20", "cw20-base", "decimal", @@ -1340,17 +1245,24 @@ dependencies = [ "js-sys", "paste", "serde", - "serde-wasm-bindgen", + "serde-wasm-bindgen 0.6.5", "traceable_result", "tsify", "wasm-bindgen", ] [[package]] -name = "parity-wasm" -version = "0.42.2" +name = "parking_lot_core" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] [[package]] name = "paste" @@ -1359,20 +1271,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "percent-encoding" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] -name = "pkcs8" -version = "0.9.0" +name = "pin-project-lite" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pkcs8" @@ -1380,8 +1288,8 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.9", - "spki 0.7.3", + "der", + "spki", ] [[package]] @@ -1419,9 +1327,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.9.0" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -1429,15 +1337,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.9.0" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -1511,13 +1419,23 @@ dependencies = [ ] [[package]] -name = "regalloc" -version = "0.0.34" +name = "redox_syscall" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regalloc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" +dependencies = [ + "fxhash", "log", - "rustc-hash", + "slice-group-by", "smallvec", ] @@ -1567,17 +1485,6 @@ dependencies = [ "bytecheck", ] -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac", - "zeroize", -] - [[package]] name = "rfc6979" version = "0.4.0" @@ -1598,6 +1505,7 @@ dependencies = [ "bytecheck", "bytes", "hashbrown 0.12.3", + "indexmap", "ptr_meta", "rend", "rkyv_derive", @@ -1623,12 +1531,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc_version" version = "0.4.0" @@ -1638,25 +1540,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - [[package]] name = "ryu" version = "1.0.18" @@ -1701,31 +1584,23 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "sec1" -version = "0.3.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", + "base16ct", + "der", "generic-array", - "pkcs8 0.9.0", + "pkcs8", "subtle", "zeroize", ] [[package]] -name = "sec1" -version = "0.7.3" +name = "self_cell" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct 0.2.0", - "der 0.7.9", - "generic-array", - "pkcs8 0.10.2", - "subtle", - "zeroize", -] +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "semver" @@ -1753,9 +1628,9 @@ dependencies = [ [[package]] name = "serde-wasm-bindgen" -version = "0.6.5" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" dependencies = [ "js-sys", "serde", @@ -1763,12 +1638,14 @@ dependencies = [ ] [[package]] -name = "serde_bytes" -version = "0.11.15" +name = "serde-wasm-bindgen" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" dependencies = [ + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -1840,13 +1717,13 @@ dependencies = [ ] [[package]] -name = "signature" -version = "1.6.4" +name = "shared-buffer" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", + "bytes", + "memmap2 0.6.2", ] [[package]] @@ -1866,20 +1743,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] -name = "smallvec" -version = "1.13.2" +name = "slice-group-by" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] -name = "spki" -version = "0.6.0" +name = "smallvec" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spki" @@ -1888,7 +1761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.9", + "der", ] [[package]] @@ -1943,18 +1816,6 @@ version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - [[package]] name = "thiserror" version = "1.0.61" @@ -1993,7 +1854,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "token-bindings" version = "0.11.0" -source = "git+https://github.com/oraichain/token-bindings.git?rev=d379675#d3796751981e64da4b6917090c500a45bf6c072f" +source = "git+https://github.com/oraichain/token-bindings.git?rev=7861576#78615761c7c0eb8ff8ebe64e26f70d20fec5b4e2" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2004,12 +1865,12 @@ dependencies = [ [[package]] name = "token-bindings-test" version = "0.11.0" -source = "git+https://github.com/oraichain/token-bindings.git?rev=d379675#d3796751981e64da4b6917090c500a45bf6c072f" +source = "git+https://github.com/oraichain/token-bindings.git?rev=7861576#78615761c7c0eb8ff8ebe64e26f70d20fec5b4e2" dependencies = [ "anyhow", "cosmwasm-std", "cw-multi-test", - "cw-storage-plus 0.16.0", + "cw-storage-plus", "itertools 0.11.0", "schemars", "serde", @@ -2020,13 +1881,13 @@ dependencies = [ [[package]] name = "tokenfactory" version = "0.11.0" -source = "git+https://github.com/oraichain/token-bindings.git?rev=d379675#d3796751981e64da4b6917090c500a45bf6c072f" +source = "git+https://github.com/oraichain/token-bindings.git?rev=7861576#78615761c7c0eb8ff8ebe64e26f70d20fec5b4e2" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cosmwasm-storage", - "cw-storage-plus 0.16.0", - "cw2 1.1.0", + "cw-storage-plus", + "cw2", "schemars", "serde", "thiserror", @@ -2046,7 +1907,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2115,12 +1975,38 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.10.0" @@ -2164,6 +2050,29 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-downcast" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" +dependencies = [ + "js-sys", + "once_cell", + "wasm-bindgen", + "wasm-bindgen-downcast-macros", +] + +[[package]] +name = "wasm-bindgen-downcast-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.92" @@ -2195,73 +2104,70 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasmer" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8d8361c9d006ea3d7797de7bd6b1492ffd0f91a22430cfda6c1658ad57bedf" +checksum = "0e626f958755a90a6552b9528f59b58a62ae288e6c17fcf40e99495bc33c60f0" dependencies = [ + "bytes", "cfg-if", + "derivative", "indexmap", "js-sys", - "loupe", "more-asserts", + "rustc-demangle", + "serde", + "serde-wasm-bindgen 0.4.5", + "shared-buffer", "target-lexicon", "thiserror", "wasm-bindgen", - "wasmer-artifact", + "wasm-bindgen-downcast", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", "wasmer-derive", - "wasmer-engine", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-types", "wasmer-vm", "winapi", ] -[[package]] -name = "wasmer-artifact" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aaf9428c29c1d8ad2ac0e45889ba8a568a835e33fd058964e5e500f2f7ce325" -dependencies = [ - "enumset", - "loupe", - "thiserror", - "wasmer-compiler", - "wasmer-types", -] - [[package]] name = "wasmer-compiler" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67a6cd866aed456656db2cfea96c18baabbd33f676578482b85c51e1ee19d2c" +checksum = "848e1922694cf97f4df680a0534c9d72c836378b5eb2313c1708fe1a75b40044" dependencies = [ + "backtrace", + "bytes", + "cfg-if", + "enum-iterator", "enumset", - "loupe", + "lazy_static", + "leb128", + "memmap2 0.5.10", + "more-asserts", + "region", "rkyv", - "serde", - "serde_bytes", + "self_cell", + "shared-buffer", "smallvec", - "target-lexicon", "thiserror", "wasmer-types", + "wasmer-vm", "wasmparser", + "winapi", ] [[package]] name = "wasmer-compiler-cranelift" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48be2f9f6495f08649e4f8b946a2cbbe119faf5a654aa1457f9504a99d23dae0" +checksum = "3d96bce6fad15a954edcfc2749b59e47ea7de524b6ef3df392035636491a40b4" dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", "gimli 0.26.2", - "loupe", "more-asserts", "rayon", "smallvec", @@ -2273,16 +2179,16 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ca2a35204d8befa85062bc7aac259a8db8070b801b8a783770ba58231d729e" +checksum = "ebaa865b40ffb3351b03dab9fe9930a5248c25daebd55b464b79b862d9b55ccd" dependencies = [ "byteorder", "dynasm", "dynasmrt", + "enumset", "gimli 0.26.2", "lazy_static", - "loupe", "more-asserts", "rayon", "smallvec", @@ -2292,9 +2198,9 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e50405cc2a2f74ff574584710a5f2c1d5c93744acce2ca0866084739284b51" +checksum = "7f08f80d166a9279671b7af7a09409c28ede2e0b4e3acabbf0e3cb22c8038ba7" dependencies = [ "proc-macro-error", "proc-macro2", @@ -2302,164 +2208,70 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "wasmer-engine" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f98f010978c244db431b392aeab0661df7ea0822343334f8f2a920763548e45" -dependencies = [ - "backtrace", - "enumset", - "lazy_static", - "loupe", - "memmap2", - "more-asserts", - "rustc-demangle", - "serde", - "serde_bytes", - "target-lexicon", - "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", - "wasmer-vm", -] - -[[package]] -name = "wasmer-engine-dylib" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0358af9c154724587731175553805648d9acb8f6657880d165e378672b7e53" -dependencies = [ - "cfg-if", - "enum-iterator", - "enumset", - "leb128", - "libloading", - "loupe", - "object 0.28.4", - "rkyv", - "serde", - "tempfile", - "tracing", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-engine", - "wasmer-object", - "wasmer-types", - "wasmer-vm", - "which", -] - -[[package]] -name = "wasmer-engine-universal" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "440dc3d93c9ca47865a4f4edd037ea81bf983b5796b59b3d712d844b32dbef15" -dependencies = [ - "cfg-if", - "enumset", - "leb128", - "loupe", - "region", - "rkyv", - "wasmer-compiler", - "wasmer-engine", - "wasmer-engine-universal-artifact", - "wasmer-types", - "wasmer-vm", - "winapi", -] - -[[package]] -name = "wasmer-engine-universal-artifact" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f1db3f54152657eb6e86c44b66525ff7801dad8328fe677da48dd06af9ad41" -dependencies = [ - "enum-iterator", - "enumset", - "loupe", - "rkyv", - "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", -] - [[package]] name = "wasmer-middlewares" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7812438ed2f37203a37007cdb5332b8475cb2b16e15d51299b2647894e9ed3a" +checksum = "eeb4b87c0ea9f8636c81a8ab8f52bad01c8623c9fcbb3db5f367d5f157fada30" dependencies = [ - "loupe", "wasmer", "wasmer-types", "wasmer-vm", ] -[[package]] -name = "wasmer-object" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d831335ff3a44ecf451303f6f891175c642488036b92ceceb24ac8623a8fa8b" -dependencies = [ - "object 0.28.4", - "thiserror", - "wasmer-compiler", - "wasmer-types", -] - [[package]] name = "wasmer-types" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39df01ea05dc0a9bab67e054c7cb01521e53b35a7bb90bd02eca564ed0b2667f" +checksum = "ae2c892882f0b416783fb4310e5697f5c30587f6f9555f9d4f2be85ab39d5d3d" dependencies = [ - "backtrace", + "bytecheck", "enum-iterator", + "enumset", "indexmap", - "loupe", "more-asserts", "rkyv", - "serde", + "target-lexicon", "thiserror", ] [[package]] name = "wasmer-vm" -version = "2.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d965fa61f4dc4cdb35a54daaf7ecec3563fbb94154a6c35433f879466247dd" +checksum = "7c0a9a57b627fb39e5a491058d4365f099bc9b140031c000fded24a3306d9480" dependencies = [ "backtrace", "cc", "cfg-if", "corosensei", + "crossbeam-queue", + "dashmap", + "derivative", "enum-iterator", + "fnv", "indexmap", "lazy_static", "libc", - "loupe", "mach", "memoffset", "more-asserts", "region", - "rkyv", "scopeguard", - "serde", "thiserror", - "wasmer-artifact", "wasmer-types", "winapi", ] [[package]] name = "wasmparser" -version = "0.83.0" +version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" +checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" +dependencies = [ + "indexmap", + "url", +] [[package]] name = "web-sys" @@ -2471,18 +2283,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2635,8 +2435,3 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" - -[[patch.unused]] -name = "curve25519-dalek" -version = "4.1.3" -source = "git+https://github.com/dalek-cryptography/curve25519-dalek.git#5b7082bbc8e0b2106ab0d956064f61fa0f393cdc" diff --git a/Cargo.toml b/Cargo.toml index 6890643..37b7f1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,10 +19,10 @@ exclude = [ ] [workspace.dependencies] -cosmwasm-std = { version = "=1.2" } -cosmwasm-schema = { version = "=1.2" } -cosmwasm-storage = { version = "=1.2" } -cosmwasm-vm = { version = "=1.2" } +cosmwasm-std = { version = "1.5" } +cosmwasm-schema = { version = "1.5" } +cosmwasm-storage = { version = "1.5" } +cosmwasm-vm = { version = "1.5" } thiserror = "1.0.26" @@ -30,8 +30,6 @@ cw2 = { version = "1.0.1" } cw20 = { version = "1.0.1" } cw20-base = { version = "1.0.1" } cw-storage-plus = { version = "1.0.1" } -cw-multi-test = "0.16.6" -cw-utils = "0.16.0" derive_more = "0.99.17" decimal-core = { path = "./packages/decimal-core" } decimal = { path = "./packages/decimal" } @@ -46,6 +44,3 @@ rpath = false lto = true overflow-checks = true panic = 'abort' - -[patch.crates-io] -curve25519-dalek = { git = 'https://github.com/dalek-cryptography/curve25519-dalek.git' } diff --git a/contracts/oraiswap-v3/Cargo.toml b/contracts/oraiswap-v3/Cargo.toml index b849436..db270a3 100644 --- a/contracts/oraiswap-v3/Cargo.toml +++ b/contracts/oraiswap-v3/Cargo.toml @@ -25,12 +25,10 @@ cosmwasm-storage = { workspace = true } cw-storage-plus = { workspace = true } cw2 = { workspace = true } cw20 = { workspace = true } -cw-utils = { workspace = true } thiserror = { workspace = true } decimal = { workspace = true } derive_more = { workspace = true } [dev-dependencies] -cw-multi-test = { workspace = true } cw20-base = { workspace = true, features = ["library"] } -cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "0c9c4d82719ab8e0b51192858c7744a77c5cf0b1" } +cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "33a262f" } diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index db5510b..10a6398 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -6,7 +6,7 @@ use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; use crate::state::CONFIG; use crate::{entrypoints::*, Config}; -use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; use cw2::set_contract_version; // version info for migration info @@ -190,38 +190,42 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::Admin {} => to_binary(&query_admin(deps)?), - QueryMsg::ProtocolFee {} => to_binary(&get_protocol_fee(deps)?), - QueryMsg::Position { owner_id, index } => to_binary(&get_position(deps, owner_id, index)?), + QueryMsg::Admin {} => to_json_binary(&query_admin(deps)?), + QueryMsg::ProtocolFee {} => to_json_binary(&get_protocol_fee(deps)?), + QueryMsg::Position { owner_id, index } => { + to_json_binary(&get_position(deps, owner_id, index)?) + } QueryMsg::Positions { owner_id, limit, offset, - } => to_binary(&get_positions(deps, owner_id, limit, offset)?), - QueryMsg::FeeTierExist { fee_tier } => to_binary(&fee_tier_exist(deps, fee_tier)?), + } => to_json_binary(&get_positions(deps, owner_id, limit, offset)?), + QueryMsg::FeeTierExist { fee_tier } => to_json_binary(&fee_tier_exist(deps, fee_tier)?), QueryMsg::Pool { token_0, token_1, fee_tier, - } => to_binary(&get_pool(deps, token_0, token_1, fee_tier)?), - QueryMsg::Pools { limit, start_after } => to_binary(&get_pools(deps, limit, start_after)?), - QueryMsg::Tick { key, index } => to_binary(&get_tick(deps, key, index)?), + } => to_json_binary(&get_pool(deps, token_0, token_1, fee_tier)?), + QueryMsg::Pools { limit, start_after } => { + to_json_binary(&get_pools(deps, limit, start_after)?) + } + QueryMsg::Tick { key, index } => to_json_binary(&get_tick(deps, key, index)?), QueryMsg::IsTickInitialized { key, index } => { - to_binary(&is_tick_initialized(deps, key, index)?) + to_json_binary(&is_tick_initialized(deps, key, index)?) } - QueryMsg::FeeTiers {} => to_binary(&get_fee_tiers(deps)?), + QueryMsg::FeeTiers {} => to_json_binary(&get_fee_tiers(deps)?), QueryMsg::PositionTicks { owner, offset } => { - to_binary(&get_position_ticks(deps, owner, offset)?) + to_json_binary(&get_position_ticks(deps, owner, offset)?) } QueryMsg::UserPositionAmount { owner } => { - to_binary(&get_user_position_amount(deps, owner)?) + to_json_binary(&get_user_position_amount(deps, owner)?) } QueryMsg::TickMap { pool_key, lower_tick_index, upper_tick_index, x_to_y, - } => to_binary(&get_tickmap( + } => to_json_binary(&get_tickmap( deps, pool_key, lower_tick_index, @@ -231,16 +235,16 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { QueryMsg::LiquidityTicks { pool_key, tick_indexes, - } => to_binary(&get_liquidity_ticks(deps, pool_key, tick_indexes)?), + } => to_json_binary(&get_liquidity_ticks(deps, pool_key, tick_indexes)?), QueryMsg::LiquidityTicksAmount { pool_key, lower_tick, upper_tick, - } => to_binary(&get_liquidity_ticks_amount( + } => to_json_binary(&get_liquidity_ticks_amount( deps, pool_key, lower_tick, upper_tick, )?), QueryMsg::PoolsForPair { token_0, token_1 } => { - to_binary(&get_all_pools_for_pair(deps, token_0, token_1)?) + to_json_binary(&get_all_pools_for_pair(deps, token_0, token_1)?) } QueryMsg::Quote { pool_key, @@ -248,7 +252,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { amount, by_amount_in, sqrt_price_limit, - } => to_binary("e( + } => to_json_binary("e( deps, env, pool_key, @@ -258,12 +262,12 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { sqrt_price_limit, )?), QueryMsg::QuoteRoute { amount_in, swaps } => { - to_binary("e_route(deps, env, amount_in, swaps)?) + to_json_binary("e_route(deps, env, amount_in, swaps)?) } QueryMsg::OwnerOf { token_id, include_expired, - } => to_binary(&query_owner_of( + } => to_json_binary(&query_owner_of( deps, env, token_id, @@ -274,7 +278,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { include_expired, start_after, limit, - } => to_binary(&query_all_approvals( + } => to_json_binary(&query_all_approvals( deps, env, owner, @@ -282,11 +286,11 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { start_after, limit, )?), - QueryMsg::NftInfo { token_id } => to_binary(&query_nft_info(deps, token_id)?), + QueryMsg::NftInfo { token_id } => to_json_binary(&query_nft_info(deps, token_id)?), QueryMsg::AllNftInfo { token_id, include_expired, - } => to_binary(&query_all_nft_info( + } => to_json_binary(&query_all_nft_info( deps, env, token_id, @@ -296,13 +300,13 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { owner, start_after, limit, - } => to_binary(&query_tokens(deps, owner, start_after, limit)?), + } => to_json_binary(&query_tokens(deps, owner, start_after, limit)?), QueryMsg::AllTokens { start_after, limit } => { - to_binary(&query_all_tokens(deps, start_after, limit)?) + to_json_binary(&query_all_tokens(deps, start_after, limit)?) } - QueryMsg::NumTokens {} => to_binary(&query_num_tokens(deps)?), + QueryMsg::NumTokens {} => to_json_binary(&query_num_tokens(deps)?), QueryMsg::PositionIncentives { owner_id, index } => { - to_binary(&query_position_incentives(deps, env, owner_id, index)?) + to_json_binary(&query_position_incentives(deps, env, owner_id, index)?) } } } @@ -310,7 +314,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { #[cfg_attr(not(feature = "library"), entry_point)] pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { let original_version = - cw_utils::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; // // query all position, then update token id // let positions: Vec<_> = crate::state::POSITIONS diff --git a/contracts/oraiswap-v3/src/error.rs b/contracts/oraiswap-v3/src/error.rs index bc0c9f9..d903b89 100644 --- a/contracts/oraiswap-v3/src/error.rs +++ b/contracts/oraiswap-v3/src/error.rs @@ -119,7 +119,7 @@ pub enum ContractError { #[error("Current Sqrt Price < Lower Sqrt Price")] CurrentSqrtPriceLess, - #[error("unauthorized")] + #[error("Unauthorized")] Unauthorized {}, #[error("Cannot set approval that is already expired")] diff --git a/contracts/oraiswap-v3/src/interface.rs b/contracts/oraiswap-v3/src/interface.rs index aec9095..80722e2 100644 --- a/contracts/oraiswap-v3/src/interface.rs +++ b/contracts/oraiswap-v3/src/interface.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::{ - to_binary, Addr, Api, BankMsg, Binary, Coin, CosmosMsg, MessageInfo, StdResult, Uint128, + to_json_binary, Addr, Api, BankMsg, Binary, Coin, CosmosMsg, MessageInfo, StdResult, Uint128, WasmMsg, }; use cw20::{Cw20ExecuteMsg, Expiration}; @@ -65,7 +65,7 @@ impl Asset { msgs.push( WasmMsg::Execute { contract_addr: contract_addr.to_string(), - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: info.sender.to_string(), amount: self.amount, })?, @@ -101,7 +101,7 @@ impl Asset { msgs.push( WasmMsg::Execute { contract_addr: contract_addr.to_string(), - msg: to_binary(&Cw20ExecuteMsg::TransferFrom { + msg: to_json_binary(&Cw20ExecuteMsg::TransferFrom { owner: info.sender.to_string(), recipient, amount: self.amount, @@ -220,7 +220,7 @@ impl Cw721ReceiveMsg { /// serializes the message pub fn into_binary(self) -> StdResult { let msg = ReceiverHandleMsg::ReceiveNft(self); - to_binary(&msg) + to_json_binary(&msg) } /// creates a cosmos_msg sending this struct to the named contract diff --git a/contracts/oraiswap-v3/src/tests/add_fee_tier.rs b/contracts/oraiswap-v3/src/tests/add_fee_tier.rs index c7a9b5b..081b620 100644 --- a/contracts/oraiswap-v3/src/tests/add_fee_tier.rs +++ b/contracts/oraiswap-v3/src/tests/add_fee_tier.rs @@ -2,6 +2,7 @@ use crate::math::types::percentage::Percentage; use crate::msg::QueryMsg; use crate::tests::helper::{macros::*, MockApp}; use crate::FeeTier; +use cw20_base::ContractError; use decimal::Decimal; #[test] @@ -30,8 +31,12 @@ fn test_add_fee_tier_not_admin() { let dex = create_dex!(app, Percentage::new(0)); let fee_tier = FeeTier::new(Percentage::new(1), 1).unwrap(); - let result = add_fee_tier!(app, dex, fee_tier, "bob").unwrap_err(); - assert!(result.to_string().contains("error executing WasmMsg")); + let error = add_fee_tier!(app, dex, fee_tier, "bob").unwrap_err(); + + assert!(error + .root_cause() + .to_string() + .contains(&ContractError::Unauthorized {}.to_string())); } #[test] @@ -53,9 +58,12 @@ fn test_add_fee_tier_tick_spacing_zero() { fee: Percentage::new(1), tick_spacing: 0, }; - let result = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); + let error = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); - assert!(result.to_string().contains("error executing WasmMsg")); + assert!(error + .root_cause() + .to_string() + .contains("error executing WasmMsg")); } #[test] @@ -67,9 +75,12 @@ fn test_add_fee_tier_over_upper_bound_tick_spacing() { fee: Percentage::new(1), tick_spacing: 101, }; - let result = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); + let error = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); - assert!(result.contains("error executing WasmMsg")); + assert!(error + .root_cause() + .to_string() + .contains("error executing WasmMsg")); } #[test] @@ -81,7 +92,10 @@ fn test_add_fee_tier_fee_above_limit() { fee: Percentage::new(1000000000000), tick_spacing: 10, }; - let result = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); + let error = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); - assert!(result.contains("error executing WasmMsg")); + assert!(error + .root_cause() + .to_string() + .contains("error executing WasmMsg")); } diff --git a/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs b/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs index 025eda0..722531f 100644 --- a/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs +++ b/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs @@ -31,7 +31,8 @@ fn test_change_fee_reciever() { ); assert!(result.is_ok()); - let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier.clone()).unwrap(); + let pool_key = + PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier.clone()).unwrap(); let result = change_fee_receiver!(app, dex, pool_key, "alice", "alice"); assert!(result.is_ok()); @@ -65,7 +66,11 @@ fn test_not_admin_change_fee_reciever() { ); assert!(result.is_ok()); - let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier.clone()).unwrap(); - let result = change_fee_receiver!(app, dex, pool_key, "bob", "bob").unwrap_err(); - assert!(result.to_string().contains("error executing WasmMsg")); + let pool_key = + PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier.clone()).unwrap(); + let error = change_fee_receiver!(app, dex, pool_key, "bob", "bob").unwrap_err(); + assert!(error + .root_cause() + .to_string() + .contains("error executing WasmMsg")); } diff --git a/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs b/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs index 57084af..c9cdefe 100644 --- a/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs +++ b/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs @@ -37,7 +37,7 @@ fn test_change_protocol_fee_not_admin() { let execute_msg = ExecuteMsg::ChangeProtocolFee { protocol_fee: Percentage::new(1), }; - let result = app + let error = app .execute( Addr::unchecked("bob"), Addr::unchecked(dex.clone()), @@ -46,5 +46,8 @@ fn test_change_protocol_fee_not_admin() { ) .unwrap_err(); - assert!(result.to_string().contains("error executing WasmMsg")); + assert!(error + .root_cause() + .to_string() + .contains("error executing WasmMsg")); } diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index eebed45..6efc4cf 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{Addr, Coin, Event, StdResult, Timestamp}; -use cw_multi_test::{AppResponse, ContractWrapper}; +use cosmwasm_testing_util::{AppResponse, ContractWrapper, MockResult}; use crate::{ interface::{Asset, AssetInfo, PoolWithPoolKey, QuoteResult, SwapHop}, @@ -35,7 +35,7 @@ impl MockApp { Self { app, dex_id } } - pub fn create_dex(&mut self, owner: &str, protocol_fee: Percentage) -> Result { + pub fn create_dex(&mut self, owner: &str, protocol_fee: Percentage) -> MockResult { let code_id = self.dex_id; self.instantiate( code_id, @@ -46,27 +46,12 @@ impl MockApp { ) } - pub fn add_fee_tier_string( - &mut self, - sender: String, - dex: String, - fee_tier: FeeTier, - ) -> Result { - println!("in add fee tier string"); - self.execute( - Addr::unchecked(sender), - Addr::unchecked(dex), - &msg::ExecuteMsg::AddFeeTier { fee_tier }, - &[], - ) - } - pub fn add_fee_tier( &mut self, sender: &str, dex: &str, fee_tier: FeeTier, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -80,7 +65,7 @@ impl MockApp { sender: &str, dex: &str, fee_tier: FeeTier, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -98,7 +83,7 @@ impl MockApp { fee_tier: FeeTier, init_sqrt_price: SqrtPrice, init_tick: i32, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -118,7 +103,7 @@ impl MockApp { sender: &str, dex: &str, pool_key: &PoolKey, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -135,7 +120,7 @@ impl MockApp { dex: &str, pool_key: &PoolKey, fee_recevier: &str, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -157,7 +142,7 @@ impl MockApp { liquidity_delta: Liquidity, slippage_limit_lower: SqrtPrice, slippage_limit_upper: SqrtPrice, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -179,7 +164,7 @@ impl MockApp { dex: &str, index: u32, receiver: &str, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -196,7 +181,7 @@ impl MockApp { sender: &str, dex: &str, index: u32, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -213,7 +198,7 @@ impl MockApp { expected_amount_out: TokenAmount, slippage: Percentage, swaps: Vec, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -236,7 +221,7 @@ impl MockApp { amount: TokenAmount, by_amount_in: bool, sqrt_price_limit: SqrtPrice, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -251,12 +236,7 @@ impl MockApp { ) } - pub fn claim_fee( - &mut self, - sender: &str, - dex: &str, - index: u32, - ) -> Result { + pub fn claim_fee(&mut self, sender: &str, dex: &str, index: u32) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -270,7 +250,7 @@ impl MockApp { sender: &str, dex: &str, index: u32, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -424,14 +404,6 @@ impl MockApp { ) } - pub fn assert_fail(&self, res: Result) { - // new version of cosmwasm does not return detail error - match res.err() { - Some(msg) => assert!(msg.contains("error executing WasmMsg")), - None => panic!("Must return generic error"), - } - } - pub fn create_incentive( &mut self, sender: &str, @@ -441,7 +413,7 @@ impl MockApp { total_reward: Option, reward_per_sec: TokenAmount, start_timestamp: Option, - ) -> Result { + ) -> MockResult { self.execute( Addr::unchecked(sender), Addr::unchecked(dex), @@ -545,13 +517,6 @@ pub mod macros { } pub(crate) use add_fee_tier; - macro_rules! add_fee_tier_string { - ($app:ident, $dex_address:expr, $fee_tier:expr, $caller:expr) => {{ - $app.add_fee_tier_string($caller, $dex_address, $fee_tier) - }}; - } - pub(crate) use add_fee_tier_string; - macro_rules! remove_fee_tier { ($app:ident, $dex_address:expr, $fee_tier:expr, $caller:tt) => {{ $app.remove_fee_tier($caller, $dex_address.as_str(), $fee_tier) diff --git a/contracts/oraiswap-v3/src/tests/nft.rs b/contracts/oraiswap-v3/src/tests/nft.rs index 41fe0f8..f1543bc 100644 --- a/contracts/oraiswap-v3/src/tests/nft.rs +++ b/contracts/oraiswap-v3/src/tests/nft.rs @@ -1192,7 +1192,7 @@ fn test_approving_revoking() { wasm_event.attributes, vec![ Attribute { - key: "_contract_addr".to_string(), + key: "_contract_address".to_string(), value: dex.to_string() }, attr("action", "approve"), From 529c4e9f2650cc139d085e4f627f702c5f85af85 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Mon, 22 Jul 2024 10:42:53 +0700 Subject: [PATCH 28/47] chore: update incentive test case by new testing version --- contracts/oraiswap-v3/src/tests/incentive.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index f19c62d..ba3a44d 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Addr, Timestamp, Uint128}; +use cosmwasm_std::{Addr, StdError, Timestamp, Uint128}; use decimal::*; use crate::{ @@ -10,7 +10,7 @@ use crate::{ sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, MAX_SQRT_PRICE, MIN_SQRT_PRICE, + ContractError, FeeTier, PoolKey, MAX_SQRT_PRICE, MIN_SQRT_PRICE, }; #[test] @@ -158,7 +158,7 @@ pub fn test_create_incentive() { ); // create fail, unauthorized - let res = create_incentive!( + let error = create_incentive!( app, dex, pool_key, @@ -167,8 +167,12 @@ pub fn test_create_incentive() { reward_per_sec, start_timestamp, "bob" - ); - assert!(res.is_err()); + ) + .unwrap_err(); + assert!(error + .root_cause() + .to_string() + .contains(&ContractError::Unauthorized {}.to_string())); } #[test] From cf6676e6d6e46f853ef1ada8e58f1a107fdd9888 Mon Sep 17 00:00:00 2001 From: Pham Tu Date: Mon, 22 Jul 2024 10:43:02 +0700 Subject: [PATCH 29/47] fix testcase --- .../oraiswap-v3/src/tests/add_fee_tier.rs | 34 +++++++++---------- contracts/oraiswap-v3/src/tests/admin.rs | 8 +++-- .../src/tests/change_fee_receiver.rs | 10 +++--- .../src/tests/change_protocol_fee.rs | 9 ++--- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/contracts/oraiswap-v3/src/tests/add_fee_tier.rs b/contracts/oraiswap-v3/src/tests/add_fee_tier.rs index 081b620..86b17c2 100644 --- a/contracts/oraiswap-v3/src/tests/add_fee_tier.rs +++ b/contracts/oraiswap-v3/src/tests/add_fee_tier.rs @@ -1,8 +1,8 @@ use crate::math::types::percentage::Percentage; use crate::msg::QueryMsg; use crate::tests::helper::{macros::*, MockApp}; +use crate::ContractError; use crate::FeeTier; -use cw20_base::ContractError; use decimal::Decimal; #[test] @@ -33,10 +33,10 @@ fn test_add_fee_tier_not_admin() { let fee_tier = FeeTier::new(Percentage::new(1), 1).unwrap(); let error = add_fee_tier!(app, dex, fee_tier, "bob").unwrap_err(); - assert!(error - .root_cause() - .to_string() - .contains(&ContractError::Unauthorized {}.to_string())); + assert_eq!( + error.root_cause().to_string(), + ContractError::Unauthorized {}.to_string() + ); } #[test] @@ -60,10 +60,10 @@ fn test_add_fee_tier_tick_spacing_zero() { }; let error = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); - assert!(error - .root_cause() - .to_string() - .contains("error executing WasmMsg")); + assert_eq!( + error.root_cause().to_string(), + ContractError::InvalidTickSpacing {}.to_string() + ); } #[test] @@ -77,10 +77,10 @@ fn test_add_fee_tier_over_upper_bound_tick_spacing() { }; let error = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); - assert!(error - .root_cause() - .to_string() - .contains("error executing WasmMsg")); + assert_eq!( + error.root_cause().to_string(), + ContractError::InvalidTickSpacing {}.to_string() + ); } #[test] @@ -94,8 +94,8 @@ fn test_add_fee_tier_fee_above_limit() { }; let error = add_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); - assert!(error - .root_cause() - .to_string() - .contains("error executing WasmMsg")); + assert_eq!( + error.root_cause().to_string(), + ContractError::InvalidFee {}.to_string() + ); } diff --git a/contracts/oraiswap-v3/src/tests/admin.rs b/contracts/oraiswap-v3/src/tests/admin.rs index 03bf34f..90d7fbc 100644 --- a/contracts/oraiswap-v3/src/tests/admin.rs +++ b/contracts/oraiswap-v3/src/tests/admin.rs @@ -2,6 +2,7 @@ use crate::msg::{ExecuteMsg, QueryMsg}; use crate::percentage::Percentage; use crate::tests::helper::macros::*; use crate::tests::helper::MockApp; +use crate::ContractError; use cosmwasm_std::Addr; use decimal::Decimal; @@ -38,7 +39,7 @@ fn test_change_admin_not_admin() { let execute_msg = ExecuteMsg::ChangeAdmin { new_admin: Addr::unchecked("bob"), }; - let result = app + let error = app .execute( Addr::unchecked("bob"), Addr::unchecked(dex.clone()), @@ -47,5 +48,8 @@ fn test_change_admin_not_admin() { ) .unwrap_err(); - assert!(result.to_string().contains("error executing WasmMsg")); + assert_eq!( + error.root_cause().to_string(), + ContractError::Unauthorized {}.to_string() + ); } diff --git a/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs b/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs index 722531f..49cf2a1 100644 --- a/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs +++ b/contracts/oraiswap-v3/src/tests/change_fee_receiver.rs @@ -2,6 +2,7 @@ use crate::math::types::percentage::Percentage; use crate::math::types::sqrt_price::calculate_sqrt_price; use crate::tests::helper::macros::*; use crate::tests::helper::MockApp; +use crate::ContractError; use crate::{FeeTier, PoolKey}; use cosmwasm_std::Addr; use decimal::Decimal; @@ -69,8 +70,9 @@ fn test_not_admin_change_fee_reciever() { let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier.clone()).unwrap(); let error = change_fee_receiver!(app, dex, pool_key, "bob", "bob").unwrap_err(); - assert!(error - .root_cause() - .to_string() - .contains("error executing WasmMsg")); + + assert_eq!( + error.root_cause().to_string(), + ContractError::Unauthorized {}.to_string() + ); } diff --git a/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs b/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs index c9cdefe..d87e319 100644 --- a/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs +++ b/contracts/oraiswap-v3/src/tests/change_protocol_fee.rs @@ -2,6 +2,7 @@ use crate::msg::{ExecuteMsg, QueryMsg}; use crate::percentage::Percentage; use crate::tests::helper::macros::*; use crate::tests::helper::MockApp; +use crate::ContractError; use cosmwasm_std::Addr; use decimal::Decimal; @@ -46,8 +47,8 @@ fn test_change_protocol_fee_not_admin() { ) .unwrap_err(); - assert!(error - .root_cause() - .to_string() - .contains("error executing WasmMsg")); + assert_eq!( + error.root_cause().to_string(), + ContractError::Unauthorized {}.to_string() + ); } From afb636c3127e0d61c7738fdd8a126355c358b9fc Mon Sep 17 00:00:00 2001 From: Pham Tu Date: Mon, 22 Jul 2024 10:43:49 +0700 Subject: [PATCH 30/47] fix testcase --- contracts/oraiswap-v3/src/tests/incentive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/oraiswap-v3/src/tests/incentive.rs b/contracts/oraiswap-v3/src/tests/incentive.rs index ba3a44d..e88b3e9 100644 --- a/contracts/oraiswap-v3/src/tests/incentive.rs +++ b/contracts/oraiswap-v3/src/tests/incentive.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Addr, StdError, Timestamp, Uint128}; +use cosmwasm_std::{Addr, Timestamp, Uint128}; use decimal::*; use crate::{ From 7f2b8ac6a239790006d7a662e6f56c175e189be0 Mon Sep 17 00:00:00 2001 From: Pham Tu Date: Mon, 22 Jul 2024 11:09:13 +0700 Subject: [PATCH 31/47] check all error details of testcases --- contracts/oraiswap-v3/src/math/log.rs | 18 ---------- contracts/oraiswap-v3/src/tests/claim.rs | 3 +- .../oraiswap-v3/src/tests/liquidity_gap.rs | 8 +++-- contracts/oraiswap-v3/src/tests/nft.rs | 33 +++++++++++-------- contracts/oraiswap-v3/src/tests/position.rs | 16 ++++++--- .../oraiswap-v3/src/tests/position_list.rs | 9 +++-- .../src/tests/position_slippage.rs | 14 ++++++-- .../oraiswap-v3/src/tests/protocol_fee.rs | 8 +++-- .../oraiswap-v3/src/tests/remove_fee_tier.rs | 15 +++++++-- contracts/oraiswap-v3/src/tests/slippage.rs | 9 +++-- contracts/oraiswap-v3/src/tests/swap.rs | 15 +++++++-- 11 files changed, 94 insertions(+), 54 deletions(-) diff --git a/contracts/oraiswap-v3/src/math/log.rs b/contracts/oraiswap-v3/src/math/log.rs index e83cf6c..8f4253b 100644 --- a/contracts/oraiswap-v3/src/math/log.rs +++ b/contracts/oraiswap-v3/src/math/log.rs @@ -391,24 +391,6 @@ mod tests { } } - #[test] - fn test_domain_calculate_sqrt_price() { - // Over max tick - // { - // let tick_out_of_range = MAX_TICK + 1; - // let (_, cause, stack) = SqrtPrice::from_tick(tick_out_of_range).unwrap_err().get(); - // assert_eq!("tick over bounds", cause); - // assert_eq!(1, stack.len()); - // } - // // Below min tick - // { - // let tick_out_of_range = -MAX_TICK - 1; - // let (_, cause, stack) = SqrtPrice::from_tick(tick_out_of_range).unwrap_err().get(); - // assert_eq!("tick over bounds", cause); - // assert_eq!(1, stack.len()); - // } - } - #[test] fn test_align_tick_with_spacing() { // zero diff --git a/contracts/oraiswap-v3/src/tests/claim.rs b/contracts/oraiswap-v3/src/tests/claim.rs index a4b5f79..e28f849 100644 --- a/contracts/oraiswap-v3/src/tests/claim.rs +++ b/contracts/oraiswap-v3/src/tests/claim.rs @@ -48,5 +48,6 @@ fn test_claim_not_owner() { init_basic_position!(app, dex, token_x, token_y); init_basic_swap!(app, dex, token_x, token_y); - claim_fee!(app, dex, 0, "bob").unwrap_err(); + let error = claim_fee!(app, dex, 0, "bob").unwrap_err(); + assert!(error.root_cause().to_string().contains("not found")); } diff --git a/contracts/oraiswap-v3/src/tests/liquidity_gap.rs b/contracts/oraiswap-v3/src/tests/liquidity_gap.rs index 8afb42b..9ca8a08 100644 --- a/contracts/oraiswap-v3/src/tests/liquidity_gap.rs +++ b/contracts/oraiswap-v3/src/tests/liquidity_gap.rs @@ -7,7 +7,7 @@ use crate::{ sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, MIN_SQRT_PRICE, + ContractError, FeeTier, PoolKey, MIN_SQRT_PRICE, }; #[test] @@ -137,7 +137,7 @@ fn test_liquidity_gap() { let swap_amount = TokenAmount(1); let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - swap!( + let error = swap!( app, dex, pool_key, @@ -148,6 +148,10 @@ fn test_liquidity_gap() { "bob" ) .unwrap_err(); + assert_eq!( + error.root_cause().to_string(), + ContractError::NoGainSwap {}.to_string() + ); } // Should skip gap and then swap diff --git a/contracts/oraiswap-v3/src/tests/nft.rs b/contracts/oraiswap-v3/src/tests/nft.rs index f1543bc..447d9ad 100644 --- a/contracts/oraiswap-v3/src/tests/nft.rs +++ b/contracts/oraiswap-v3/src/tests/nft.rs @@ -10,7 +10,7 @@ use crate::{ sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, Position, MIN_SQRT_PRICE, + ContractError, FeeTier, PoolKey, Position, MIN_SQRT_PRICE, }; #[test] @@ -275,8 +275,10 @@ fn test_burn_nft() { // Load states let pool_state = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); // Check ticks - get_tick!(app, dex, pool_key, lower_tick_index).unwrap_err(); - get_tick!(app, dex, pool_key, upper_tick_index).unwrap_err(); + let error = get_tick!(app, dex, pool_key, lower_tick_index).unwrap_err(); + assert!(error.to_string().contains("not found")); + let error = get_tick!(app, dex, pool_key, upper_tick_index).unwrap_err(); + assert!(error.to_string().contains("not found")); let lower_tick_bit = is_tick_initialized!(app, dex, pool_key, lower_tick_index); let upper_tick_bit = is_tick_initialized!(app, dex, pool_key, upper_tick_index); @@ -1104,16 +1106,21 @@ fn test_only_owner_can_transfer_nft() { ) .unwrap(); - app.execute( - Addr::unchecked("bob"), - dex.clone(), - &msg::ExecuteMsg::TransferNft { - recipient: Addr::unchecked("alice"), - token_id, - }, - &[], - ) - .unwrap_err(); + let error = app + .execute( + Addr::unchecked("bob"), + dex.clone(), + &msg::ExecuteMsg::TransferNft { + recipient: Addr::unchecked("alice"), + token_id, + }, + &[], + ) + .unwrap_err(); + assert_eq!( + error.root_cause().to_string(), + ContractError::Unauthorized {}.to_string() + ); } } diff --git a/contracts/oraiswap-v3/src/tests/position.rs b/contracts/oraiswap-v3/src/tests/position.rs index ca850ac..78357d7 100644 --- a/contracts/oraiswap-v3/src/tests/position.rs +++ b/contracts/oraiswap-v3/src/tests/position.rs @@ -7,7 +7,7 @@ use crate::{ sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, MIN_SQRT_PRICE, + ContractError, FeeTier, PoolKey, MIN_SQRT_PRICE, }; #[test] @@ -82,7 +82,7 @@ fn test_position_same_upper_and_lower_tick() { let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier).unwrap(); - create_position!( + let error = create_position!( app, dex, pool_key, @@ -94,6 +94,11 @@ fn test_position_same_upper_and_lower_tick() { "alice" ) .unwrap_err(); + + assert_eq!( + error.root_cause().to_string(), + ContractError::InvalidTickIndex {}.to_string() + ); } #[test] @@ -224,8 +229,11 @@ fn test_remove_position() { // Load states let pool_state = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); // Check ticks - get_tick!(app, dex, pool_key, lower_tick_index).unwrap_err(); - get_tick!(app, dex, pool_key, upper_tick_index).unwrap_err(); + let error = get_tick!(app, dex, pool_key, lower_tick_index).unwrap_err(); + assert!(error.to_string().contains("not found")); + let error = get_tick!(app, dex, pool_key, upper_tick_index).unwrap_err(); + assert!(error.to_string().contains("not found")); + let lower_tick_bit = is_tick_initialized!(app, dex, pool_key, lower_tick_index); let upper_tick_bit = is_tick_initialized!(app, dex, pool_key, upper_tick_index); diff --git a/contracts/oraiswap-v3/src/tests/position_list.rs b/contracts/oraiswap-v3/src/tests/position_list.rs index 9d89ea0..09d58cf 100644 --- a/contracts/oraiswap-v3/src/tests/position_list.rs +++ b/contracts/oraiswap-v3/src/tests/position_list.rs @@ -34,7 +34,8 @@ fn test_remove_position_from_empty_list() { ) .unwrap(); - remove_position!(app, dex, 0, "alice").unwrap_err(); + let error = remove_position!(app, dex, 0, "alice").unwrap_err(); + assert!(error.root_cause().to_string().contains("not found")); } #[test] @@ -369,13 +370,14 @@ fn test_only_owner_can_modify_position_list() { let last_position_index_before = get_all_positions!(app, dex, "alice").len() - 1; let unauthorized_user = "bob"; - remove_position!( + let error = remove_position!( app, dex, last_position_index_before as u32, unauthorized_user ) .unwrap_err(); + assert!(error.root_cause().to_string().contains("not found")); } } @@ -674,7 +676,8 @@ fn test_only_owner_can_transfer_position() { { let transferred_index = 0; - transfer_position!(app, dex, transferred_index, "alice", "bob").unwrap_err(); + let error = transfer_position!(app, dex, transferred_index, "alice", "bob").unwrap_err(); + assert!(error.root_cause().to_string().contains("not found")); } } diff --git a/contracts/oraiswap-v3/src/tests/position_slippage.rs b/contracts/oraiswap-v3/src/tests/position_slippage.rs index 170394e..c7053ea 100644 --- a/contracts/oraiswap-v3/src/tests/position_slippage.rs +++ b/contracts/oraiswap-v3/src/tests/position_slippage.rs @@ -5,7 +5,7 @@ use crate::{ percentage::Percentage, sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, - FeeTier, PoolKey, + ContractError, FeeTier, PoolKey, }; #[test] @@ -72,7 +72,7 @@ fn test_position_slippage_below_range() { let limit_lower = SqrtPrice::new(1014432353584998786339859); let limit_upper = SqrtPrice::new(1045335831204498605270797); let tick = pool_key.fee_tier.tick_spacing as i32; - create_position!( + let error = create_position!( app, dex, pool_key, @@ -84,6 +84,10 @@ fn test_position_slippage_below_range() { "alice" ) .unwrap_err(); + assert_eq!( + error.root_cause().to_string(), + ContractError::PriceLimitReached {}.to_string() + ); } #[test] @@ -99,7 +103,7 @@ fn test_position_slippage_above_range() { let limit_lower = SqrtPrice::new(955339206774222158009382); let limit_upper = SqrtPrice::new(984442481813945288458906); let tick = pool_key.fee_tier.tick_spacing as i32; - create_position!( + let error = create_position!( app, dex, pool_key, @@ -111,4 +115,8 @@ fn test_position_slippage_above_range() { "alice" ) .unwrap_err(); + assert_eq!( + error.root_cause().to_string(), + ContractError::PriceLimitReached {}.to_string() + ); } diff --git a/contracts/oraiswap-v3/src/tests/protocol_fee.rs b/contracts/oraiswap-v3/src/tests/protocol_fee.rs index 9715aa4..ea443db 100644 --- a/contracts/oraiswap-v3/src/tests/protocol_fee.rs +++ b/contracts/oraiswap-v3/src/tests/protocol_fee.rs @@ -4,7 +4,7 @@ use crate::{ percentage::Percentage, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, + ContractError, FeeTier, PoolKey, }; #[test] @@ -60,7 +60,11 @@ fn test_protocol_fee_not_admin() { ) .unwrap(); - withdraw_protocol_fee!(app, dex, pool_key, "bob").unwrap_err(); + let error = withdraw_protocol_fee!(app, dex, pool_key, "bob").unwrap_err(); + assert_eq!( + error.root_cause().to_string(), + ContractError::Unauthorized {}.to_string() + ); } #[test] diff --git a/contracts/oraiswap-v3/src/tests/remove_fee_tier.rs b/contracts/oraiswap-v3/src/tests/remove_fee_tier.rs index 84273fb..a7c622c 100644 --- a/contracts/oraiswap-v3/src/tests/remove_fee_tier.rs +++ b/contracts/oraiswap-v3/src/tests/remove_fee_tier.rs @@ -3,7 +3,7 @@ use decimal::*; use crate::{ percentage::Percentage, tests::helper::{macros::*, MockApp}, - FeeTier, + ContractError, FeeTier, }; #[test] @@ -35,7 +35,12 @@ fn test_remove_not_existing_fee_tier() { add_fee_tier!(app, dex, fee_tier, "alice").unwrap(); let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 2).unwrap(); - remove_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); + let error = remove_fee_tier!(app, dex, fee_tier, "alice").unwrap_err(); + + assert_eq!( + error.root_cause().to_string(), + ContractError::FeeTierNotFound {}.to_string() + ); } #[test] @@ -49,5 +54,9 @@ fn test_remove_fee_tier_not_admin() { let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 2).unwrap(); add_fee_tier!(app, dex, fee_tier, "alice").unwrap(); - remove_fee_tier!(app, dex, fee_tier, "bob").unwrap_err(); + let error = remove_fee_tier!(app, dex, fee_tier, "bob").unwrap_err(); + assert_eq!( + error.root_cause().to_string(), + ContractError::Unauthorized {}.to_string() + ); } diff --git a/contracts/oraiswap-v3/src/tests/slippage.rs b/contracts/oraiswap-v3/src/tests/slippage.rs index 8dbc459..22eb60b 100644 --- a/contracts/oraiswap-v3/src/tests/slippage.rs +++ b/contracts/oraiswap-v3/src/tests/slippage.rs @@ -6,7 +6,7 @@ use crate::{ sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, - FeeTier, PoolKey, MAX_SQRT_PRICE, + ContractError, FeeTier, PoolKey, MAX_SQRT_PRICE, }; #[test] @@ -66,7 +66,7 @@ fn test_swap_close_to_limit() { let target_sqrt_price = quoted_target_sqrt_price - SqrtPrice::new(1); - swap!( + let error = swap!( app, dex, pool_key, @@ -77,6 +77,11 @@ fn test_swap_close_to_limit() { "alice" ) .unwrap_err(); + + assert_eq!( + error.root_cause().to_string(), + ContractError::PriceLimitReached {}.to_string() + ); } #[test] diff --git a/contracts/oraiswap-v3/src/tests/swap.rs b/contracts/oraiswap-v3/src/tests/swap.rs index 902d63e..3edfe52 100644 --- a/contracts/oraiswap-v3/src/tests/swap.rs +++ b/contracts/oraiswap-v3/src/tests/swap.rs @@ -7,7 +7,7 @@ use crate::{ sqrt_price::{calculate_sqrt_price, SqrtPrice}, tests::helper::macros::*, token_amount::TokenAmount, - FeeTier, PoolKey, MAX_SQRT_PRICE, MIN_SQRT_PRICE, + ContractError, FeeTier, PoolKey, MAX_SQRT_PRICE, MIN_SQRT_PRICE, }; use super::helper::MockApp; @@ -373,7 +373,7 @@ fn test_swap_not_enough_liquidity_token_x() { let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - swap!( + let error = swap!( app, dex, pool_key, @@ -384,6 +384,11 @@ fn test_swap_not_enough_liquidity_token_x() { "bob" ) .unwrap_err(); + + assert_eq!( + error.root_cause().to_string(), + ContractError::TickLimitReached {}.to_string() + ); } #[test] @@ -460,7 +465,7 @@ fn test_swap_not_enough_liquidity_token_y() { let slippage = SqrtPrice::new(MAX_SQRT_PRICE); - swap!( + let error = swap!( app, dex, pool_key, @@ -471,4 +476,8 @@ fn test_swap_not_enough_liquidity_token_y() { "bob" ) .unwrap_err(); + assert_eq!( + error.root_cause().to_string(), + ContractError::TickLimitReached {}.to_string() + ); } From 52a47728b048951474ae75adbaa09d913ab3c754 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Tue, 23 Jul 2024 22:43:33 +0700 Subject: [PATCH 32/47] update: add event attributes --- .../oraiswap-v3/src/entrypoints/execute.rs | 205 ++++++++++++++---- contracts/oraiswap-v3/src/interface.rs | 7 + 2 files changed, 166 insertions(+), 46 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 932e813..59193f7 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -13,7 +13,7 @@ use super::{ check_can_send, create_tick, remove_tick_and_flip_bitmap, swap_internal, swap_route_internal, transfer_nft, update_approvals, TimeStampExt, }; -use cosmwasm_std::{attr, Addr, Binary, DepsMut, Env, MessageInfo, Response}; +use cosmwasm_std::{attr, Addr, Binary, DepsMut, Env, Event, MessageInfo, Response}; use cw20::Expiration; use decimal::Decimal; @@ -40,9 +40,15 @@ pub fn change_admin( config.admin = new_admin.clone(); CONFIG.save(deps.storage, &config)?; - Ok(Response::new() - .add_attribute("action", "change_admin") - .add_attribute("new_admin", new_admin)) + let event_attributes = vec![ + attr("action", "change_admin"), + attr("old_admin", info.sender.as_str()), + attr("new_admin", new_admin.as_str()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_event(event)) } /// Allows an fee receiver to withdraw collected fees. @@ -81,11 +87,17 @@ pub fn withdraw_protocol_fee( asset_0.transfer(&mut msgs, &info)?; asset_1.transfer(&mut msgs, &info)?; - Ok(Response::new() - .add_messages(msgs) - .add_attribute("action", "withdraw_protocol_fee") - .add_attribute("token_x", fee_protocol_token_x.to_string()) - .add_attribute("token_y", fee_protocol_token_y.to_string())) + let event_attributes = vec![ + attr("action", "withdraw_protocol_fee"), + attr("pool_key", pool_key.to_string()), + attr("token_x", fee_protocol_token_x.to_string()), + attr("token_y", fee_protocol_token_y.to_string()), + attr("receiver", pool.fee_receiver.as_str()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_messages(msgs).add_event(event)) } /// Allows an admin to adjust the protocol fee. @@ -106,10 +118,21 @@ pub fn change_protocol_fee( return Err(ContractError::Unauthorized {}); } + let old_protocol_fee = config.protocol_fee; + config.protocol_fee = protocol_fee; CONFIG.save(deps.storage, &config)?; - Ok(Response::new().add_attribute("action", "change_protocol_fee")) + let event_attributes = vec![ + attr("action", "change_protocol_fee"), + attr("admin", info.sender.as_str()), + attr("old_protocol_fee", old_protocol_fee.to_string()), + attr("new_protocol_fee", protocol_fee.to_string()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_event(event)) } /// Allows admin to change current fee receiver. @@ -134,10 +157,21 @@ pub fn change_fee_receiver( let pool_key_db = pool_key.key(); let mut pool = POOLS.load(deps.storage, &pool_key_db)?; + let old_fee_receiver = pool.fee_receiver.clone(); pool.fee_receiver = fee_receiver.to_string(); POOLS.save(deps.storage, &pool_key_db, &pool)?; - Ok(Response::new().add_attribute("action", "change_fee_receiver")) + let event_attributes = vec![ + attr("action", "change_fee_receiver"), + attr("pool_key", pool_key.to_string()), + attr("admin", info.sender.as_str()), + attr("old_fee_receiver", old_fee_receiver.as_str()), + attr("new_fee_receiver", fee_receiver.as_str()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_event(event)) } /// Opens a position. @@ -236,8 +270,9 @@ pub fn create_position( let event_attributes = vec![ attr("action", "create_position"), + attr("pool_key", pool_key.to_string()), attr("token_id", position.token_id.to_string()), - attr("address", info.sender.as_str()), + attr("owner", info.sender.as_str()), attr("liquidity", liquidity_delta.to_string()), attr("lower_tick", lower_tick.index.to_string()), attr("upper_tick", upper_tick.index.to_string()), @@ -246,9 +281,9 @@ pub fn create_position( attr("amount_y", y.to_string()), ]; - Ok(Response::new() - .add_messages(msgs) - .add_attributes(event_attributes)) + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_messages(msgs).add_event(event)) } /// Performs a single swap based on the provided parameters. @@ -271,6 +306,7 @@ pub fn create_position( /// - Fails if the allowance is insufficient or the user balance transfer fails. /// - Fails if there is insufficient liquidity in pool /// - Fails if pool does not +/// TODO: config receipient? #[allow(clippy::too_many_arguments)] pub fn swap( deps: DepsMut, @@ -308,14 +344,21 @@ pub fn swap( sqrt_price_limit, )?; - Ok(Response::new() - .add_messages(msgs) - .add_attribute("action", "swap") - .add_attribute("pool_key", pool_key.to_string()) - .add_attribute("amount_in", amount_in.to_string()) - .add_attribute("amount_out", amount_out.to_string()) - .add_attribute("fee", fee.to_string()) - .add_attribute("x_to_y", x_to_y.to_string())) + let event_attributes = vec![ + attr("action", "swap"), + attr("pool_key", pool_key.to_string()), + attr("sender", info.sender.as_str()), // TODO: sender is contract or original sender? + attr("amount_in", amount_in.to_string()), + attr("amount_out", amount_out.to_string()), + attr("current_tick", pool.current_tick_index.to_string()), + attr("current_sqrt_price", pool.sqrt_price.to_string()), + attr("x_to_y", x_to_y.to_string()), + attr("fee", fee.to_string()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_messages(msgs).add_event(event)) } /// Performs atomic swap involving several pools based on the provided parameters. @@ -406,7 +449,16 @@ pub fn transfer_position( position.approvals = vec![]; state::add_position(deps.storage, &receiver_addr, &position)?; - Ok(Response::new().add_attribute("action", "transfer_position")) + let event_attributes = vec![ + attr("action", "transfer_position"), + attr("sender", info.sender.as_str()), + attr("receiver", receiver), + attr("position_token_id", position.token_id.to_string()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_event(event)) } /// Allows an authorized user (owner of the position) to claim collected fees. @@ -469,11 +521,18 @@ pub fn claim_fee( asset_0.transfer(&mut msgs, &info)?; asset_1.transfer(&mut msgs, &info)?; - Ok(Response::new() - .add_messages(msgs) - .add_attribute("action", "claim_fee") - .add_attribute("amount_x", x.to_string()) - .add_attribute("amount_y", y.to_string())) + let event_attributes = vec![ + attr("action", "claim_fee"), + attr("owner", info.sender.as_str()), + attr("pool_key", position.pool_key.to_string()), + attr("position_token_id", position.token_id.to_string()), + attr("amount_x", x.to_string()), + attr("amount_y", y.to_string()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_messages(msgs).add_event(event)) } /// Allows an authorized user (owner of the position) to claim incentives. @@ -505,13 +564,36 @@ pub fn claim_incentives( POOLS.save(deps.storage, &pool_key_db, &pool)?; let mut msgs = vec![]; - for asset in incentives { + for asset in incentives.clone() { asset.transfer(&mut msgs, &info)?; } - Ok(Response::new() - .add_messages(msgs) - .add_attribute("action", "claim_incentives")) + let event_attributes = vec![ + attr("action", "claim_incentives"), + attr("owner", info.sender.as_str()), + attr("pool_key", position.pool_key.to_string()), + attr("position_token_id", position.token_id.to_string()), + attr( + "incentives_token_address", + incentives + .iter() + .map(|x| x.info.denom()) + .collect::>() + .join(","), + ), + attr( + "incentives_amount", + incentives + .iter() + .map(|x| x.amount.to_string()) + .collect::>() + .join(","), + ), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_messages(msgs).add_event(event)) } /// Removes a position. Sends tokens associated with specified position to the owner. @@ -601,16 +683,15 @@ pub fn remove_position( let event_attributes = vec![ attr("action", "remove_position"), - attr("address", info.sender.as_str()), + attr("owner", info.sender.as_str()), + attr("pool_key", position.pool_key.to_string()), + attr("position_token_id", position.token_id.to_string()), attr("liquidity", withdrawed_liquidity.to_string()), - attr("lower_tick", lower_tick.index.to_string()), - attr("upper_tick", upper_tick.index.to_string()), - attr("current_sqrt_price", pool.sqrt_price.to_string()), ]; - Ok(Response::new() - .add_messages(msgs) - .add_attributes(event_attributes)) + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_messages(msgs).add_event(event)) } /// Allows a user to create a custom pool on a specified token pair and fee tier. @@ -669,7 +750,17 @@ pub fn create_pool( POOLS.save(deps.storage, &db_key, &pool)?; - Ok(Response::new().add_attribute("action", "create_pool")) + let event_attributes = vec![ + attr("action", "create_pool"), + attr("block", env.block.height.to_string()), + attr("pool_key", pool_key.to_string()), + attr("init_sqrt_price", init_sqrt_price.to_string()), + attr("init_tick", init_tick.to_string()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_event(event)) } /// Allows admin to add a custom fee tier. @@ -707,7 +798,16 @@ pub fn add_fee_tier( CONFIG.save(deps.storage, &config)?; - Ok(Response::new().add_attribute("action", "add_fee_tier")) + let event_attributes = vec![ + attr("action", "add_fee_tier"), + attr("admin", info.sender.as_str()), + attr("fee", fee_tier.fee.to_string()), + attr("tick_spacing", fee_tier.tick_spacing.to_string()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_event(event)) } /// Removes an existing fee tier. @@ -738,7 +838,16 @@ pub fn remove_fee_tier( CONFIG.save(deps.storage, &config)?; - Ok(Response::new().add_attribute("action", "remove_fee_tier")) + let event_attributes = vec![ + attr("action", "remove_fee_tier"), + attr("admin", info.sender.as_str()), + attr("fee", fee_tier.fee.to_string()), + attr("tick_spacing", fee_tier.tick_spacing.to_string()), + ]; + + let event = Event::new("amm_v3").add_attributes(event_attributes); + + Ok(Response::new().add_event(event)) } pub fn handle_approve( @@ -753,6 +862,7 @@ pub fn handle_approve( Ok(Response::new().add_attributes(vec![ attr("action", "approve"), + attr("token_id", token_id.to_string()), attr("sender", info.sender), attr("spender", spender), ])) @@ -769,6 +879,7 @@ pub fn handle_revoke( Ok(Response::new().add_attributes(vec![ attr("action", "revoke"), + attr("token_id", token_id.to_string()), attr("sender", info.sender), attr("spender", spender), ])) @@ -830,6 +941,7 @@ pub fn handle_transfer_nft( Ok(Response::new().add_attributes(vec![ attr("action", "transfer_nft"), + attr("token_id", token_id.to_string()), attr("sender", info.sender), attr("recipient", recipient), ])) @@ -874,6 +986,7 @@ pub fn handle_send_nft( .add_message(send.into_cosmos_msg(contract.to_string())?) .add_attributes(vec![ attr("action", "send_nft"), + attr("token_id", token_id.to_string()), attr("sender", info.sender), attr("recipient", contract), ])) @@ -943,12 +1056,12 @@ pub fn create_incentive( Ok(Response::new().add_attributes(vec![ ("action", "create_incentive"), - ("pool", &format!("{:?}", pool_key)), + ("pool", &pool_key.to_string()), ("reward_token", &format!("{:?}", reward_token)), ("total_reward", &remaining.to_string()), ("reward_per_sec", &reward_per_sec.to_string()), ( - "reward_per_sec", + "start_timestamp", &start_timestamp .unwrap_or(env.block.time.seconds()) .to_string(), @@ -993,7 +1106,7 @@ pub fn update_incentive( Ok(Response::new().add_attributes(vec![ ("action", "update_incentive"), - ("pool", &format!("{:?}", pool_key)), + ("pool", &pool_key.to_string()), ("record_id", &record_id.to_string()), ])) } diff --git a/contracts/oraiswap-v3/src/interface.rs b/contracts/oraiswap-v3/src/interface.rs index 80722e2..7bc6d59 100644 --- a/contracts/oraiswap-v3/src/interface.rs +++ b/contracts/oraiswap-v3/src/interface.rs @@ -45,6 +45,13 @@ impl AssetInfo { } } } + + pub fn denom(&self) -> String { + match self { + AssetInfo::Token { contract_addr } => contract_addr.to_string(), + AssetInfo::NativeToken { denom } => denom.to_string(), + } + } } #[cw_serde] From 439117ea77e39e4842381c33aa763d0410b0ea1d Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Tue, 23 Jul 2024 22:58:22 +0700 Subject: [PATCH 33/47] fix: test case & remove unuse event amm-v3 --- .../oraiswap-v3/src/entrypoints/execute.rs | 28 +++++-------------- contracts/oraiswap-v3/src/tests/helper.rs | 7 +++++ contracts/oraiswap-v3/src/tests/nft.rs | 1 + 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 59193f7..7a9b323 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -46,9 +46,7 @@ pub fn change_admin( attr("new_admin", new_admin.as_str()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_event(event)) + Ok(Response::new().add_attributes(event_attributes)) } /// Allows an fee receiver to withdraw collected fees. @@ -130,9 +128,7 @@ pub fn change_protocol_fee( attr("new_protocol_fee", protocol_fee.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_event(event)) + Ok(Response::new().add_attributes(event_attributes)) } /// Allows admin to change current fee receiver. @@ -169,9 +165,7 @@ pub fn change_fee_receiver( attr("new_fee_receiver", fee_receiver.as_str()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_event(event)) + Ok(Response::new().add_attributes(event_attributes)) } /// Opens a position. @@ -456,9 +450,7 @@ pub fn transfer_position( attr("position_token_id", position.token_id.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_event(event)) + Ok(Response::new().add_attributes(event_attributes)) } /// Allows an authorized user (owner of the position) to claim collected fees. @@ -758,9 +750,7 @@ pub fn create_pool( attr("init_tick", init_tick.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_event(event)) + Ok(Response::new().add_attributes(event_attributes)) } /// Allows admin to add a custom fee tier. @@ -805,9 +795,7 @@ pub fn add_fee_tier( attr("tick_spacing", fee_tier.tick_spacing.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_event(event)) + Ok(Response::new().add_attributes(event_attributes)) } /// Removes an existing fee tier. @@ -845,9 +833,7 @@ pub fn remove_fee_tier( attr("tick_spacing", fee_tier.tick_spacing.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_event(event)) + Ok(Response::new().add_attributes(event_attributes)) } pub fn handle_approve( diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index 6efc4cf..02c3dd8 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -444,6 +444,13 @@ pub fn extract_amount(events: &[Event], key: &str) -> Option { } } } + if event.ty == "wasm-amm_v3" { + for attr in &event.attributes { + if attr.key == key { + return attr.value.parse::().map(TokenAmount).ok(); + } + } + } } None } diff --git a/contracts/oraiswap-v3/src/tests/nft.rs b/contracts/oraiswap-v3/src/tests/nft.rs index 447d9ad..9d15c91 100644 --- a/contracts/oraiswap-v3/src/tests/nft.rs +++ b/contracts/oraiswap-v3/src/tests/nft.rs @@ -1203,6 +1203,7 @@ fn test_approving_revoking() { value: dex.to_string() }, attr("action", "approve"), + attr("token_id", token_id.to_string()), attr("sender", "alice"), attr("spender", "random"), ] From 6d6b1c105f17c91c49dec88cba41722d5148bdaa Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Wed, 24 Jul 2024 11:23:51 +0700 Subject: [PATCH 34/47] update: remove amm-v3 events, merge claim bot fee & incentives --- .../oraiswap-v3/src/entrypoints/execute.rs | 29 ++-- contracts/oraiswap-v3/src/tests/claim.rs | 128 +++++++++++++++++- contracts/oraiswap-v3/src/tests/helper.rs | 7 - 3 files changed, 133 insertions(+), 31 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 7a9b323..278a3ce 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -13,7 +13,7 @@ use super::{ check_can_send, create_tick, remove_tick_and_flip_bitmap, swap_internal, swap_route_internal, transfer_nft, update_approvals, TimeStampExt, }; -use cosmwasm_std::{attr, Addr, Binary, DepsMut, Env, Event, MessageInfo, Response}; +use cosmwasm_std::{attr, Addr, Binary, DepsMut, Env, MessageInfo, Response}; use cw20::Expiration; use decimal::Decimal; @@ -93,9 +93,7 @@ pub fn withdraw_protocol_fee( attr("receiver", pool.fee_receiver.as_str()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_messages(msgs).add_event(event)) + Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) } /// Allows an admin to adjust the protocol fee. @@ -275,9 +273,7 @@ pub fn create_position( attr("amount_y", y.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_messages(msgs).add_event(event)) + Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) } /// Performs a single swap based on the provided parameters. @@ -300,7 +296,6 @@ pub fn create_position( /// - Fails if the allowance is insufficient or the user balance transfer fails. /// - Fails if there is insufficient liquidity in pool /// - Fails if pool does not -/// TODO: config receipient? #[allow(clippy::too_many_arguments)] pub fn swap( deps: DepsMut, @@ -341,7 +336,7 @@ pub fn swap( let event_attributes = vec![ attr("action", "swap"), attr("pool_key", pool_key.to_string()), - attr("sender", info.sender.as_str()), // TODO: sender is contract or original sender? + attr("sender", info.sender.as_str()), attr("amount_in", amount_in.to_string()), attr("amount_out", amount_out.to_string()), attr("current_tick", pool.current_tick_index.to_string()), @@ -350,9 +345,7 @@ pub fn swap( attr("fee", fee.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_messages(msgs).add_event(event)) + Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) } /// Performs atomic swap involving several pools based on the provided parameters. @@ -522,9 +515,9 @@ pub fn claim_fee( attr("amount_y", y.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); + let resp = claim_incentives(deps, env, info, index)?; - Ok(Response::new().add_messages(msgs).add_event(event)) + Ok(resp.add_messages(msgs).add_attributes(event_attributes)) } /// Allows an authorized user (owner of the position) to claim incentives. @@ -583,9 +576,7 @@ pub fn claim_incentives( ), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_messages(msgs).add_event(event)) + Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) } /// Removes a position. Sends tokens associated with specified position to the owner. @@ -681,9 +672,7 @@ pub fn remove_position( attr("liquidity", withdrawed_liquidity.to_string()), ]; - let event = Event::new("amm_v3").add_attributes(event_attributes); - - Ok(Response::new().add_messages(msgs).add_event(event)) + Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) } /// Allows a user to create a custom pool on a specified token pair and fee tier. diff --git a/contracts/oraiswap-v3/src/tests/claim.rs b/contracts/oraiswap-v3/src/tests/claim.rs index e28f849..d834a7c 100644 --- a/contracts/oraiswap-v3/src/tests/claim.rs +++ b/contracts/oraiswap-v3/src/tests/claim.rs @@ -1,10 +1,8 @@ +use cosmwasm_std::Timestamp; use decimal::{Decimal, Factories}; use crate::{ - percentage::Percentage, - tests::helper::{macros::*, MockApp}, - token_amount::TokenAmount, - FeeTier, + interface::AssetInfo, liquidity::Liquidity, percentage::Percentage, sqrt_price::{self, calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, FeeTier, PoolKey }; #[test] @@ -51,3 +49,125 @@ fn test_claim_not_owner() { let error = claim_fee!(app, dex, 0, "bob").unwrap_err(); assert!(error.root_cause().to_string().contains("not found")); } + +#[test] +fn claim_both_fee_and_incentives() { + let protocol_fee = Percentage::from_scale(6, 3); + let mut app = MockApp::new(&[]); + let dex = create_dex!(app, Percentage::new(0)); + let dex_raw = &dex.to_string(); + + let initial_amount = 10u128.pow(10); + let (token_x, token_y, token_z) = + create_3_tokens!(app, initial_amount, initial_amount, initial_amount); + mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + + let fee_tier = FeeTier::new(protocol_fee, 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(); + + let reward_token = AssetInfo::Token { + contract_addr: token_z.clone(), + }; + let total_reward = Some(TokenAmount::from_integer(1000000000)); + let reward_per_sec = TokenAmount(100); + let start_timestamp: Option = None; + let liquidity = Liquidity::from_integer(1000000); + + // create position in range -20 - 20 + approve!(app, token_x, dex, initial_amount, "alice").unwrap(); + approve!(app, token_y, dex, initial_amount, "alice").unwrap(); + create_position!( + app, + dex, + pool_key, + -20, + 20, + liquidity, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + + let timestamp_init = app.app.block_info().time.seconds(); + create_incentive!( + app, + dex, + pool_key, + reward_token.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + + let before_dex_balance_token_x = balance_of!(app, token_x, dex); + let before_dex_balance_token_z = balance_of!(app, token_z, dex); + let before_user_balance_token_x = balance_of!(app, token_x, "alice"); + let before_user_balance_token_z = balance_of!(app, token_z, "alice"); + + // swap to increase fee growth + mint!(app, token_x, "bob", initial_amount, "alice").unwrap(); + approve!(app, token_x, dex, initial_amount, "bob").unwrap(); + swap!(app, dex, pool_key, true, TokenAmount(1000), true, sqrt_price::get_min_sqrt_price(fee_tier.tick_spacing), "bob").unwrap(); + + // increase time to have incentives + let mut block_info = app.app.block_info(); + let current_timestamp = block_info.time.seconds(); + block_info.time = Timestamp::from_seconds(current_timestamp + 1000); + app.app.set_block(block_info.clone()); + + // claim both + claim_fee!(app, dex, 0, "alice").unwrap(); + + let timestamp_after = app.app.block_info().time.seconds(); + let total_emit = (timestamp_after - timestamp_init) as u128 * reward_per_sec.0; + + let after_dex_balance_token_x = balance_of!(app, token_x, dex); + let after_dex_balance_token_z = balance_of!(app, token_z, dex); + let after_user_balance_token_x = balance_of!(app, token_x, "alice"); + let after_user_balance_token_z = balance_of!(app, token_z, "alice"); + + // incentive assert + assert!(before_dex_balance_token_z.gt(&after_dex_balance_token_z)); + assert!(before_user_balance_token_z.lt(&after_user_balance_token_z)); + assert!( + (before_user_balance_token_z + before_dex_balance_token_z).eq(&(after_user_balance_token_z + after_dex_balance_token_z)) + ); + assert!((after_user_balance_token_z - before_user_balance_token_z).le(&total_emit)); + + // fee claimed assert + let position = get_position!(app, dex, 0, "alice").unwrap(); + let fee_tokens_claimed = 6; + let receive_x_for_dex = 994; + let pool = get_pool!(app, dex, token_x, token_y, fee_tier).unwrap(); + + assert_eq!( + before_user_balance_token_x + fee_tokens_claimed, + after_user_balance_token_x + ); + assert_eq!( + before_dex_balance_token_x + receive_x_for_dex, + after_dex_balance_token_x + ); + assert_eq!(position.fee_growth_inside_x, pool.fee_growth_global_x); + assert_eq!(position.tokens_owed_x, TokenAmount(0)); +} diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index 02c3dd8..6efc4cf 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -444,13 +444,6 @@ pub fn extract_amount(events: &[Event], key: &str) -> Option { } } } - if event.ty == "wasm-amm_v3" { - for attr in &event.attributes { - if attr.key == key { - return attr.value.parse::().map(TokenAmount).ok(); - } - } - } } None } From beb78e7c732a352c856eb679b617b726b40c47ce Mon Sep 17 00:00:00 2001 From: meomeocoj Date: Wed, 24 Jul 2024 17:41:53 +0700 Subject: [PATCH 35/47] chore: add pool_creator to create_pool_event --- contracts/oraiswap-v3/src/contract.rs | 1 + .../oraiswap-v3/src/entrypoints/execute.rs | 24 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index 10a6398..e54f824 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -109,6 +109,7 @@ pub fn execute( init_tick, } => create_pool( deps, + info, env, token_0, token_1, diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 278a3ce..417cefd 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -93,7 +93,9 @@ pub fn withdraw_protocol_fee( attr("receiver", pool.fee_receiver.as_str()), ]; - Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) + Ok(Response::new() + .add_messages(msgs) + .add_attributes(event_attributes)) } /// Allows an admin to adjust the protocol fee. @@ -273,7 +275,9 @@ pub fn create_position( attr("amount_y", y.to_string()), ]; - Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) + Ok(Response::new() + .add_messages(msgs) + .add_attributes(event_attributes)) } /// Performs a single swap based on the provided parameters. @@ -336,7 +340,7 @@ pub fn swap( let event_attributes = vec![ attr("action", "swap"), attr("pool_key", pool_key.to_string()), - attr("sender", info.sender.as_str()), + attr("sender", info.sender.as_str()), attr("amount_in", amount_in.to_string()), attr("amount_out", amount_out.to_string()), attr("current_tick", pool.current_tick_index.to_string()), @@ -345,7 +349,9 @@ pub fn swap( attr("fee", fee.to_string()), ]; - Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) + Ok(Response::new() + .add_messages(msgs) + .add_attributes(event_attributes)) } /// Performs atomic swap involving several pools based on the provided parameters. @@ -576,7 +582,9 @@ pub fn claim_incentives( ), ]; - Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) + Ok(Response::new() + .add_messages(msgs) + .add_attributes(event_attributes)) } /// Removes a position. Sends tokens associated with specified position to the owner. @@ -672,7 +680,9 @@ pub fn remove_position( attr("liquidity", withdrawed_liquidity.to_string()), ]; - Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) + Ok(Response::new() + .add_messages(msgs) + .add_attributes(event_attributes)) } /// Allows a user to create a custom pool on a specified token pair and fee tier. @@ -695,6 +705,7 @@ pub fn remove_position( #[allow(clippy::too_many_arguments)] pub fn create_pool( deps: DepsMut, + info: MessageInfo, env: Env, token_0: String, token_1: String, @@ -733,6 +744,7 @@ pub fn create_pool( let event_attributes = vec![ attr("action", "create_pool"), + attr("pool_creator", info.sender.as_str()), attr("block", env.block.height.to_string()), attr("pool_key", pool_key.to_string()), attr("init_sqrt_price", init_sqrt_price.to_string()), From a1b7e1ea09b6d01c4c1c92c0d3b2fd5fc443bbf4 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Thu, 25 Jul 2024 11:53:56 +0700 Subject: [PATCH 36/47] fix: decimal in events --- .../oraiswap-v3/src/entrypoints/execute.rs | 18 +++++++++--------- contracts/oraiswap-v3/src/tests/position.rs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 278a3ce..5642142 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -122,8 +122,8 @@ pub fn change_protocol_fee( let event_attributes = vec![ attr("action", "change_protocol_fee"), attr("admin", info.sender.as_str()), - attr("old_protocol_fee", old_protocol_fee.to_string()), - attr("new_protocol_fee", protocol_fee.to_string()), + attr("old_protocol_fee", old_protocol_fee.get().to_string()), + attr("new_protocol_fee", protocol_fee.get().to_string()), ]; Ok(Response::new().add_attributes(event_attributes)) @@ -265,10 +265,10 @@ pub fn create_position( attr("pool_key", pool_key.to_string()), attr("token_id", position.token_id.to_string()), attr("owner", info.sender.as_str()), - attr("liquidity", liquidity_delta.to_string()), + attr("liquidity", liquidity_delta.get().to_string()), attr("lower_tick", lower_tick.index.to_string()), attr("upper_tick", upper_tick.index.to_string()), - attr("current_sqrt_price", pool.sqrt_price.to_string()), + attr("current_sqrt_price", pool.sqrt_price.get().to_string()), attr("amount_x", x.to_string()), attr("amount_y", y.to_string()), ]; @@ -340,7 +340,7 @@ pub fn swap( attr("amount_in", amount_in.to_string()), attr("amount_out", amount_out.to_string()), attr("current_tick", pool.current_tick_index.to_string()), - attr("current_sqrt_price", pool.sqrt_price.to_string()), + attr("current_sqrt_price", pool.sqrt_price.get().to_string()), attr("x_to_y", x_to_y.to_string()), attr("fee", fee.to_string()), ]; @@ -669,7 +669,7 @@ pub fn remove_position( attr("owner", info.sender.as_str()), attr("pool_key", position.pool_key.to_string()), attr("position_token_id", position.token_id.to_string()), - attr("liquidity", withdrawed_liquidity.to_string()), + attr("liquidity", withdrawed_liquidity.get().to_string()), ]; Ok(Response::new().add_messages(msgs).add_attributes(event_attributes)) @@ -735,7 +735,7 @@ pub fn create_pool( attr("action", "create_pool"), attr("block", env.block.height.to_string()), attr("pool_key", pool_key.to_string()), - attr("init_sqrt_price", init_sqrt_price.to_string()), + attr("init_sqrt_price", init_sqrt_price.get().to_string()), attr("init_tick", init_tick.to_string()), ]; @@ -780,7 +780,7 @@ pub fn add_fee_tier( let event_attributes = vec![ attr("action", "add_fee_tier"), attr("admin", info.sender.as_str()), - attr("fee", fee_tier.fee.to_string()), + attr("fee", fee_tier.fee.get().to_string()), attr("tick_spacing", fee_tier.tick_spacing.to_string()), ]; @@ -818,7 +818,7 @@ pub fn remove_fee_tier( let event_attributes = vec![ attr("action", "remove_fee_tier"), attr("admin", info.sender.as_str()), - attr("fee", fee_tier.fee.to_string()), + attr("fee", fee_tier.fee.get().to_string()), attr("tick_spacing", fee_tier.tick_spacing.to_string()), ]; diff --git a/contracts/oraiswap-v3/src/tests/position.rs b/contracts/oraiswap-v3/src/tests/position.rs index 78357d7..b1536a6 100644 --- a/contracts/oraiswap-v3/src/tests/position.rs +++ b/contracts/oraiswap-v3/src/tests/position.rs @@ -20,7 +20,7 @@ fn test_create_position() { add_fee_tier!(app, dex, fee_tier, "alice").unwrap(); - let init_tick = 10; + let init_tick = 0; let init_sqrt_price = calculate_sqrt_price(init_tick).unwrap(); create_pool!( app, From 823eb1766f5b1e413a86104523345011ab088e8b Mon Sep 17 00:00:00 2001 From: Pham Tu Date: Fri, 26 Jul 2024 18:11:52 +0700 Subject: [PATCH 37/47] update testing --- Cargo.lock | 2 +- contracts/oraiswap-v3/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4adf093..00edc30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,7 +304,7 @@ dependencies = [ [[package]] name = "cosmwasm-testing-util" version = "0.1.0" -source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=33a262f#33a262f3aeca4b46ada3213a5e60edb0585418ad" +source = "git+https://github.com/oraichain/cosmwasm-testing-util.git?rev=1b9c412#1b9c4126e8b5e19dc547f992a1a5cd9dde3d1b0d" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/contracts/oraiswap-v3/Cargo.toml b/contracts/oraiswap-v3/Cargo.toml index db270a3..58632ed 100644 --- a/contracts/oraiswap-v3/Cargo.toml +++ b/contracts/oraiswap-v3/Cargo.toml @@ -31,4 +31,4 @@ derive_more = { workspace = true } [dev-dependencies] cw20-base = { workspace = true, features = ["library"] } -cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "33a262f" } +cosmwasm-testing-util = { git = "https://github.com/oraichain/cosmwasm-testing-util.git", rev = "1b9c412" } From 2033994cace532203d25aabebf31136e10577853 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 26 Jul 2024 18:48:06 +0700 Subject: [PATCH 38/47] add get pool keys --- contracts/oraiswap-v3/src/contract.rs | 5 ++++- contracts/oraiswap-v3/src/entrypoints/query.rs | 14 ++++++++++++++ contracts/oraiswap-v3/src/msg.rs | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index e54f824..a418b24 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -308,7 +308,10 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { QueryMsg::NumTokens {} => to_json_binary(&query_num_tokens(deps)?), QueryMsg::PositionIncentives { owner_id, index } => { to_json_binary(&query_position_incentives(deps, env, owner_id, index)?) - } + }, + QueryMsg::PoolsByPoolKeys { pool_keys } => { + to_json_binary(&get_pools_with_pool_keys(deps, pool_keys)?) + }, } } diff --git a/contracts/oraiswap-v3/src/entrypoints/query.rs b/contracts/oraiswap-v3/src/entrypoints/query.rs index 468b989..747db9d 100644 --- a/contracts/oraiswap-v3/src/entrypoints/query.rs +++ b/contracts/oraiswap-v3/src/entrypoints/query.rs @@ -121,6 +121,20 @@ pub fn get_pools( state::get_pools(deps.storage, limit, start_after) } +pub fn get_pools_with_pool_keys( + deps: Deps, + pool_keys: Vec, +) -> Result, ContractError> { + let mut pools = vec![]; + for pool_key in pool_keys { + if let Ok(pool) = state::get_pool(deps.storage, &pool_key) { + pools.push(PoolWithPoolKey { pool, pool_key }); + } + } + Ok(pools) +} + + /// Retrieves listed pools for provided token pair /// - `token_0`: Address of first token /// - `token_1`: Address of second token diff --git a/contracts/oraiswap-v3/src/msg.rs b/contracts/oraiswap-v3/src/msg.rs index 48282c3..dd99ce6 100644 --- a/contracts/oraiswap-v3/src/msg.rs +++ b/contracts/oraiswap-v3/src/msg.rs @@ -304,4 +304,7 @@ pub enum QueryMsg { #[returns(Vec)] PositionIncentives { owner_id: Addr, index: u32 }, + + #[returns(Vec)] + PoolsByPoolKeys { pool_keys: Vec }, } From c338298f85df1c14aa2aece3a6f0b7a6efb0544c Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Sat, 27 Jul 2024 23:07:19 +0700 Subject: [PATCH 39/47] fix event claim_incentives --- .../oraiswap-v3/src/entrypoints/execute.rs | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 8701d05..e818cce 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -411,14 +411,7 @@ pub fn swap_route( .add_messages(msgs) .add_attribute("action", "swap_route") .add_attribute("amount_out", amount_out.to_string()) - .add_attribute( - "swap_hop", - swaps - .iter() - .map(|x| x.pool_key.to_string()) - .collect::>() - .join(","), - )) + .add_attribute("swap_hop", &format!("{:?}", swaps))) } /// Transfers a position between users. @@ -564,22 +557,7 @@ pub fn claim_incentives( attr("owner", info.sender.as_str()), attr("pool_key", position.pool_key.to_string()), attr("position_token_id", position.token_id.to_string()), - attr( - "incentives_token_address", - incentives - .iter() - .map(|x| x.info.denom()) - .collect::>() - .join(","), - ), - attr( - "incentives_amount", - incentives - .iter() - .map(|x| x.amount.to_string()) - .collect::>() - .join(","), - ), + attr("incentives_info", &format!("{:?}", incentives)), ]; Ok(Response::new() From 7c7acf82f1797df0d3fac3d7c4328a6756c68ff1 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Mon, 29 Jul 2024 16:09:07 +0700 Subject: [PATCH 40/47] add rm position event --- contracts/oraiswap-v3/src/entrypoints/execute.rs | 4 +++- contracts/oraiswap-v3/src/storage/position.rs | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index e818cce..943f8ee 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -599,7 +599,7 @@ pub fn remove_position( // calculate pending incentives let incentives = position.claim_incentives(&pool, &upper_tick, &lower_tick)?; - let (amount_x, amount_y, deinitialize_lower_tick, deinitialize_upper_tick) = position.remove( + let (amount_x, amount_y, liquidity_x, liquidity_y, deinitialize_lower_tick, deinitialize_upper_tick) = position.remove( &mut pool, current_timestamp, &mut lower_tick, @@ -656,6 +656,8 @@ pub fn remove_position( attr("pool_key", position.pool_key.to_string()), attr("position_token_id", position.token_id.to_string()), attr("liquidity", withdrawed_liquidity.get().to_string()), + attr("liquidity_x", liquidity_x.to_string()), + attr("liquidity_y", liquidity_y.to_string()), ]; Ok(Response::new() diff --git a/contracts/oraiswap-v3/src/storage/position.rs b/contracts/oraiswap-v3/src/storage/position.rs index 3a513da..ae5414b 100644 --- a/contracts/oraiswap-v3/src/storage/position.rs +++ b/contracts/oraiswap-v3/src/storage/position.rs @@ -310,7 +310,7 @@ impl Position { lower_tick: &mut Tick, upper_tick: &mut Tick, tick_spacing: u16, - ) -> Result<(TokenAmount, TokenAmount, bool, bool), ContractError> { + ) -> Result<(TokenAmount, TokenAmount, TokenAmount, TokenAmount, bool, bool), ContractError> { let liquidity_delta = self.liquidity; let (mut amount_x, mut amount_y) = self.modify( pool, @@ -322,6 +322,8 @@ impl Position { tick_spacing, )?; + let liquidity_x = amount_x; + let liquidity_y = amount_y; amount_x = amount_x.checked_add(self.tokens_owed_x)?; amount_y = amount_y.checked_add(self.tokens_owed_y)?; @@ -331,6 +333,8 @@ impl Position { Ok(( amount_x, amount_y, + liquidity_x, + liquidity_y, deinitialize_lower_tick, deinitialize_upper_tick, )) From 0f42924a6c80c7aaf6746a736768bf3635f692ef Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Wed, 31 Jul 2024 10:19:16 +0700 Subject: [PATCH 41/47] update events --- .../oraiswap-v3/src/entrypoints/execute.rs | 120 ++++++++++++++---- contracts/oraiswap-v3/src/storage/position.rs | 6 +- contracts/oraiswap-v3/src/tests/claim.rs | 60 ++++++++- 3 files changed, 155 insertions(+), 31 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index 943f8ee..d5c4042 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -13,7 +13,7 @@ use super::{ check_can_send, create_tick, remove_tick_and_flip_bitmap, swap_internal, swap_route_internal, transfer_nft, update_approvals, TimeStampExt, }; -use cosmwasm_std::{attr, Addr, Binary, DepsMut, Env, MessageInfo, Response}; +use cosmwasm_std::{attr, Addr, Attribute, Binary, DepsMut, Env, MessageInfo, Response}; use cw20::Expiration; use decimal::Decimal; @@ -267,12 +267,14 @@ pub fn create_position( attr("pool_key", pool_key.to_string()), attr("token_id", position.token_id.to_string()), attr("owner", info.sender.as_str()), - attr("liquidity", liquidity_delta.get().to_string()), + attr("position_liquidity", liquidity_delta.get().to_string()), attr("lower_tick", lower_tick.index.to_string()), attr("upper_tick", upper_tick.index.to_string()), attr("current_sqrt_price", pool.sqrt_price.get().to_string()), - attr("amount_x", x.to_string()), - attr("amount_y", y.to_string()), + attr("liquidity_x", x.to_string()), + attr("liquidity_y", y.to_string()), + attr("after_liquidity ", pool.liquidity.get().to_string()), + attr("ater_tick_index", pool.current_tick_index.to_string()), ]; Ok(Response::new() @@ -322,6 +324,7 @@ pub fn swap( amount_in, amount_out, fee, + pool: after_pool, .. } = swap_internal( deps.storage, @@ -343,8 +346,12 @@ pub fn swap( attr("sender", info.sender.as_str()), attr("amount_in", amount_in.to_string()), attr("amount_out", amount_out.to_string()), - attr("current_tick", pool.current_tick_index.to_string()), - attr("current_sqrt_price", pool.sqrt_price.get().to_string()), + attr("current_tick", after_pool.current_tick_index.to_string()), + attr( + "current_sqrt_price", + after_pool.sqrt_price.get().to_string(), + ), + attr("liquidity", after_pool.liquidity.get().to_string()), attr("x_to_y", x_to_y.to_string()), attr("fee", fee.to_string()), ]; @@ -542,7 +549,9 @@ pub fn claim_incentives( // update global incentive pool.update_global_incentives(env.block.time.seconds())?; - let incentives = position.claim_incentives(&pool, &upper_tick, &lower_tick)?; + let incentives = position + .claim_incentives(&pool, &upper_tick, &lower_tick) + .unwrap_or(vec![]); state::update_position(deps.storage, &position)?; POOLS.save(deps.storage, &pool_key_db, &pool)?; @@ -552,13 +561,28 @@ pub fn claim_incentives( asset.transfer(&mut msgs, &info)?; } - let event_attributes = vec![ - attr("action", "claim_incentives"), - attr("owner", info.sender.as_str()), - attr("pool_key", position.pool_key.to_string()), - attr("position_token_id", position.token_id.to_string()), - attr("incentives_info", &format!("{:?}", incentives)), - ]; + let mut event_attributes: Vec = vec![]; + + if incentives.len() > 0 { + event_attributes.append(&mut vec![ + attr( + "incentives_token_address", + incentives + .iter() + .map(|x| x.info.denom()) + .collect::>() + .join(","), + ), + attr( + "incentives_amount", + incentives + .iter() + .map(|x| x.amount.to_string()) + .collect::>() + .join(","), + ), + ]); + } Ok(Response::new() .add_messages(msgs) @@ -599,7 +623,42 @@ pub fn remove_position( // calculate pending incentives let incentives = position.claim_incentives(&pool, &upper_tick, &lower_tick)?; - let (amount_x, amount_y, liquidity_x, liquidity_y, deinitialize_lower_tick, deinitialize_upper_tick) = position.remove( + let mut event_attributes: Vec = vec![attr("action", "remove_position")]; + + if incentives.len() > 0 { + event_attributes.append(&mut vec![ + // attr("_contract_address", env.contract.address.to_string()), + attr( + "incentives_token_address", + incentives + .iter() + .map(|x| x.info.denom()) + .collect::>() + .join(","), + ), + attr( + "incentives_amount", + incentives + .iter() + .map(|x| x.amount.to_string()) + .collect::>() + .join(","), + ), + ]); + } + + let ( + amount_x, + amount_y, + liquidity_x, + liquidity_y, + fee_x, + fee_y, + after_liquidity, + ater_tick_index, + deinitialize_lower_tick, + deinitialize_upper_tick, + ) = position.remove( &mut pool, current_timestamp, &mut lower_tick, @@ -607,6 +666,14 @@ pub fn remove_position( position.pool_key.fee_tier.tick_spacing, )?; + event_attributes.append(&mut vec![ + attr("owner", info.sender.as_str()), + attr("pool_key", position.pool_key.to_string()), + attr("position_token_id", position.token_id.to_string()), + attr("amount_x", fee_x.to_string()), + attr("amount_y", fee_y.to_string()), + ]); + POOLS.save(deps.storage, &pool_key_db, &pool)?; if deinitialize_lower_tick { @@ -650,15 +717,19 @@ pub fn remove_position( asset.transfer(&mut msgs, &info)?; } - let event_attributes = vec![ - attr("action", "remove_position"), - attr("owner", info.sender.as_str()), + event_attributes.append(&mut vec![ attr("pool_key", position.pool_key.to_string()), - attr("position_token_id", position.token_id.to_string()), - attr("liquidity", withdrawed_liquidity.get().to_string()), + attr("token_id", position.token_id.to_string()), + attr("owner", info.sender.as_str()), + attr("position_liquidity", withdrawed_liquidity.get().to_string()), + attr("lower_tick", lower_tick.index.to_string()), + attr("upper_tick", upper_tick.index.to_string()), + attr("current_sqrt_price", pool.sqrt_price.get().to_string()), attr("liquidity_x", liquidity_x.to_string()), attr("liquidity_y", liquidity_y.to_string()), - ]; + attr("after_liquidity ", after_liquidity.get().to_string()), + attr("ater_tick_index", ater_tick_index.to_string()), + ]); Ok(Response::new() .add_messages(msgs) @@ -1012,7 +1083,7 @@ pub fn create_incentive( id, reward_per_sec, reward_token: reward_token.clone(), - remaining: remaining, + remaining, start_timestamp: start_timestamp.unwrap_or(env.block.time.seconds()), incentive_growth_global: FeeGrowth(0), last_updated: env.block.time.seconds(), @@ -1024,7 +1095,7 @@ pub fn create_incentive( Ok(Response::new().add_attributes(vec![ ("action", "create_incentive"), ("pool", &pool_key.to_string()), - ("reward_token", &format!("{:?}", reward_token)), + ("reward_token", &reward_token.denom()), ("total_reward", &remaining.to_string()), ("reward_per_sec", &reward_per_sec.to_string()), ( @@ -1075,5 +1146,8 @@ pub fn update_incentive( ("action", "update_incentive"), ("pool", &pool_key.to_string()), ("record_id", &record_id.to_string()), + ("remaining_reward", &remaining_reward.unwrap_or_default().to_string()), + ("start_timestamp", &start_timestamp.unwrap_or_default().to_string()), + ("reward_per_sec", &reward_per_sec.unwrap_or_default().to_string()), ])) } diff --git a/contracts/oraiswap-v3/src/storage/position.rs b/contracts/oraiswap-v3/src/storage/position.rs index ae5414b..071268a 100644 --- a/contracts/oraiswap-v3/src/storage/position.rs +++ b/contracts/oraiswap-v3/src/storage/position.rs @@ -310,7 +310,7 @@ impl Position { lower_tick: &mut Tick, upper_tick: &mut Tick, tick_spacing: u16, - ) -> Result<(TokenAmount, TokenAmount, TokenAmount, TokenAmount, bool, bool), ContractError> { + ) -> Result<(TokenAmount, TokenAmount, TokenAmount, TokenAmount, TokenAmount, TokenAmount, Liquidity, i32, bool, bool), ContractError> { let liquidity_delta = self.liquidity; let (mut amount_x, mut amount_y) = self.modify( pool, @@ -335,6 +335,10 @@ impl Position { amount_y, liquidity_x, liquidity_y, + self.tokens_owed_x, + self.tokens_owed_y, + pool.liquidity, + pool.current_tick_index, deinitialize_lower_tick, deinitialize_upper_tick, )) diff --git a/contracts/oraiswap-v3/src/tests/claim.rs b/contracts/oraiswap-v3/src/tests/claim.rs index d834a7c..e01f20b 100644 --- a/contracts/oraiswap-v3/src/tests/claim.rs +++ b/contracts/oraiswap-v3/src/tests/claim.rs @@ -2,7 +2,13 @@ use cosmwasm_std::Timestamp; use decimal::{Decimal, Factories}; use crate::{ - interface::AssetInfo, liquidity::Liquidity, percentage::Percentage, sqrt_price::{self, calculate_sqrt_price, SqrtPrice}, tests::helper::{macros::*, MockApp}, token_amount::TokenAmount, FeeTier, PoolKey + interface::AssetInfo, + liquidity::Liquidity, + percentage::Percentage, + sqrt_price::{self, calculate_sqrt_price, SqrtPrice}, + tests::helper::{macros::*, MockApp}, + token_amount::TokenAmount, + FeeTier, PoolKey, }; #[test] @@ -61,6 +67,9 @@ fn claim_both_fee_and_incentives() { let (token_x, token_y, token_z) = create_3_tokens!(app, initial_amount, initial_amount, initial_amount); mint!(app, token_z, dex_raw, initial_amount, "alice").unwrap(); + let (token_a, token_b) = create_tokens!(app, initial_amount, initial_amount); + mint!(app, token_a, dex_raw, initial_amount, "alice").unwrap(); + mint!(app, token_b, dex_raw, initial_amount, "alice").unwrap(); let fee_tier = FeeTier::new(protocol_fee, 1).unwrap(); @@ -82,9 +91,15 @@ fn claim_both_fee_and_incentives() { let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier).unwrap(); - let reward_token = AssetInfo::Token { + let reward_token_1 = AssetInfo::Token { contract_addr: token_z.clone(), }; + let reward_token_2 = AssetInfo::Token { + contract_addr: token_a.clone(), + }; + let reward_token_3 = AssetInfo::Token { + contract_addr: token_b.clone(), + }; let total_reward = Some(TokenAmount::from_integer(1000000000)); let reward_per_sec = TokenAmount(100); let start_timestamp: Option = None; @@ -111,7 +126,29 @@ fn claim_both_fee_and_incentives() { app, dex, pool_key, - reward_token.clone(), + reward_token_1.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + create_incentive!( + app, + dex, + pool_key, + reward_token_2.clone(), + total_reward, + reward_per_sec, + start_timestamp, + "alice" + ) + .unwrap(); + create_incentive!( + app, + dex, + pool_key, + reward_token_3.clone(), total_reward, reward_per_sec, start_timestamp, @@ -127,7 +164,17 @@ fn claim_both_fee_and_incentives() { // swap to increase fee growth mint!(app, token_x, "bob", initial_amount, "alice").unwrap(); approve!(app, token_x, dex, initial_amount, "bob").unwrap(); - swap!(app, dex, pool_key, true, TokenAmount(1000), true, sqrt_price::get_min_sqrt_price(fee_tier.tick_spacing), "bob").unwrap(); + swap!( + app, + dex, + pool_key, + true, + TokenAmount(1000), + true, + sqrt_price::get_min_sqrt_price(fee_tier.tick_spacing), + "bob" + ) + .unwrap(); // increase time to have incentives let mut block_info = app.app.block_info(); @@ -149,9 +196,8 @@ fn claim_both_fee_and_incentives() { // incentive assert assert!(before_dex_balance_token_z.gt(&after_dex_balance_token_z)); assert!(before_user_balance_token_z.lt(&after_user_balance_token_z)); - assert!( - (before_user_balance_token_z + before_dex_balance_token_z).eq(&(after_user_balance_token_z + after_dex_balance_token_z)) - ); + assert!((before_user_balance_token_z + before_dex_balance_token_z) + .eq(&(after_user_balance_token_z + after_dex_balance_token_z))); assert!((after_user_balance_token_z - before_user_balance_token_z).le(&total_emit)); // fee claimed assert From f9511229804b2a590020b7d8a0d16068c3569282 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Wed, 31 Jul 2024 10:29:55 +0700 Subject: [PATCH 42/47] chore: refactor --- .../oraiswap-v3/src/entrypoints/execute.rs | 21 +++++++++++++------ contracts/oraiswap-v3/src/storage/position.rs | 18 ++++++++++++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index d5c4042..ac90ef3 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -418,7 +418,7 @@ pub fn swap_route( .add_messages(msgs) .add_attribute("action", "swap_route") .add_attribute("amount_out", amount_out.to_string()) - .add_attribute("swap_hop", &format!("{:?}", swaps))) + .add_attribute("swap_hop", format!("{:?}", swaps))) } /// Transfers a position between users. @@ -563,7 +563,7 @@ pub fn claim_incentives( let mut event_attributes: Vec = vec![]; - if incentives.len() > 0 { + if !incentives.is_empty() { event_attributes.append(&mut vec![ attr( "incentives_token_address", @@ -625,7 +625,7 @@ pub fn remove_position( let mut event_attributes: Vec = vec![attr("action", "remove_position")]; - if incentives.len() > 0 { + if !incentives.is_empty() { event_attributes.append(&mut vec![ // attr("_contract_address", env.contract.address.to_string()), attr( @@ -1146,8 +1146,17 @@ pub fn update_incentive( ("action", "update_incentive"), ("pool", &pool_key.to_string()), ("record_id", &record_id.to_string()), - ("remaining_reward", &remaining_reward.unwrap_or_default().to_string()), - ("start_timestamp", &start_timestamp.unwrap_or_default().to_string()), - ("reward_per_sec", &reward_per_sec.unwrap_or_default().to_string()), + ( + "remaining_reward", + &remaining_reward.unwrap_or_default().to_string(), + ), + ( + "start_timestamp", + &start_timestamp.unwrap_or_default().to_string(), + ), + ( + "reward_per_sec", + &reward_per_sec.unwrap_or_default().to_string(), + ), ])) } diff --git a/contracts/oraiswap-v3/src/storage/position.rs b/contracts/oraiswap-v3/src/storage/position.rs index 071268a..19cd4e6 100644 --- a/contracts/oraiswap-v3/src/storage/position.rs +++ b/contracts/oraiswap-v3/src/storage/position.rs @@ -310,7 +310,21 @@ impl Position { lower_tick: &mut Tick, upper_tick: &mut Tick, tick_spacing: u16, - ) -> Result<(TokenAmount, TokenAmount, TokenAmount, TokenAmount, TokenAmount, TokenAmount, Liquidity, i32, bool, bool), ContractError> { + ) -> Result< + ( + TokenAmount, + TokenAmount, + TokenAmount, + TokenAmount, + TokenAmount, + TokenAmount, + Liquidity, + i32, + bool, + bool, + ), + ContractError, + > { let liquidity_delta = self.liquidity; let (mut amount_x, mut amount_y) = self.modify( pool, @@ -335,7 +349,7 @@ impl Position { amount_y, liquidity_x, liquidity_y, - self.tokens_owed_x, + self.tokens_owed_x, self.tokens_owed_y, pool.liquidity, pool.current_tick_index, From b15106fef91b6f3391959b032f1462a279f5f47f Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Wed, 31 Jul 2024 11:26:06 +0700 Subject: [PATCH 43/47] update events --- contracts/oraiswap-v3/src/entrypoints/execute.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index d5c4042..3d6bdc0 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -667,11 +667,8 @@ pub fn remove_position( )?; event_attributes.append(&mut vec![ - attr("owner", info.sender.as_str()), - attr("pool_key", position.pool_key.to_string()), - attr("position_token_id", position.token_id.to_string()), - attr("amount_x", fee_x.to_string()), - attr("amount_y", fee_y.to_string()), + attr("fee_x", fee_x.to_string()), + attr("fee_y", fee_y.to_string()), ]); POOLS.save(deps.storage, &pool_key_db, &pool)?; @@ -728,7 +725,7 @@ pub fn remove_position( attr("liquidity_x", liquidity_x.to_string()), attr("liquidity_y", liquidity_y.to_string()), attr("after_liquidity ", after_liquidity.get().to_string()), - attr("ater_tick_index", ater_tick_index.to_string()), + attr("after_tick_index", ater_tick_index.to_string()), ]); Ok(Response::new() From 2b11d7f02e603f712999a2209a2a6443d5e5bcbf Mon Sep 17 00:00:00 2001 From: meomeocoj Date: Wed, 31 Jul 2024 12:38:02 +0700 Subject: [PATCH 44/47] feat: add query_all_position --- contracts/oraiswap-v3/src/contract.rs | 7 +- .../oraiswap-v3/src/entrypoints/execute.rs | 2 +- .../oraiswap-v3/src/entrypoints/query.rs | 20 +++- contracts/oraiswap-v3/src/msg.rs | 6 + .../src/tests/get_position_ticks.rs | 112 ++++++++++++++++++ contracts/oraiswap-v3/src/tests/helper.rs | 13 +- 6 files changed, 153 insertions(+), 7 deletions(-) diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index a418b24..ea72564 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -308,10 +308,13 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { QueryMsg::NumTokens {} => to_json_binary(&query_num_tokens(deps)?), QueryMsg::PositionIncentives { owner_id, index } => { to_json_binary(&query_position_incentives(deps, env, owner_id, index)?) - }, + } QueryMsg::PoolsByPoolKeys { pool_keys } => { to_json_binary(&get_pools_with_pool_keys(deps, pool_keys)?) - }, + } + QueryMsg::AllPosition { limit, start_after } => { + to_json_binary(&query_positions(deps, limit, start_after)?) + } } } diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index fe376a8..fe4ae42 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -521,7 +521,7 @@ pub fn claim_fee( attr("amount_y", y.to_string()), ]; - let resp = claim_incentives(deps, env, info, index)?; + let resp: Response = claim_incentives(deps, env, info, index)?; Ok(resp.add_messages(msgs).add_attributes(event_attributes)) } diff --git a/contracts/oraiswap-v3/src/entrypoints/query.rs b/contracts/oraiswap-v3/src/entrypoints/query.rs index 747db9d..0d2d854 100644 --- a/contracts/oraiswap-v3/src/entrypoints/query.rs +++ b/contracts/oraiswap-v3/src/entrypoints/query.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Addr, Deps, Env, Order, StdResult}; +use cosmwasm_std::{Addr, Binary, Deps, Env, Order, StdResult}; use cw_storage_plus::Bound; use crate::{ @@ -9,7 +9,7 @@ use crate::{ }, percentage::Percentage, sqrt_price::{get_max_tick, get_min_tick, SqrtPrice}, - state::{self, CONFIG, MAX_LIMIT}, + state::{self, CONFIG, MAX_LIMIT, POSITIONS}, tick_to_position, token_amount::TokenAmount, ContractError, FeeTier, LiquidityTick, Pool, PoolKey, Position, PositionTick, Tick, CHUNK_SIZE, @@ -134,7 +134,6 @@ pub fn get_pools_with_pool_keys( Ok(pools) } - /// Retrieves listed pools for provided token pair /// - `token_0`: Address of first token /// - `token_1`: Address of second token @@ -558,3 +557,18 @@ pub fn query_position_incentives( Ok(incentives) } + +pub fn query_positions( + deps: Deps, + limit: Option, + start_after: Option, +) -> Result, ContractError> { + let limit = limit.unwrap_or(MAX_LIMIT).min(MAX_LIMIT) as usize; + let start = start_after.map(|x| x.to_vec()).map(Bound::ExclusiveRaw); + Ok(POSITIONS + .range(deps.storage, start, None, Order::Ascending) + .take(limit) + .filter_map(Result::ok) + .map(|(_, position)| position) + .collect::>()) +} diff --git a/contracts/oraiswap-v3/src/msg.rs b/contracts/oraiswap-v3/src/msg.rs index dd99ce6..ae80bac 100644 --- a/contracts/oraiswap-v3/src/msg.rs +++ b/contracts/oraiswap-v3/src/msg.rs @@ -174,6 +174,12 @@ pub enum QueryMsg { offset: Option, }, + #[returns(Vec)] + AllPosition { + limit: Option, + start_after: Option, + }, + #[returns(bool)] FeeTierExist { fee_tier: FeeTier }, diff --git a/contracts/oraiswap-v3/src/tests/get_position_ticks.rs b/contracts/oraiswap-v3/src/tests/get_position_ticks.rs index d6952c8..a5ef4c8 100644 --- a/contracts/oraiswap-v3/src/tests/get_position_ticks.rs +++ b/contracts/oraiswap-v3/src/tests/get_position_ticks.rs @@ -2,6 +2,9 @@ use cosmwasm_std::coin; use cosmwasm_std::Addr; use decimal::{Decimal, Factories}; +use crate::fee_growth::FeeGrowth; +use crate::token_amount::TokenAmount; +use crate::Position; use crate::POSITION_TICK_LIMIT; use crate::{ liquidity::Liquidity, @@ -220,3 +223,112 @@ fn test_get_position_ticks_with_offset() { assert_eq!(result_1[2], result_2[0]); assert_eq!(result_1[3], result_2[1]); } + +#[test] +fn test_query_all_positions() { + let initial_mint = 10u128.pow(10); + let mut app = MockApp::new(&[("alice", &[coin(initial_mint, "orai")])]); + + let dex = app + .create_dex("alice", Percentage::from_scale(1, 2)) + .unwrap(); + + let initial_amount = 10u128.pow(10); + let (token_x, token_y) = create_tokens!(app, initial_amount, initial_amount); + + let fee_tier = FeeTier::new(Percentage::from_scale(1, 2), 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(); + + approve!(app, token_x, dex, 500, "alice").unwrap(); + approve!(app, token_y, dex, 500, "alice").unwrap(); + + let pool_key = PoolKey::new(token_x.to_string(), token_y.to_string(), fee_tier).unwrap(); + create_position!( + app, + dex, + pool_key, + -10, + 10, + Liquidity::new(10), + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + create_position!( + app, + dex, + pool_key, + -100, + 100, + Liquidity::new(10), + SqrtPrice::new(0), + SqrtPrice::max_instance(), + "alice" + ) + .unwrap(); + let positions = app.query_all_positions(dex.as_str(), None, None).unwrap(); + assert_eq!(positions.len(), 2); + assert_eq!( + positions, + [ + Position { + pool_key: PoolKey { + token_x: String::from("contract1"), + token_y: String::from("contract2"), + fee_tier: FeeTier { + fee: Percentage(10000000000), + tick_spacing: 1 + } + }, + liquidity: Liquidity(10), + lower_tick_index: -10, + upper_tick_index: 10, + fee_growth_inside_x: FeeGrowth(0), + fee_growth_inside_y: FeeGrowth(0), + last_block_number: 12353, + tokens_owed_x: TokenAmount(0), + tokens_owed_y: TokenAmount(0), + approvals: vec![], + token_id: 1, + incentives: vec![] + }, + Position { + pool_key: PoolKey { + token_x: String::from("contract1"), + token_y: String::from("contract2"), + fee_tier: FeeTier { + fee: Percentage(10000000000), + tick_spacing: 1 + } + }, + liquidity: Liquidity(10), + lower_tick_index: -100, + upper_tick_index: 100, + fee_growth_inside_x: FeeGrowth(0), + fee_growth_inside_y: FeeGrowth(0), + last_block_number: 12354, + tokens_owed_x: TokenAmount(0), + tokens_owed_y: TokenAmount(0), + token_id: 2, + approvals: vec![], + incentives: vec![] + } + ] + ) +} diff --git a/contracts/oraiswap-v3/src/tests/helper.rs b/contracts/oraiswap-v3/src/tests/helper.rs index 6efc4cf..1545774 100644 --- a/contracts/oraiswap-v3/src/tests/helper.rs +++ b/contracts/oraiswap-v3/src/tests/helper.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Addr, Coin, Event, StdResult, Timestamp}; +use cosmwasm_std::{Addr, Binary, Coin, Event, StdResult, Timestamp}; use cosmwasm_testing_util::{AppResponse, ContractWrapper, MockResult}; use crate::{ @@ -427,6 +427,17 @@ impl MockApp { &[], ) } + pub fn query_all_positions( + &self, + dex: &str, + limit: Option, + start_after: Option, + ) -> StdResult> { + self.query( + Addr::unchecked(dex), + &msg::QueryMsg::AllPosition { limit, start_after }, + ) + } pub fn increase_block_time_by_seconds(&mut self, seconds: u64) { let mut block_info = self.app.app.block_info(); From 7bc8907f26c1ff5f593d8ef191b557c383907549 Mon Sep 17 00:00:00 2001 From: meomeocoj Date: Wed, 31 Jul 2024 12:38:42 +0700 Subject: [PATCH 45/47] chore: remove query_positions to query_all_positions --- contracts/oraiswap-v3/src/contract.rs | 2 +- contracts/oraiswap-v3/src/entrypoints/query.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/oraiswap-v3/src/contract.rs b/contracts/oraiswap-v3/src/contract.rs index ea72564..59765a1 100644 --- a/contracts/oraiswap-v3/src/contract.rs +++ b/contracts/oraiswap-v3/src/contract.rs @@ -313,7 +313,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { to_json_binary(&get_pools_with_pool_keys(deps, pool_keys)?) } QueryMsg::AllPosition { limit, start_after } => { - to_json_binary(&query_positions(deps, limit, start_after)?) + to_json_binary(&query_all_positions(deps, limit, start_after)?) } } } diff --git a/contracts/oraiswap-v3/src/entrypoints/query.rs b/contracts/oraiswap-v3/src/entrypoints/query.rs index 0d2d854..beb7efa 100644 --- a/contracts/oraiswap-v3/src/entrypoints/query.rs +++ b/contracts/oraiswap-v3/src/entrypoints/query.rs @@ -558,7 +558,7 @@ pub fn query_position_incentives( Ok(incentives) } -pub fn query_positions( +pub fn query_all_positions( deps: Deps, limit: Option, start_after: Option, From 8081d69a9374277410ae08539ca63dc83e34c8d2 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Wed, 31 Jul 2024 16:13:43 +0700 Subject: [PATCH 46/47] add events --- contracts/oraiswap-v3/src/entrypoints/execute.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/oraiswap-v3/src/entrypoints/execute.rs b/contracts/oraiswap-v3/src/entrypoints/execute.rs index fe376a8..a652ddc 100644 --- a/contracts/oraiswap-v3/src/entrypoints/execute.rs +++ b/contracts/oraiswap-v3/src/entrypoints/execute.rs @@ -1092,6 +1092,7 @@ pub fn create_incentive( Ok(Response::new().add_attributes(vec![ ("action", "create_incentive"), ("pool", &pool_key.to_string()), + ("record_id", &id.to_string()), ("reward_token", &reward_token.denom()), ("total_reward", &remaining.to_string()), ("reward_per_sec", &reward_per_sec.to_string()), From 8d37109c887345a2b397a73ae355b657276f0104 Mon Sep 17 00:00:00 2001 From: trung2891 Date: Thu, 1 Aug 2024 10:28:33 +0700 Subject: [PATCH 47/47] oraiswap-v3 v0.2.0 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00edc30..ade137e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "decimal" -version = "0.1.0" +version = "0.2.0" dependencies = [ "decimal-core", "integer-sqrt", @@ -672,7 +672,7 @@ dependencies = [ [[package]] name = "decimal-core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "proc-macro2", "quote", @@ -1221,7 +1221,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "oraiswap-v3" -version = "0.1.0" +version = "0.2.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1238,7 +1238,7 @@ dependencies = [ [[package]] name = "oraiswap-v3-wasm" -version = "0.1.0" +version = "0.2.0" dependencies = [ "decimal", "derive_more", diff --git a/Cargo.toml b/Cargo.toml index 37b7f1a..a4c6eed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = ["packages/*", "contracts/*", "wasm"] [workspace.package] -version = "0.1.0" +version = "0.2.0" authors = ["Oraichain Labs"] edition = "2021" license = "MIT"