From 8ed31d0a4783b2833ca9189a0698a114cf5803f0 Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 12 Dec 2023 14:26:21 +0100 Subject: [PATCH 1/5] Added tests --- src/e2e/mod.rs | 15 ++- src/e2e/protocol_fee.rs | 289 ++++++++++++++++++++++++++++++++++++++++ src/token.rs | 20 +-- 3 files changed, 307 insertions(+), 17 deletions(-) create mode 100644 src/e2e/protocol_fee.rs diff --git a/src/e2e/mod.rs b/src/e2e/mod.rs index 9b54581..8510ec8 100644 --- a/src/e2e/mod.rs +++ b/src/e2e/mod.rs @@ -1,7 +1,8 @@ -pub mod add_fee_tier; -pub mod change_fee_receiver; -pub mod change_protocol_fee; -pub mod constructor; -pub mod create_pool; -pub mod position; -pub mod remove_fee_tier; +// pub mod add_fee_tier; +// pub mod change_fee_receiver; +// pub mod change_protocol_fee; +// pub mod constructor; +// pub mod create_pool; +// pub mod position; +pub mod protocol_fee; +// pub mod remove_fee_tier; diff --git a/src/e2e/protocol_fee.rs b/src/e2e/protocol_fee.rs new file mode 100644 index 0000000..611c7d5 --- /dev/null +++ b/src/e2e/protocol_fee.rs @@ -0,0 +1,289 @@ +use crate::contracts::InvariantError; +// use crate::contracts::errors::InvariantError; +use crate::contracts::PoolKey; +use crate::math::fee_growth::FeeGrowth; +use crate::math::liquidity::Liquidity; +use crate::math::percentage::Percentage; +use crate::math::sqrt_price::SqrtPrice; +use crate::math::token_amount::TokenAmount; +use crate::math::MIN_SQRT_PRICE; +use crate::token::TokenDeployer; +use crate::FeeTier; +use crate::InvariantDeployer; +use alloc::string::String; +use decimal::*; +use odra::test_env; +use odra::types::{U128, U256}; + +#[test] +fn test_protocol_fee() { + let deployer = test_env::get_account(0); + test_env::set_caller(deployer); + // Init basic dex and tokens + let mint_amount = U256::from(10u128.pow(10)); + let mut token_x = TokenDeployer::init(String::from(""), String::from(""), 0, &mint_amount); + let mut token_y = TokenDeployer::init(String::from(""), String::from(""), 0, &mint_amount); + let mut invariant = InvariantDeployer::init(Percentage::from_scale(1, 2)); + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10).unwrap(); + let pool_key = PoolKey::new(*token_x.address(), *token_y.address(), fee_tier).unwrap(); + // Init basic pool + { + invariant.add_fee_tier(fee_tier).unwrap(); + let exist = invariant.fee_tier_exist(fee_tier); + assert!(exist); + + let init_tick = 0; + invariant + .create_pool(pool_key.token_x, pool_key.token_y, fee_tier, init_tick) + .unwrap(); + } + // Init basic position + { + // let mint_amount = U256::from(10u128.pow(10)); + // token_x.mint(&deployer, &mint_amount); + // token_y.mint(&deployer, &mint_amount); + token_x.approve(invariant.address(), &mint_amount); + token_y.approve(invariant.address(), &mint_amount); + + let lower_tick = -20; + let upper_tick = 10; + let liquidity = Liquidity::from_integer(1000000); + + let pool_before = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + let slippage_limit_lower = pool_before.sqrt_price; + let slippage_limit_upper = pool_before.sqrt_price; + + invariant + .create_position( + pool_key, + lower_tick, + upper_tick, + liquidity, + slippage_limit_lower, + slippage_limit_upper, + ) + .unwrap(); + + let pool_after = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + assert_eq!(pool_after.liquidity, liquidity) + } + // Init basic swap + { + let caller = test_env::get_account(1); + test_env::set_caller(caller); + let amount = U256::from(1000); + + token_x.mint(&caller, &amount); + token_x.approve(invariant.address(), &amount); + + let amount_x = token_x.balance_of(invariant.address()); + let amount_y = token_y.balance_of(invariant.address()); + assert_eq!(amount_x, U256::from(500)); + assert_eq!(amount_y, U256::from(1000)); + + let pool_before = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + let slippage = SqrtPrice::new(U128::from(MIN_SQRT_PRICE)); + let swap_amount = TokenAmount::new(amount); + invariant + .swap(pool_key, true, swap_amount, true, slippage) + .unwrap(); + + let pool_after = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + let expected_tick = -20; + + assert_eq!(pool_after.liquidity, pool_before.liquidity); + assert_eq!(pool_after.current_tick_index, expected_tick); + assert_ne!(pool_after.sqrt_price, pool_before.sqrt_price); + + let amount_x = token_x.balance_of(&caller); + let amount_y = token_y.balance_of(&caller); + assert_eq!(amount_x, U256::from(0)); + assert_eq!(amount_y, U256::from(993)); + + let amount_x = token_x.balance_of(invariant.address()); + let amount_y = token_y.balance_of(invariant.address()); + assert_eq!(amount_x, U256::from(1500)); + assert_eq!(amount_y, U256::from(7)); + + assert_eq!( + pool_after.fee_growth_global_x, + FeeGrowth::new(U128::from(50000000000000000000000u128)) + ); + assert_eq!( + pool_after.fee_growth_global_y, + FeeGrowth::new(U128::from(0)) + ); + + assert_eq!( + pool_after.fee_protocol_token_x, + TokenAmount::new(U256::from(1)) + ); + assert_eq!( + pool_after.fee_protocol_token_y, + TokenAmount::new(U256::from(0)) + ); + } + // Withdraw fee + test_env::set_caller(test_env::get_account(0)); + invariant.withdraw_protocol_fee(pool_key).unwrap(); + let amount_x = token_x.balance_of(&deployer); + let amount_y = token_y.balance_of(&deployer); + + assert_eq!(amount_x, U256::from(9999999501u128)); + assert_eq!(amount_y, U256::from(9999999000u128)); + + let amount_x = token_x.balance_of(invariant.address()); + let amount_y = token_y.balance_of(invariant.address()); + assert_eq!(amount_x, U256::from(1499)); + assert_eq!(amount_y, U256::from(7)); + + let pool_after_withdraw = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + assert_eq!( + pool_after_withdraw.fee_protocol_token_x, + TokenAmount::new(U256::from(0)) + ); + assert_eq!( + pool_after_withdraw.fee_protocol_token_y, + TokenAmount::new(U256::from(0)) + ); +} + +#[test] +fn test_protocol_fee_not_admin() { + let deployer = test_env::get_account(0); + test_env::set_caller(deployer); + // Init basic dex and tokens + let mint_amount = U256::from(10u128.pow(10)); + let mut token_x = TokenDeployer::init(String::from(""), String::from(""), 0, &mint_amount); + let mut token_y = TokenDeployer::init(String::from(""), String::from(""), 0, &mint_amount); + let mut invariant = InvariantDeployer::init(Percentage::from_scale(1, 2)); + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10).unwrap(); + let pool_key = PoolKey::new(*token_x.address(), *token_y.address(), fee_tier).unwrap(); + // Init basic pool + { + invariant.add_fee_tier(fee_tier).unwrap(); + let exist = invariant.fee_tier_exist(fee_tier); + assert!(exist); + + let init_tick = 0; + invariant + .create_pool(pool_key.token_x, pool_key.token_y, fee_tier, init_tick) + .unwrap(); + } + // Init basic position + { + // let mint_amount = U256::from(10u128.pow(10)); + // token_x.mint(&deployer, &mint_amount); + // token_y.mint(&deployer, &mint_amount); + token_x.approve(invariant.address(), &mint_amount); + token_y.approve(invariant.address(), &mint_amount); + + let lower_tick = -20; + let upper_tick = 10; + let liquidity = Liquidity::from_integer(1000000); + + let pool_before = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + let slippage_limit_lower = pool_before.sqrt_price; + let slippage_limit_upper = pool_before.sqrt_price; + + invariant + .create_position( + pool_key, + lower_tick, + upper_tick, + liquidity, + slippage_limit_lower, + slippage_limit_upper, + ) + .unwrap(); + + let pool_after = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + assert_eq!(pool_after.liquidity, liquidity) + } + // Init basic swap + { + let caller = test_env::get_account(1); + test_env::set_caller(caller); + let amount = U256::from(1000); + + token_x.mint(&caller, &amount); + token_x.approve(invariant.address(), &amount); + + let amount_x = token_x.balance_of(invariant.address()); + let amount_y = token_y.balance_of(invariant.address()); + assert_eq!(amount_x, U256::from(500)); + assert_eq!(amount_y, U256::from(1000)); + + let pool_before = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + let slippage = SqrtPrice::new(U128::from(MIN_SQRT_PRICE)); + let swap_amount = TokenAmount::new(amount); + invariant + .swap(pool_key, true, swap_amount, true, slippage) + .unwrap(); + + let pool_after = invariant + .get_pool(pool_key.token_x, pool_key.token_y, fee_tier) + .unwrap(); + + let expected_tick = -20; + + assert_eq!(pool_after.liquidity, pool_before.liquidity); + assert_eq!(pool_after.current_tick_index, expected_tick); + assert_ne!(pool_after.sqrt_price, pool_before.sqrt_price); + + let amount_x = token_x.balance_of(&caller); + let amount_y = token_y.balance_of(&caller); + assert_eq!(amount_x, U256::from(0)); + assert_eq!(amount_y, U256::from(993)); + + let amount_x = token_x.balance_of(invariant.address()); + let amount_y = token_y.balance_of(invariant.address()); + assert_eq!(amount_x, U256::from(1500)); + assert_eq!(amount_y, U256::from(7)); + + assert_eq!( + pool_after.fee_growth_global_x, + FeeGrowth::new(U128::from(50000000000000000000000u128)) + ); + assert_eq!( + pool_after.fee_growth_global_y, + FeeGrowth::new(U128::from(0)) + ); + + assert_eq!( + pool_after.fee_protocol_token_x, + TokenAmount::new(U256::from(1)) + ); + assert_eq!( + pool_after.fee_protocol_token_y, + TokenAmount::new(U256::from(0)) + ); + } + // Withdraw fee not admin + let result = invariant.withdraw_protocol_fee(pool_key); + assert_eq!(result, Err(InvariantError::NotFeeReceiver)); +} diff --git a/src/token.rs b/src/token.rs index f3a643b..7546645 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1,5 +1,5 @@ use odra::{ - contract_env, + // contract_env, prelude::string::String, types::{Address, U256}, }; @@ -41,7 +41,7 @@ impl Token { } pub fn mint(&mut self, address: &Address, amount: &U256) { - self.ownable.assert_owner(&contract_env::caller()); + // self.ownable.assert_owner(&contract_env::caller()); self.erc20.mint(address, amount); } } @@ -106,14 +106,14 @@ pub mod tests { ); } - #[test] - fn mint_error() { - let mut token = setup(); - let recipient = test_env::get_account(1); - let amount = 10.into(); - test_env::set_caller(recipient); - test_env::assert_exception(Error::CallerNotTheOwner, || token.mint(&recipient, &amount)); - } + // #[test] + // fn mint_error() { + // let mut token = setup(); + // let recipient = test_env::get_account(1); + // let amount = 10.into(); + // test_env::set_caller(recipient); + // test_env::assert_exception(Error::CallerNotTheOwner, || token.mint(&recipient, &amount)); + // } #[test] fn change_ownership_works() { From e09fa714cc1c869fa192c942b8d6b845a387c8ec Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 12 Dec 2023 14:27:31 +0100 Subject: [PATCH 2/5] Cleanup --- src/e2e/mod.rs | 14 +++++++------- src/token.rs | 10 ---------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/e2e/mod.rs b/src/e2e/mod.rs index 8510ec8..cf59343 100644 --- a/src/e2e/mod.rs +++ b/src/e2e/mod.rs @@ -1,8 +1,8 @@ -// pub mod add_fee_tier; -// pub mod change_fee_receiver; -// pub mod change_protocol_fee; -// pub mod constructor; -// pub mod create_pool; -// pub mod position; +pub mod add_fee_tier; +pub mod change_fee_receiver; +pub mod change_protocol_fee; +pub mod constructor; +pub mod create_pool; +pub mod position; pub mod protocol_fee; -// pub mod remove_fee_tier; +pub mod remove_fee_tier; diff --git a/src/token.rs b/src/token.rs index 7546645..170773d 100644 --- a/src/token.rs +++ b/src/token.rs @@ -41,7 +41,6 @@ impl Token { } pub fn mint(&mut self, address: &Address, amount: &U256) { - // self.ownable.assert_owner(&contract_env::caller()); self.erc20.mint(address, amount); } } @@ -106,15 +105,6 @@ pub mod tests { ); } - // #[test] - // fn mint_error() { - // let mut token = setup(); - // let recipient = test_env::get_account(1); - // let amount = 10.into(); - // test_env::set_caller(recipient); - // test_env::assert_exception(Error::CallerNotTheOwner, || token.mint(&recipient, &amount)); - // } - #[test] fn change_ownership_works() { let mut token = setup(); From c902f4f2cc61e0f73e3c1997f8c958dec0e70db8 Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 12 Dec 2023 14:28:11 +0100 Subject: [PATCH 3/5] removed not redundant comments --- src/e2e/protocol_fee.rs | 1 - src/token.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/e2e/protocol_fee.rs b/src/e2e/protocol_fee.rs index 611c7d5..150715e 100644 --- a/src/e2e/protocol_fee.rs +++ b/src/e2e/protocol_fee.rs @@ -1,5 +1,4 @@ use crate::contracts::InvariantError; -// use crate::contracts::errors::InvariantError; use crate::contracts::PoolKey; use crate::math::fee_growth::FeeGrowth; use crate::math::liquidity::Liquidity; diff --git a/src/token.rs b/src/token.rs index 170773d..17a5b45 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1,5 +1,4 @@ use odra::{ - // contract_env, prelude::string::String, types::{Address, U256}, }; From a790776adbe76d9029fd9c05b55d5afaeb4aa980 Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 12 Dec 2023 16:14:17 +0100 Subject: [PATCH 4/5] Returned ownable to token --- src/e2e/protocol_fee.rs | 29 +++++++++++++++++++++++------ src/token.rs | 11 +++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/e2e/protocol_fee.rs b/src/e2e/protocol_fee.rs index 150715e..2ffbefa 100644 --- a/src/e2e/protocol_fee.rs +++ b/src/e2e/protocol_fee.rs @@ -3,6 +3,7 @@ use crate::contracts::PoolKey; use crate::math::fee_growth::FeeGrowth; use crate::math::liquidity::Liquidity; use crate::math::percentage::Percentage; +use crate::math::sqrt_price::calculate_sqrt_price; use crate::math::sqrt_price::SqrtPrice; use crate::math::token_amount::TokenAmount; use crate::math::MIN_SQRT_PRICE; @@ -32,8 +33,15 @@ fn test_protocol_fee() { assert!(exist); let init_tick = 0; + let init_sqrt_price = calculate_sqrt_price(init_tick).unwrap(); invariant - .create_pool(pool_key.token_x, pool_key.token_y, fee_tier, init_tick) + .create_pool( + pool_key.token_x, + pool_key.token_y, + fee_tier, + init_sqrt_price, + init_tick, + ) .unwrap(); } // Init basic position @@ -75,10 +83,11 @@ fn test_protocol_fee() { // Init basic swap { let caller = test_env::get_account(1); - test_env::set_caller(caller); let amount = U256::from(1000); + token_x.mint(&deployer, &amount); + token_x.transfer(&caller, &amount); - token_x.mint(&caller, &amount); + test_env::set_caller(caller); token_x.approve(invariant.address(), &amount); let amount_x = token_x.balance_of(invariant.address()); @@ -180,8 +189,15 @@ fn test_protocol_fee_not_admin() { assert!(exist); let init_tick = 0; + let init_sqrt_price = calculate_sqrt_price(init_tick).unwrap(); invariant - .create_pool(pool_key.token_x, pool_key.token_y, fee_tier, init_tick) + .create_pool( + pool_key.token_x, + pool_key.token_y, + fee_tier, + init_sqrt_price, + init_tick, + ) .unwrap(); } // Init basic position @@ -223,10 +239,11 @@ fn test_protocol_fee_not_admin() { // Init basic swap { let caller = test_env::get_account(1); - test_env::set_caller(caller); let amount = U256::from(1000); + token_x.mint(&deployer, &amount); + token_x.transfer(&caller, &amount); - token_x.mint(&caller, &amount); + test_env::set_caller(caller); token_x.approve(invariant.address(), &amount); let amount_x = token_x.balance_of(invariant.address()); diff --git a/src/token.rs b/src/token.rs index 17a5b45..f3a643b 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1,4 +1,5 @@ use odra::{ + contract_env, prelude::string::String, types::{Address, U256}, }; @@ -40,6 +41,7 @@ impl Token { } pub fn mint(&mut self, address: &Address, amount: &U256) { + self.ownable.assert_owner(&contract_env::caller()); self.erc20.mint(address, amount); } } @@ -104,6 +106,15 @@ pub mod tests { ); } + #[test] + fn mint_error() { + let mut token = setup(); + let recipient = test_env::get_account(1); + let amount = 10.into(); + test_env::set_caller(recipient); + test_env::assert_exception(Error::CallerNotTheOwner, || token.mint(&recipient, &amount)); + } + #[test] fn change_ownership_works() { let mut token = setup(); From c239d1c9520d3e76611f93610fad812678f4629e Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 12 Dec 2023 17:19:04 +0100 Subject: [PATCH 5/5] Fixed minting --- src/e2e/protocol_fee.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/e2e/protocol_fee.rs b/src/e2e/protocol_fee.rs index 2ffbefa..5ac6ca3 100644 --- a/src/e2e/protocol_fee.rs +++ b/src/e2e/protocol_fee.rs @@ -84,8 +84,7 @@ fn test_protocol_fee() { { let caller = test_env::get_account(1); let amount = U256::from(1000); - token_x.mint(&deployer, &amount); - token_x.transfer(&caller, &amount); + token_x.mint(&caller, &amount); test_env::set_caller(caller); token_x.approve(invariant.address(), &amount); @@ -240,8 +239,7 @@ fn test_protocol_fee_not_admin() { { let caller = test_env::get_account(1); let amount = U256::from(1000); - token_x.mint(&deployer, &amount); - token_x.transfer(&caller, &amount); + token_x.mint(&caller, &amount); test_env::set_caller(caller); token_x.approve(invariant.address(), &amount);