diff --git a/src/contracts/collections/fee_tiers.rs b/src/contracts/collections/fee_tiers.rs index 83d25952..d9ef6bd7 100644 --- a/src/contracts/collections/fee_tiers.rs +++ b/src/contracts/collections/fee_tiers.rs @@ -1,13 +1,11 @@ +use crate::{math::types::percentage::Percentage, InvariantError}; use ink::storage::Mapping; -use crate::math::types::percentage::Percentage; - #[derive(scale::Decode, scale::Encode, Debug, Copy, Clone, PartialEq)] #[cfg_attr( feature = "std", derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) )] -// key(fee: Percentage, tick_spacing: u16) pub struct FeeTierKey(pub Percentage, pub u16); #[ink::storage_item] @@ -17,13 +15,60 @@ pub struct FeeTiers { } impl FeeTiers { - pub fn get_fee_tier(&self, key: FeeTierKey) -> Option<()> { - self.fee_tiers.get(&key) + pub fn add(&mut self, fee_tier_key: FeeTierKey) -> Result<(), InvariantError> { + self.fee_tiers + .get(&fee_tier_key) + .map_or(Ok(()), |_| Err(InvariantError::FeeTierAlreadyExist))?; + + self.fee_tiers.insert(&fee_tier_key, &()); + Ok(()) + } + + pub fn remove(&mut self, fee_tier_key: FeeTierKey) -> Result<(), InvariantError> { + self.fee_tiers + .get(fee_tier_key) + .ok_or(InvariantError::FeeTierNotFound)?; + + self.fee_tiers.remove(&fee_tier_key); + Ok(()) + } + + pub fn get(&self, fee_tier_key: FeeTierKey) -> Option<()> { + self.fee_tiers.get(fee_tier_key) } - pub fn add_fee_tier(&mut self, key: FeeTierKey) { - self.fee_tiers.insert(&key, &()); +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::math::percentage::Percentage; + use decimal::*; + + #[ink::test] + fn test_add() { + let fee_tiers = &mut FeeTiers::default(); + let fee_tier_key = FeeTierKey(Percentage::new(0), 1); + let new_fee_tier_key = FeeTierKey(Percentage::new(0), 2); + + fee_tiers.add(fee_tier_key).unwrap(); + assert_eq!(fee_tiers.get(fee_tier_key), Some(())); + assert_eq!(fee_tiers.get(new_fee_tier_key), None); + + let result = fee_tiers.add(fee_tier_key); + assert_eq!(result, Err(InvariantError::FeeTierAlreadyExist)); } - pub fn remove_fee_tier(&mut self, key: FeeTierKey) { - self.fee_tiers.remove(&key); + + #[ink::test] + fn test_remove() { + let fee_tiers = &mut FeeTiers::default(); + let fee_tier_key = FeeTierKey(Percentage::new(0), 1); + + fee_tiers.add(fee_tier_key).unwrap(); + + fee_tiers.remove(fee_tier_key).unwrap(); + assert_eq!(fee_tiers.get(fee_tier_key), None); + + let result = fee_tiers.remove(fee_tier_key); + assert_eq!(result, Err(InvariantError::FeeTierNotFound)); } } diff --git a/src/contracts/collections/pools.rs b/src/contracts/collections/pools.rs index d6e91f31..5113b4f3 100644 --- a/src/contracts/collections/pools.rs +++ b/src/contracts/collections/pools.rs @@ -1,6 +1,7 @@ -use crate::contracts::Pool; -use crate::contracts::PoolKey; -use crate::InvariantError; +use crate::{ + contracts::{Pool, PoolKey}, + InvariantError, +}; use ink::storage::Mapping; #[ink::storage_item] @@ -11,14 +12,28 @@ pub struct Pools { impl Pools { pub fn add(&mut self, pool_key: PoolKey, pool: &Pool) -> Result<(), InvariantError> { - if self.pools.get(&pool_key).is_some() { - return Err(InvariantError::PoolAlreadyExist); - } + self.pools + .get(&pool_key) + .map_or(Ok(()), |_| Err(InvariantError::PoolAlreadyExist))?; self.pools.insert(pool_key, pool); Ok(()) } + pub fn update(&mut self, pool_key: PoolKey, pool: &Pool) -> Result<(), InvariantError> { + self.get(pool_key)?; + + self.pools.insert(pool_key, pool); + Ok(()) + } + + pub fn remove(&mut self, pool_key: PoolKey) -> Result<(), InvariantError> { + self.get(pool_key)?; + + self.pools.remove(&pool_key); + Ok(()) + } + pub fn get(&self, pool_key: PoolKey) -> Result { let pool = self .pools @@ -27,22 +42,88 @@ impl Pools { Ok(pool) } +} - pub fn update(&mut self, pool_key: PoolKey, pool: &Pool) -> Result<(), InvariantError> { - self.pools - .get(pool_key) - .ok_or(InvariantError::PoolNotFound)?; +#[cfg(test)] +mod tests { + use super::*; + use crate::{contracts::FeeTier, math::percentage::Percentage}; + use decimal::*; + use ink::primitives::AccountId; - self.pools.insert(pool_key, pool); - Ok(()) + #[ink::test] + fn test_add() { + let pools = &mut Pools::default(); + let token_x = AccountId::from([0x01; 32]); + let token_y = AccountId::from([0x02; 32]); + let fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 1, + }; + let new_fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 2, + }; + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let new_pool_key = PoolKey::new(token_x, token_y, new_fee_tier).unwrap(); + let pool = Pool::default(); + + pools.add(pool_key, &pool).unwrap(); + assert_eq!(pools.get(pool_key), Ok(pool.clone())); + assert_eq!(pools.get(new_pool_key), Err(InvariantError::PoolNotFound)); + + let result = pools.add(pool_key, &pool); + assert_eq!(result, Err(InvariantError::PoolAlreadyExist)); } - pub fn remove(&mut self, pool_key: PoolKey) -> Result<(), InvariantError> { - self.pools - .get(pool_key) - .ok_or(InvariantError::PoolNotFound)?; + #[ink::test] + fn test_update() { + let pools = &mut Pools::default(); + let token_x = AccountId::from([0x01; 32]); + let token_y = AccountId::from([0x02; 32]); + let fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 1, + }; + let new_fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 2, + }; + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let new_pool_key = PoolKey::new(token_x, token_y, new_fee_tier).unwrap(); + let pool = Pool::default(); + let new_pool = Pool { + current_tick_index: 1, + ..Pool::default() + }; - self.pools.remove(&pool_key); - Ok(()) + pools.add(pool_key, &pool).unwrap(); + + pools.update(pool_key, &new_pool).unwrap(); + assert_eq!(pools.get(pool_key), Ok(new_pool.clone())); + + let result = pools.update(new_pool_key, &new_pool); + assert_eq!(result, Err(InvariantError::PoolNotFound)); + } + + #[ink::test] + fn test_remove() { + let pools = &mut Pools::default(); + let token_x = AccountId::from([0x01; 32]); + let token_y = AccountId::from([0x02; 32]); + let fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 1, + }; + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let pool = Pool::default(); + + pools.add(pool_key, &pool).unwrap(); + + pools.remove(pool_key).unwrap(); + assert_eq!(pools.get(pool_key), Err(InvariantError::PoolNotFound)); + + let result = pools.remove(pool_key); + assert_eq!(result, Err(InvariantError::PoolNotFound)); } } diff --git a/src/contracts/collections/positions.rs b/src/contracts/collections/positions.rs index 760fcf56..71453111 100644 --- a/src/contracts/collections/positions.rs +++ b/src/contracts/collections/positions.rs @@ -9,11 +9,11 @@ pub struct Positions { } impl Positions { - pub fn add(&mut self, account_id: AccountId, position: Position) { + pub fn add(&mut self, account_id: AccountId, position: &Position) { let positions_length = self.get_length(account_id); self.positions - .insert((account_id, positions_length), &position); + .insert((account_id, positions_length), position); self.positions_length .insert(account_id, &(positions_length + 1)); @@ -42,12 +42,7 @@ impl Positions { index: u32, ) -> Result { let positions_length = self.get_length(account_id); - - if index >= positions_length { - return Err(InvariantError::PositionNotFound); - } - - let position = self.positions.get((account_id, index)); + let position = self.get(account_id, index)?; if index < positions_length - 1 { let last_position = self @@ -62,7 +57,7 @@ impl Positions { self.positions_length .insert(account_id, &(positions_length - 1)); - Ok(position.unwrap()) + Ok(position) } pub fn transfer( @@ -72,22 +67,26 @@ impl Positions { receiver_account_id: AccountId, ) -> Result<(), InvariantError> { let position = self.remove(account_id, index)?; - self.add(receiver_account_id, position); + self.add(receiver_account_id, &position); Ok(()) } + pub fn get(&self, account_id: AccountId, index: u32) -> Result { + let position = self + .positions + .get((account_id, index)) + .ok_or(InvariantError::PositionNotFound)?; + + Ok(position) + } + pub fn get_all(&self, account_id: AccountId) -> Vec { (0..self.get_length(account_id)) .map(|index| self.positions.get((account_id, index)).unwrap()) .collect() } - pub fn get(&mut self, account_id: AccountId, index: u32) -> Option { - let position = self.positions.get((account_id, index)); - position - } - pub fn get_length(&self, account_id: AccountId) -> u32 { let positions_length = self.positions_length.get(account_id).unwrap_or(0); positions_length @@ -109,11 +108,14 @@ mod tests { ..Position::default() }; - positions.add(account_id, position); - positions.add(account_id, new_position); - assert_eq!(positions.get(account_id, 0), Some(position)); - assert_eq!(positions.get(account_id, 1), Some(new_position)); - assert_eq!(positions.get(account_id, 2), None); + positions.add(account_id, &position); + positions.add(account_id, &new_position); + assert_eq!(positions.get(account_id, 0), Ok(position)); + assert_eq!(positions.get(account_id, 1), Ok(new_position)); + assert_eq!( + positions.get(account_id, 2), + Err(InvariantError::PositionNotFound) + ); assert_eq!(positions.get_length(account_id), 2); } @@ -128,10 +130,10 @@ mod tests { ..Position::default() }; - positions.add(account_id, position); + positions.add(account_id, &position); positions.update(account_id, 0, &new_position).unwrap(); - assert_eq!(positions.get(account_id, 0), Some(new_position)); + assert_eq!(positions.get(account_id, 0), Ok(new_position)); assert_eq!(positions.get_length(account_id), 1); let result = positions.update(account_id, 1, &new_position); @@ -149,17 +151,20 @@ mod tests { ..Position::default() }; - positions.add(account_id, position); - positions.add(account_id, new_position); + positions.add(account_id, &position); + positions.add(account_id, &new_position); let result = positions.remove(account_id, 0); assert_eq!(result, Ok(position)); - assert_eq!(positions.get(account_id, 0), Some(new_position)); + assert_eq!(positions.get(account_id, 0), Ok(new_position)); assert_eq!(positions.get_length(account_id), 1); let result = positions.remove(account_id, 0); assert_eq!(result, Ok(new_position)); - assert_eq!(positions.get(account_id, 0), None); + assert_eq!( + positions.get(account_id, 0), + Err(InvariantError::PositionNotFound) + ); assert_eq!(positions.get_length(account_id), 0); let result = positions.remove(account_id, 0); @@ -173,14 +178,17 @@ mod tests { let receiver_account_id = AccountId::from([0x02; 32]); let position = Position::default(); - positions.add(account_id, position); + positions.add(account_id, &position); positions .transfer(account_id, 0, receiver_account_id) .unwrap(); - assert_eq!(positions.get(account_id, 0), None); + assert_eq!( + positions.get(account_id, 0), + Err(InvariantError::PositionNotFound) + ); assert_eq!(positions.get_length(account_id), 0); - assert_eq!(positions.get(receiver_account_id, 0), Some(position)); + assert_eq!(positions.get(receiver_account_id, 0), Ok(position)); assert_eq!(positions.get_length(receiver_account_id), 1); let result = positions.transfer(account_id, 0, receiver_account_id); @@ -203,8 +211,8 @@ mod tests { assert_eq!(result.len(), 0); assert_eq!(positions.get_length(account_id), 0); - positions.add(account_id, position); - positions.add(account_id, new_position); + positions.add(account_id, &position); + positions.add(account_id, &new_position); let result = positions.get_all(account_id); assert_eq!(result, vec![position, new_position]); @@ -226,8 +234,8 @@ mod tests { let result = positions.get_length(account_id); assert_eq!(result, 0); - positions.add(account_id, position); - positions.add(account_id, new_position); + positions.add(account_id, &position); + positions.add(account_id, &new_position); let result = positions.get_length(account_id); assert_eq!(result, 2); diff --git a/src/contracts/collections/ticks.rs b/src/contracts/collections/ticks.rs index 13c5f3fa..5a849ed2 100644 --- a/src/contracts/collections/ticks.rs +++ b/src/contracts/collections/ticks.rs @@ -1,8 +1,9 @@ +use crate::{ + contracts::{PoolKey, Tick}, + InvariantError, +}; use ink::storage::Mapping; -use crate::contracts::PoolKey; -use crate::contracts::Tick; -use crate::InvariantError; #[ink::storage_item] #[derive(Debug, Default)] pub struct Ticks { @@ -10,35 +11,119 @@ pub struct Ticks { } impl Ticks { - pub fn get_tick(&self, key: PoolKey, index: i32) -> Option { - self.ticks.get(&(key, index)) - } - // pub fn update_tick(&mut self, key: PoolKey, index: i32, tick: Tick) {} - pub fn remove_tick(&mut self, key: PoolKey, index: i32) -> Result<(), InvariantError> { + pub fn add( + &mut self, + pool_key: PoolKey, + index: i32, + tick: &Tick, + ) -> Result<(), InvariantError> { self.ticks - .get(&(key, index)) - .ok_or(InvariantError::TickNotFound)?; + .get(&(pool_key, index)) + .map_or(Ok(()), |_| Err(InvariantError::TickAlreadyExist))?; - self.ticks.remove(&(key, index)); + self.ticks.insert(&(pool_key, index), tick); Ok(()) } - pub fn add_tick(&mut self, key: PoolKey, index: i32, tick: Tick) { - self.ticks.insert(&(key, index), &tick); - } - - pub fn update_tick( + pub fn update( &mut self, - key: PoolKey, + pool_key: PoolKey, index: i32, tick: &Tick, ) -> Result<(), InvariantError> { - self.ticks - .get(&(key, index)) - .ok_or(InvariantError::TickNotFound)?; + self.get(pool_key, index)?; + + self.ticks.insert((&pool_key, index), tick); + Ok(()) + } - self.ticks.insert((&key, index), tick); + pub fn remove(&mut self, pool_key: PoolKey, index: i32) -> Result<(), InvariantError> { + self.get(pool_key, index)?; + self.ticks.remove(&(pool_key, index)); Ok(()) } + + pub fn get(&self, pool_key: PoolKey, index: i32) -> Result { + let tick = self + .ticks + .get(&(pool_key, index)) + .ok_or(InvariantError::TickNotFound)?; + + Ok(tick) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{contracts::FeeTier, math::percentage::Percentage}; + use decimal::*; + use ink::primitives::AccountId; + + #[ink::test] + fn test_add() { + let ticks = &mut Ticks::default(); + let token_x = AccountId::from([0x01; 32]); + let token_y = AccountId::from([0x02; 32]); + let fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 1, + }; + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let tick = Tick::default(); + + ticks.add(pool_key, 0, &tick).unwrap(); + assert_eq!(ticks.get(pool_key, 0), Ok(tick)); + assert_eq!(ticks.get(pool_key, 1), Err(InvariantError::TickNotFound)); + + // let result = ticks.add(pool_key, 0, &tick); + // assert_eq!(result, Err(InvariantError::TickAlreadyExist)); + } + + #[ink::test] + fn test_update() { + let ticks = &mut Ticks::default(); + let token_x = AccountId::from([0x01; 32]); + let token_y = AccountId::from([0x02; 32]); + let fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 1, + }; + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let tick = Tick::default(); + let new_tick = Tick { + seconds_outside: 1, + ..Tick::default() + }; + + ticks.add(pool_key, 0, &tick).unwrap(); + + ticks.update(pool_key, 0, &new_tick).unwrap(); + assert_eq!(ticks.get(pool_key, 0), Ok(new_tick)); + + let result = ticks.update(pool_key, 1, &new_tick); + assert_eq!(result, Err(InvariantError::TickNotFound)); + } + + #[ink::test] + fn test_remove() { + let ticks = &mut Ticks::default(); + let token_x = AccountId::from([0x01; 32]); + let token_y = AccountId::from([0x02; 32]); + let fee_tier = FeeTier { + fee: Percentage::new(0), + tick_spacing: 1, + }; + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let tick = Tick::default(); + + ticks.add(pool_key, 0, &tick).unwrap(); + + ticks.remove(pool_key, 0).unwrap(); + assert_eq!(ticks.get(pool_key, 0), Err(InvariantError::TickNotFound)); + + let result = ticks.remove(pool_key, 0); + assert_eq!(result, Err(InvariantError::TickNotFound)); + } } diff --git a/src/contracts/entrypoints.rs b/src/contracts/entrypoints.rs index 21cc5a57..7d105d6f 100644 --- a/src/contracts/entrypoints.rs +++ b/src/contracts/entrypoints.rs @@ -79,7 +79,7 @@ pub trait Invariant { fn transfer_position(&mut self, index: u32, receiver: AccountId) -> Result<(), InvariantError>; #[ink(message)] - fn get_position(&mut self, index: u32) -> Option; + fn get_position(&mut self, index: u32) -> Result; #[ink(message)] fn get_all_positions(&mut self) -> Vec; @@ -125,7 +125,7 @@ pub trait Invariant { ) -> Result; #[ink(message)] - fn get_tick(&self, key: PoolKey, index: i32) -> Option; + fn get_tick(&self, key: PoolKey, index: i32) -> Result; #[ink(message)] fn get_tickmap_bit(&self, key: PoolKey, index: i32) -> bool; diff --git a/src/lib.rs b/src/lib.rs index 62faf352..6a31add8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,7 @@ pub enum InvariantError { PriceLimitReached, NoGainSwap, InvalidTickSpacing, - FeeTierAlreadyAdded, + FeeTierAlreadyExist, UnauthorizedFeeReceriver, ZeroLiquidity, TransferError, @@ -175,13 +175,8 @@ pub mod contract { let pool = self.pools.get(pool_key)?; - let tick_option = self.ticks.get_tick(pool_key, index); - if tick_option.is_some() { - return Err(InvariantError::TickAlreadyExist); - } - let tick = Tick::create(index, &pool, current_timestamp); - self.ticks.add_tick(pool_key, index, tick); + self.ticks.add(pool_key, index, &tick)?; self.tickmap .flip(true, index, pool_key.fee_tier.tick_spacing, pool_key); @@ -272,7 +267,7 @@ pub mod contract { let update_limiting_tick = limiting_tick.map(|(index, bool)| { if bool { - tick = self.ticks.get_tick(pool_key, index).unwrap(); + tick = self.ticks.get(pool_key, index).unwrap(); (index, Some(&mut tick)) } else { (index, None) @@ -314,7 +309,7 @@ pub mod contract { } fn remove_tick(&mut self, key: PoolKey, index: i32) { - self.ticks.remove_tick(key, index); + self.ticks.remove(key, index); } fn remove_pool(&mut self, key: PoolKey) { @@ -324,7 +319,7 @@ pub mod contract { // Ticks fn add_tick(&mut self, key: PoolKey, index: i32, tick: Tick) { - self.ticks.add_tick(key, index, tick); + self.ticks.add(key, index, &tick); } fn emit_swap_event( @@ -526,13 +521,13 @@ pub mod contract { let mut lower_tick = self .ticks - .get_tick(pool_key, lower_tick) - .unwrap_or_else(|| Self::create_tick(self, pool_key, lower_tick).unwrap()); + .get(pool_key, lower_tick) + .unwrap_or_else(|_| Self::create_tick(self, pool_key, lower_tick).unwrap()); let mut upper_tick = self .ticks - .get_tick(pool_key, upper_tick) - .unwrap_or_else(|| Self::create_tick(self, pool_key, upper_tick).unwrap()); + .get(pool_key, upper_tick) + .unwrap_or_else(|_| Self::create_tick(self, pool_key, upper_tick).unwrap()); let (position, x, y) = Position::create( &mut pool, @@ -549,10 +544,10 @@ pub mod contract { self.pools.update(pool_key, &pool)?; - self.positions.add(caller, position); + self.positions.add(caller, &position); - self.ticks.add_tick(pool_key, lower_tick.index, lower_tick); - self.ticks.add_tick(pool_key, upper_tick.index, upper_tick); + self.ticks.update(pool_key, lower_tick.index, &lower_tick)?; + self.ticks.update(pool_key, upper_tick.index, &upper_tick)?; let mut token_x: contract_ref!(PSP22) = pool_key.token_x.into(); token_x @@ -590,7 +585,7 @@ pub mod contract { self.calculate_swap(pool_key, x_to_y, amount, by_amount_in, sqrt_price_limit)?; for tick in calculate_swap_result.ticks.iter() { - self.ticks.update_tick(pool_key, tick.index, tick); + self.ticks.update(pool_key, tick.index, tick); } self.pools.update(pool_key, &calculate_swap_result.pool)?; @@ -745,7 +740,7 @@ pub mod contract { // } #[ink(message)] - fn get_position(&mut self, index: u32) -> Option { + fn get_position(&mut self, index: u32) -> Result { let caller = self.env().caller(); self.positions.get(caller, index) @@ -767,20 +762,11 @@ pub mod contract { let caller = self.env().caller(); let current_timestamp = self.env().block_timestamp(); - let mut position = self - .positions - .get(caller, index) - .ok_or(InvariantError::PositionNotFound)?; + let mut position = self.positions.get(caller, index)?; - let lower_tick = self - .ticks - .get_tick(pool_key, position.lower_tick_index) - .ok_or(InvariantError::TickNotFound)?; + let lower_tick = self.ticks.get(pool_key, position.lower_tick_index)?; - let upper_tick = self - .ticks - .get_tick(pool_key, position.upper_tick_index) - .ok_or(InvariantError::TickNotFound)?; + let upper_tick = self.ticks.get(pool_key, position.upper_tick_index)?; let pool = self.pools.get(pool_key)?; @@ -798,20 +784,15 @@ pub mod contract { let caller = self.env().caller(); let current_timestamp = self.env().block_timestamp(); - let mut position = self - .positions - .get(caller, index) - .ok_or(InvariantError::PositionNotFound)?; + let mut position = self.positions.get(caller, index)?; let mut lower_tick = self .ticks - .get_tick(position.pool_key, position.lower_tick_index) - .ok_or(InvariantError::TickNotFound)?; + .get(position.pool_key, position.lower_tick_index)?; let mut upper_tick = self .ticks - .get_tick(position.pool_key, position.upper_tick_index) - .ok_or(InvariantError::TickNotFound)?; + .get(position.pool_key, position.upper_tick_index)?; let mut pool = self.pools.get(position.pool_key)?; @@ -825,9 +806,9 @@ pub mod contract { self.positions.update(caller, index, &position); self.pools.update(position.pool_key, &pool)?; self.ticks - .update_tick(position.pool_key, upper_tick.index, &upper_tick)?; + .update(position.pool_key, upper_tick.index, &upper_tick)?; self.ticks - .update_tick(position.pool_key, lower_tick.index, &lower_tick)?; + .update(position.pool_key, lower_tick.index, &lower_tick)?; if x.get() > 0 { let mut token_x: contract_ref!(PSP22) = position.pool_key.token_x.into(); @@ -854,20 +835,15 @@ pub mod contract { let caller = self.env().caller(); let current_timestamp = self.env().block_timestamp(); - let mut position = self - .positions - .get(caller, index) - .ok_or(InvariantError::PositionNotFound)?; + let mut position = self.positions.get(caller, index)?; let mut lower_tick = self .ticks - .get_tick(position.pool_key, position.lower_tick_index) - .ok_or(InvariantError::TickNotFound)?; + .get(position.pool_key, position.lower_tick_index)?; let mut upper_tick = self .ticks - .get_tick(position.pool_key, position.upper_tick_index) - .ok_or(InvariantError::TickNotFound)?; + .get(position.pool_key, position.upper_tick_index)?; let pool = &mut self.pools.get(position.pool_key)?; @@ -890,11 +866,11 @@ pub mod contract { position.pool_key, ); self.ticks - .remove_tick(position.pool_key, position.lower_tick_index) + .remove(position.pool_key, position.lower_tick_index) .unwrap(); } else { self.ticks - .update_tick(position.pool_key, position.lower_tick_index, &lower_tick) + .update(position.pool_key, position.lower_tick_index, &lower_tick) .unwrap(); } @@ -906,11 +882,11 @@ pub mod contract { position.pool_key, ); self.ticks - .remove_tick(position.pool_key, position.upper_tick_index) + .remove(position.pool_key, position.upper_tick_index) .unwrap(); } else { self.ticks - .update_tick(position.pool_key, position.upper_tick_index, &upper_tick) + .update(position.pool_key, position.upper_tick_index, &upper_tick) .unwrap(); } @@ -950,10 +926,11 @@ pub mod contract { } let fee_tier_key = FeeTierKey(fee_tier.fee, fee_tier.tick_spacing); - if self.fee_tiers.get_fee_tier(fee_tier_key).is_some() { - Err(InvariantError::FeeTierAlreadyAdded) + + if self.fee_tiers.get(fee_tier_key).is_some() { + return Err(InvariantError::FeeTierAlreadyExist); } else { - self.fee_tiers.add_fee_tier(fee_tier_key); + self.fee_tiers.add(fee_tier_key); self.fee_tier_keys.push(fee_tier_key); Ok(()) } @@ -961,12 +938,12 @@ pub mod contract { #[ink(message)] fn get_fee_tier(&self, key: FeeTierKey) -> Option<()> { - self.fee_tiers.get_fee_tier(key) + self.fee_tiers.get(key) } #[ink(message)] fn remove_fee_tier(&mut self, key: FeeTierKey) { - self.fee_tiers.remove_fee_tier(key); + self.fee_tiers.remove(key); self.fee_tier_keys.retain(|&x| x != key); } @@ -983,7 +960,7 @@ pub mod contract { let fee_tier_key = FeeTierKey(fee_tier.fee, fee_tier.tick_spacing); self.fee_tiers - .get_fee_tier(fee_tier_key) + .get(fee_tier_key) .ok_or(InvariantError::FeeTierNotFound)?; let pool_key = PoolKey::new(token_0, token_1, fee_tier)?; @@ -1003,18 +980,142 @@ pub mod contract { fee_tier: FeeTier, ) -> Result { let key: PoolKey = PoolKey::new(token_0, token_1, fee_tier)?; - self.pools.get(key) + let pool = self.pools.get(key)?; + + Ok(pool) + } + + fn remove_pool(&mut self, key: PoolKey) { + self.pools.remove(key); + self.pool_keys.retain(|&x| x != key); + } + + // Ticks + fn add_tick(&mut self, key: PoolKey, index: i32, tick: Tick) { + self.ticks.add(key, index, &tick); } #[ink(message)] - fn get_tick(&self, key: PoolKey, index: i32) -> Option { - self.ticks.get_tick(key, index) + fn get_tick(&self, key: PoolKey, index: i32) -> Result { + self.ticks.get(key, index) } #[ink(message)] fn get_tickmap_bit(&self, key: PoolKey, index: i32) -> bool { self.tickmap.get(index, key.fee_tier.tick_spacing, key) } + fn remove_tick(&mut self, key: PoolKey, index: i32) { + self.ticks.remove(key, index); + } + + fn emit_swap_event( + &self, + address: AccountId, + pool: PoolKey, + amount_in: TokenAmount, + amount_out: TokenAmount, + fee: TokenAmount, + start_sqrt_price: SqrtPrice, + target_sqrt_price: SqrtPrice, + x_to_y: bool, + ) { + let timestamp = self.get_timestamp(); + ink::codegen::EmitEvent::::emit_event( + self.env(), + SwapEvent { + timestamp, + address, + pool, + amount_in, + amount_out, + fee, + start_sqrt_price, + target_sqrt_price, + x_to_y, + }, + ); + } + fn emit_create_position_event( + &self, + address: AccountId, + pool: PoolKey, + liquidity: Liquidity, + lower_tick: i32, + upper_tick: i32, + current_sqrt_price: SqrtPrice, + ) { + let timestamp = self.get_timestamp(); + ink::codegen::EmitEvent::::emit_event( + self.env(), + CreatePositionEvent { + timestamp, + address, + pool, + liquidity, + lower_tick, + upper_tick, + current_sqrt_price, + }, + ); + } + fn emit_remove_position_event( + &self, + address: AccountId, + pool: PoolKey, + liquidity: Liquidity, + lower_tick: i32, + upper_tick: i32, + current_sqrt_price: SqrtPrice, + ) { + let timestamp = self.get_timestamp(); + ink::codegen::EmitEvent::::emit_event( + self.env(), + RemovePositionEvent { + timestamp, + address, + pool, + liquidity, + lower_tick, + upper_tick, + current_sqrt_price, + }, + ); + } + fn emit_cross_tick_event(&self, address: AccountId, pool: PoolKey, index: i32) { + let timestamp = self.get_timestamp(); + ink::codegen::EmitEvent::::emit_event( + self.env(), + CrossTickEvent { + timestamp, + address, + pool, + index, + }, + ); + } + + fn get_timestamp(&self) -> u64 { + self.env().block_timestamp() + } + + fn _order_tokens( + &self, + token_0: AccountId, + token_1: AccountId, + balance_0: Balance, + balance_1: Balance, + ) -> OrderPair { + match token_0.lt(&token_1) { + true => OrderPair { + x: (token_0, balance_0), + y: (token_1, balance_1), + }, + false => OrderPair { + x: (token_1, balance_1), + y: (token_0, balance_0), + }, + } + } } #[cfg(test)] @@ -1154,10 +1255,10 @@ pub mod contract { let index = 10i32; contract.add_tick(pool_key, index, tick); let recieved_tick = contract.get_tick(pool_key, index); - assert_eq!(Some(tick), recieved_tick); + assert_eq!(Ok(tick), recieved_tick); contract.remove_tick(pool_key, index); let recieved_tick = contract.get_tick(pool_key, index); - assert_eq!(None, recieved_tick); + assert_eq!(Err(InvariantError::TickNotFound), recieved_tick); } } @@ -3089,8 +3190,8 @@ pub mod contract { assert_eq!(dex_y_before_remove - dex_y, expected_withdrawn_y); // Check ticks - assert_eq!(lower_tick, None); - assert_eq!(upper_tick, None); + assert_eq!(lower_tick, Err(InvariantError::TickNotFound)); + assert_eq!(upper_tick, Err(InvariantError::TickNotFound)); // Check tickmap assert!(!lower_tick_bit); diff --git a/src/test_helpers/lib.rs b/src/test_helpers/lib.rs index fac4e25c..fcfac3ce 100644 --- a/src/test_helpers/lib.rs +++ b/src/test_helpers/lib.rs @@ -616,9 +616,8 @@ macro_rules! get_tick { let _msg = build_message::<$dex>($dex_address.clone()) .call(|contract| contract.get_tick($pool_key, $index)); $client - .call(&$caller, _msg, 0, None) + .call_dry_run(&$caller, &_msg, 0, None) .await - .expect("Tick recieving failed") .return_value() }}; }