diff --git a/ramm-sui/sources/math.move b/ramm-sui/sources/math.move index 3216f4c..2684ad8 100644 --- a/ramm-sui/sources/math.move +++ b/ramm-sui/sources/math.move @@ -246,7 +246,6 @@ module ramm_sui::math { lp_tokens_issued: &VecMap, prices: &VecMap, factors_for_balances: &VecMap, - factor_lpt: u256, factors_for_prices: &VecMap, prec: u8, max_prec: u8, @@ -257,9 +256,10 @@ module ramm_sui::math { let _N = (vec_map::size(balances) as u8); let mut j: u8 = 0; while (j < _N) { + let factor_j = *vec_map::get(factors_for_balances, &j); let price_j = *vec_map::get(prices, &j) * *vec_map::get(factors_for_prices, &j); - _B = _B + mul(price_j, *vec_map::get(balances, &j) * *vec_map::get(factors_for_balances, &j), prec, max_prec); - _L = _L + mul(price_j, *vec_map::get(lp_tokens_issued, &j) * factor_lpt, prec, max_prec); + _B = _B + mul(price_j, *vec_map::get(balances, &j) * factor_j, prec, max_prec); + _L = _L + mul(price_j, *vec_map::get(lp_tokens_issued, &j) * factor_j, prec, max_prec); j = j + 1; }; @@ -275,7 +275,6 @@ module ramm_sui::math { lp_tokens_issued: &VecMap, prices: &VecMap, factors_for_balances: &VecMap, - factor_lpt: u256, factors_for_prices: &VecMap, prec: u8, max_prec: u8, @@ -285,7 +284,6 @@ module ramm_sui::math { lp_tokens_issued, prices, factors_for_balances, - factor_lpt, factors_for_prices, prec, max_prec, @@ -297,9 +295,10 @@ module ramm_sui::math { let mut j: u8 = 0; while (j < _N) { if (*vec_map::get(lp_tokens_issued, &j) != 0) { + let factor_j = *vec_map::get(factors_for_balances, &j); let val = div( mul(*vec_map::get(balances, &j) * *vec_map::get(factors_for_balances, &j), _L, prec, max_prec), - mul(_B, *vec_map::get(lp_tokens_issued, &j) * factor_lpt, prec, max_prec), + mul(_B, *vec_map::get(lp_tokens_issued, &j) * factor_j, prec, max_prec), prec, max_prec ); vec_map::insert(&mut imbs, j, val); @@ -317,7 +316,7 @@ module ramm_sui::math { /// or if they would be closer to the range than before the trade. /// /// As is the case with other functions in this module, the parameters - /// `factor_lpt, prec, max_prec, one, delta` + /// `prec, max_prec, one, delta` /// will be constants defined in the `ramm.move` module, and passed to this function. /// /// Sui Move does not permit sharing of constants between modules. @@ -331,7 +330,6 @@ module ramm_sui::math { ao: u256, pr_fee: u256, factors_for_balances: &VecMap, - factor_lpt: u256, factors_for_prices: &VecMap, prec: u8, max_prec: u8, @@ -361,7 +359,6 @@ module ramm_sui::math { lp_tokens_issued, prices, factors_for_balances, - factor_lpt, factors_for_prices, prec, max_prec @@ -385,7 +382,6 @@ module ramm_sui::math { i: u8, o: u8, factors_for_balances: &VecMap, - factor_lpt: u256, factors_for_prices: &VecMap, base_fee: u256, base_leverage: u256, @@ -397,7 +393,6 @@ module ramm_sui::math { lp_tokens_issued, prices, factors_for_balances, - factor_lpt, factors_for_prices, prec, max_prec, diff --git a/ramm-sui/sources/ramm.move b/ramm-sui/sources/ramm.move index 43529c9..21ed5ba 100644 --- a/ramm-sui/sources/ramm.move +++ b/ramm-sui/sources/ramm.move @@ -49,8 +49,6 @@ module ramm_sui::ramm { /// Decimal places that LP tokens will be using; may yet change. //const LP_TOKENS_DECIMAL_PLACES: u8 = 9; - /// Factor to apply to LP token amounts during calculations. - const FACTOR_LPT: u256 = 1_000_000_000_000 / 1_000_000_000; // FACTOR_LPT = 10**(PRECISION_DECIMAL_PLACES-LP_TOKENS_DECIMAL_PLACES) /// Value of `1` using `PRECISION_DECIMAL_PLACES`; useful to scale other values to /// the baseline precision. /// @@ -1538,7 +1536,6 @@ module ramm_sui::ramm { &self.lp_tokens_issued, prices, &self.factors_for_balances, - FACTOR_LPT, factors_for_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -1559,7 +1556,6 @@ module ramm_sui::ramm { &self.lp_tokens_issued, prices, &self.factors_for_balances, - FACTOR_LPT, factors_for_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -1588,7 +1584,6 @@ module ramm_sui::ramm { ao, pr_fee, &self.factors_for_balances, - FACTOR_LPT, factors_for_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -1623,7 +1618,6 @@ module ramm_sui::ramm { i, o, &self.factors_for_balances, - FACTOR_LPT, factors_for_prices, BASE_FEE, BASE_LEVERAGE, @@ -1891,7 +1885,7 @@ module ramm_sui::ramm { let lpt: u64 = ai; return lpt } else { - let lpt: u256 = div(mul((ai as u256) * factor_i, _L), _B) / FACTOR_LPT; + let lpt: u256 = div(mul((ai as u256) * factor_i, _L), _B) / factor_i; return (lpt as u64) } }; @@ -1906,10 +1900,10 @@ module ramm_sui::ramm { mul3( (ai as u256) * factor_i, ri, - get_typed_lptok_issued(self, i) * FACTOR_LPT + get_typed_lptok_issued(self, i) * factor_i ), bi - ) / FACTOR_LPT; + ) / factor_i; return (lpt as u64) } else { return 0 @@ -1958,7 +1952,7 @@ module ramm_sui::ramm { // Recall that in this case, the "Case 1" step below is skipped, and the withdrawal // continues with different tokens - see below. if (get_bal(self, o) == 0) { - *ao = div(mul(lpt * FACTOR_LPT, _B), _L) / factor_o; + *ao = div(mul(lpt * factor_o, _B), _L) / factor_o; *a_remaining = *ao; }; @@ -1969,14 +1963,14 @@ module ramm_sui::ramm { // Case 1.1 if (lpt < get_typed_lptok_issued(self, o)) { - *ao = div(mul(lpt * FACTOR_LPT, bo), mul(_Lo, ro)) / factor_o; + *ao = div(mul(lpt * factor_o, bo), mul(_Lo, ro)) / factor_o; let max_token_o: &mut u256 = &mut 0; if (ONE - DELTA < ro) { - let min_token_o: u256 = div(mul3(_B, (get_lptok_issued(self, o) - lpt) * FACTOR_LPT, ONE - DELTA), _L) / factor_o; + let min_token_o: u256 = div(mul3(_B, (get_lptok_issued(self, o) - lpt) * factor_o, ONE - DELTA), _L) / factor_o; *max_token_o = get_bal(self, o) - min_token_o; } else { - *max_token_o = div(mul(lpt * FACTOR_LPT, bo), _Lo) / factor_o; + *max_token_o = div(mul(lpt * factor_o, bo), _Lo) / factor_o; }; let amount_out_o: &mut u256 = vec_map::get_mut(&mut amounts_out, &o); @@ -2052,7 +2046,7 @@ module ramm_sui::ramm { ), *vec_map::get(&prices, &k) * *vec_map::get(&factors_for_prices, &k) ) / factor_k; - let _Lk: u256 = get_lptok_issued(self, k) * FACTOR_LPT; + let _Lk: u256 = get_lptok_issued(self, k) * factor_k; // Mk = bk-(1.0-DELTA)*Lk*B/L let min_token_k: u256 = div(mul3(_B, _Lk, ONE - DELTA), _L) / factor_k; let max_token_k: u256 = get_bal(self, k) - min_token_k; diff --git a/ramm-sui/tests/interface2_tests.move b/ramm-sui/tests/interface2_tests.move index 42c080a..dcadbc8 100644 --- a/ramm-sui/tests/interface2_tests.move +++ b/ramm-sui/tests/interface2_tests.move @@ -75,14 +75,14 @@ module ramm_sui::interface2_tests { test_utils::assert_eq(ramm::get_balance(&ramm), 480 * test_util::eth_factor()); test_utils::assert_eq(ramm::get_typed_balance(&ramm), 480 * test_util::eth_factor()); - let total_usdt: u256 = 940044_93561689; + let total_usdt: u256 = 940044_935617; test_utils::assert_eq(ramm::get_balance(&ramm), total_usdt); test_utils::assert_eq(ramm::get_typed_balance(&ramm), total_usdt); // Later in the test, when accounting for all the USDT given to liquidity providers // and comparing it to the pool's USDT balance, liquidity withdrawal fees count toward // this tally, but protocol trading fees do not - they must be removed from the count. - let usdt_trade_fees = 1_201_708_581; + let usdt_trade_fees = 1_201_708_5; test_utils::assert_eq(ramm::get_collected_protocol_fees(&ramm), 0); test_utils::assert_eq(ramm::get_collected_protocol_fees(&ramm), usdt_trade_fees); @@ -147,7 +147,7 @@ module ramm_sui::interface2_tests { test_utils::assert_eq(coin::value(ð), (47808 * test_util::eth_factor() / 100 as u64)); let usdt = test_scenario::take_from_address>(scenario, ADMIN); - let first_usdt_wthdrwl: u256 = 39863_55571872; + let first_usdt_wthdrwl: u256 = 39863_555719; test_utils::assert_eq((coin::value(&usdt) as u256), first_usdt_wthdrwl); test_scenario::return_to_address(ADMIN, eth); @@ -195,7 +195,7 @@ module ramm_sui::interface2_tests { let snd_udst_wthdrwl: u256 = { let usdt = test_scenario::take_from_address>(scenario, ADMIN); - let snd_udst_wthdrwl: u256 = 896421_20015571; + let snd_udst_wthdrwl: u256 = 896421_200156; test_utils::assert_eq((coin::value(&usdt) as u256), snd_udst_wthdrwl); test_scenario::return_to_address(ADMIN, usdt); @@ -245,7 +245,7 @@ module ramm_sui::interface2_tests { let initial_eth_balance: u256 = ramm::get_typed_balance(&ramm); let initial_usdt_balance: u256 = ramm::get_typed_balance(&ramm); test_utils::assert_eq(initial_eth_balance, 500 * test_util::eth_factor()); - test_utils::assert_eq(initial_usdt_balance, 900_000 * test_util::eth_factor()); + test_utils::assert_eq(initial_usdt_balance, 900_000 * test_util::usdc_factor()); let amount_in = coin::mint_for_testing(eth_trade_amount, test_scenario::ctx(scenario)); interface2::trade_amount_in_2( diff --git a/ramm-sui/tests/interface3_tests.move b/ramm-sui/tests/interface3_tests.move index c16afb1..43ffdb0 100644 --- a/ramm-sui/tests/interface3_tests.move +++ b/ramm-sui/tests/interface3_tests.move @@ -350,7 +350,7 @@ module ramm_sui::interface3_tests { let initial_usdt_balance: u256 = ramm::get_typed_balance(&ramm); test_utils::assert_eq(initial_eth_balance, 200 * test_util::eth_factor()); test_utils::assert_eq(initial_matic_balance, 200_000 * test_util::eth_factor()); - test_utils::assert_eq(initial_usdt_balance, 400_000 * test_util::eth_factor()); + test_utils::assert_eq(initial_usdt_balance, 400_000 * test_util::usdc_factor()); let amount_in = coin::mint_for_testing(eth_trade_amount, test_scenario::ctx(scenario)); interface3::trade_amount_in_3( diff --git a/ramm-sui/tests/math_tests.move b/ramm-sui/tests/math_tests.move index c561fee..989a244 100644 --- a/ramm-sui/tests/math_tests.move +++ b/ramm-sui/tests/math_tests.move @@ -17,8 +17,6 @@ module ramm_sui::math_tests { /// Number of decimal places of precision. const PRECISION_DECIMAL_PLACES: u8 = 12; const MAX_PRECISION_DECIMAL_PLACES: u8 = 25; - // FACTOR = 10**(PRECISION_DECIMAL_PLACES-LP_TOKENS_DECIMAL_PLACES) - const FACTOR_LPT: u256 = 1_000_000_000_000 / 1_000_000_000; const ONE: u256 = 1_000_000_000_000; /// Miguel's note: @@ -326,7 +324,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -348,7 +345,6 @@ module ramm_sui::math_tests { i, o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -384,7 +380,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -406,7 +401,6 @@ module ramm_sui::math_tests { next_i, next_o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -437,7 +431,6 @@ module ramm_sui::math_tests { ao, pr_fee, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -470,7 +463,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -483,7 +475,6 @@ module ramm_sui::math_tests { i, o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -515,7 +506,6 @@ module ramm_sui::math_tests { ao, pr_fee, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -592,7 +582,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -609,7 +598,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -650,7 +638,6 @@ module ramm_sui::math_tests { i, o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -676,7 +663,6 @@ module ramm_sui::math_tests { ao, pr_fee, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -714,7 +700,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -731,7 +716,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -772,7 +756,6 @@ module ramm_sui::math_tests { i, o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -798,7 +781,6 @@ module ramm_sui::math_tests { ao, pr_fee, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -835,7 +817,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -852,7 +833,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -893,7 +873,6 @@ module ramm_sui::math_tests { i, o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -919,7 +898,6 @@ module ramm_sui::math_tests { ao, pr_fee, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -959,7 +937,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -976,7 +953,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -1015,7 +991,6 @@ module ramm_sui::math_tests { i, o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -1041,7 +1016,6 @@ module ramm_sui::math_tests { ao, pr_fee, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -1079,7 +1053,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -1095,7 +1068,6 @@ module ramm_sui::math_tests { &lp_tokens_issued, &prices, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, @@ -1134,7 +1106,6 @@ module ramm_sui::math_tests { i, o, &factors_balances, - FACTOR_LPT, &factors_prices, BASE_FEE, BASE_LEVERAGE, @@ -1160,7 +1131,6 @@ module ramm_sui::math_tests { ao, pr_fee, &factors_balances, - FACTOR_LPT, &factors_prices, PRECISION_DECIMAL_PLACES, MAX_PRECISION_DECIMAL_PLACES, diff --git a/ramm-sui/tests/sui_usdc_usdt_liquidity_tests.move b/ramm-sui/tests/sui_usdc_usdt_liquidity_tests.move new file mode 100644 index 0000000..076783c --- /dev/null +++ b/ramm-sui/tests/sui_usdc_usdt_liquidity_tests.move @@ -0,0 +1,172 @@ +#[test_only] +module ramm_sui::sui_usdc_usdt_liquidity_tests { + use sui::clock::Clock; + use sui::coin::{Self, Coin}; + use sui::sui::SUI; + use sui::test_scenario::{Self, TransactionEffects}; + use sui::test_utils; + + use ramm_sui::interface3; + use ramm_sui::math; + use ramm_sui::ramm::{Self, LP, RAMM, RAMMAdminCap}; + use ramm_sui::test_util::{Self, USDC, USDT}; + + use switchboard::aggregator::Aggregator; + + const ADMIN: address = @0xFACE; + const ALICE: address = @0xACE; + const BOB: address = @0xBACE; + + #[test] + /// Test designed to correct issue with LP withdrawals being wildly incorrect in their + /// precision. + /// + /// Recall that this `SUI/USDC/USDT` pool begins with + /// * 100 SUI + /// * 145 USDC + /// * 148 USDT + /// + /// The test runs as follows: + /// 1. The pool is created, with the `ADMIN` holding all of the initial liquidity + /// 2. `ALICE` moves in to deposit 650 USDC + /// 3. Alice deposits 500 SUI + /// 4. The admin then withdraws from all of their positions + /// + /// The withdrawn amounts are then tallied, and their precision must be correct - the 145 + /// USDC withdrawal must correspond to the 145 USDC deposited, and not 0.14 USDC, or 1000 + /// times smaller than expected. + fun sui_usdc_usdt_liquidity_test() { + let (ramm_id, sui_ag_id, usdc_ag_id, usdt_ag_id, mut scenario_val) = test_util::create_ramm_test_scenario_sui_usdc_usdt(ADMIN); + let scenario = &mut scenario_val; + + test_scenario::next_tx(scenario, ALICE); + + // `ALICE`'s deposits + { + let mut ramm = test_scenario::take_shared_by_id(scenario, ramm_id); + let clock = test_scenario::take_shared(scenario); + let sui_aggr = test_scenario::take_shared_by_id(scenario, sui_ag_id); + let usdc_aggr = test_scenario::take_shared_by_id(scenario, usdc_ag_id); + let usdt_aggr = test_scenario::take_shared_by_id(scenario, usdt_ag_id); + + let usdc = coin::mint_for_testing( + 650 * (test_util::usdc_factor() as u64), + test_scenario::ctx(scenario) + ); + + interface3::liquidity_deposit_3( + &mut ramm, + &clock, + usdc, + &usdc_aggr, + &sui_aggr, + &usdt_aggr, + test_scenario::ctx(scenario) + ); + + let sui = coin::mint_for_testing( + 500 * (test_util::sui_factor() as u64), + test_scenario::ctx(scenario) + ); + + interface3::liquidity_deposit_3( + &mut ramm, + &clock, + sui, + &sui_aggr, + &usdc_aggr, + &usdt_aggr, + test_scenario::ctx(scenario) + ); + + test_utils::assert_eq(ramm::get_lptokens_issued(&ramm), 795 * test_util::usdc_factor()); + test_utils::assert_eq(ramm::get_lptokens_issued(&ramm), 600 * test_util::sui_factor()); + test_utils::assert_eq(ramm::get_lptokens_issued(&ramm), 148 * test_util::usdt_factor()); + + test_scenario::return_shared(ramm); + test_scenario::return_shared(clock); + test_scenario::return_shared(sui_aggr); + test_scenario::return_shared(usdc_aggr); + test_scenario::return_shared(usdt_aggr); + }; + + test_scenario::next_tx(scenario, ADMIN); + + // `ADMIN`'s withdrawals + { + let mut ramm = test_scenario::take_shared_by_id(scenario, ramm_id); + let clock = test_scenario::take_shared(scenario); + let sui_aggr = test_scenario::take_shared_by_id(scenario, sui_ag_id); + let usdc_aggr = test_scenario::take_shared_by_id(scenario, usdc_ag_id); + let usdt_aggr = test_scenario::take_shared_by_id(scenario, usdt_ag_id); + + let lp_sui = test_scenario::take_from_address>>(scenario, ADMIN); + test_utils::assert_eq(coin::value(&lp_sui), (100 * test_util::sui_factor() as u64)); + + let lp_usdc = test_scenario::take_from_address>>(scenario, ADMIN); + // Observer how the lambda factor applied to USDT and USDC is incorrect - the whitepaper + // advises a lambda of 1 as a reasonable default, and using the `FACTOR_LP` constant + // when a pool's assets have different decimal places leads to this. + test_utils::assert_eq(coin::value(&lp_usdc), (145 * test_util::usdc_factor() as u64)); + + let lp_usdt = test_scenario::take_from_address>>(scenario, ADMIN); + test_utils::assert_eq(coin::value(&lp_usdt), (148 * test_util::usdt_factor() as u64)); + + interface3::liquidity_withdrawal_3( + &mut ramm, + &clock, + lp_sui, + &sui_aggr, + &usdc_aggr, + &usdt_aggr, + test_scenario::ctx(scenario) + ); + + interface3::liquidity_withdrawal_3( + &mut ramm, + &clock, + lp_usdc, + &sui_aggr, + &usdc_aggr, + &usdt_aggr, + test_scenario::ctx(scenario) + ); + + interface3::liquidity_withdrawal_3( + &mut ramm, + &clock, + lp_usdt, + &sui_aggr, + &usdc_aggr, + &usdt_aggr, + test_scenario::ctx(scenario) + ); + + test_scenario::return_shared(ramm); + test_scenario::return_shared(clock); + test_scenario::return_shared(sui_aggr); + test_scenario::return_shared(usdc_aggr); + test_scenario::return_shared(usdt_aggr); + }; + + test_scenario::next_tx(scenario, ADMIN); + + // Admin verifies withdrawn amounts + { + let sui = test_scenario::take_from_address>(scenario, ADMIN); + test_utils::assert_eq(coin::value(&sui), (996 * test_util::sui_factor() as u64) / 10); + + let usdc = test_scenario::take_from_address>(scenario, ADMIN); + test_utils::assert_eq(coin::value(&usdc), (14442 * test_util::usdc_factor() as u64) / 100); + + let usdt = test_scenario::take_from_address>(scenario, ADMIN); + test_utils::assert_eq(coin::value(&usdt), (147408 * test_util::usdt_factor() as u64) / 1000); + + test_scenario::return_to_address>(ADMIN, sui); + test_scenario::return_to_address>(ADMIN, usdc); + test_scenario::return_to_address>(ADMIN, usdt); + }; + + test_scenario::end(scenario_val); + } +} \ No newline at end of file diff --git a/ramm-sui/tests/test_util.move b/ramm-sui/tests/test_util.move index 057bd77..65a3475 100644 --- a/ramm-sui/tests/test_util.move +++ b/ramm-sui/tests/test_util.move @@ -6,6 +6,7 @@ module ramm_sui::test_util { use sui::clock::{Self, Clock}; use sui::coin; use sui::object::{Self, ID}; + use sui::sui::SUI; use sui::test_scenario::{Self, Scenario}; use sui::test_utils; use sui::tx_context::{Self, TxContext}; @@ -77,6 +78,16 @@ module ramm_sui::test_util { public struct USDC has drop {} public struct USDT has drop {} + /// Decimal places of the globally known SUI coin type. + public(package) fun sui_dec_places(): u8 { + 9 + } + + /// Scaling factor for SUI coin type. + public(package) fun sui_factor(): u256 { + ramm_math::pow(10u256, sui_dec_places()) + } + /// Decimal places of this module's BTC coin type. public(package) fun btc_dec_places(): u8 { 8 @@ -119,7 +130,7 @@ module ramm_sui::test_util { /// Decimal places of this module's USDT coin type. public(package) fun usdt_dec_places(): u8 { - 8 + 6 } /// Scaling factor for USDT coin type. @@ -127,6 +138,16 @@ module ramm_sui::test_util { ramm_math::pow(10u256, usdt_dec_places()) } + /// Decimal places of this module's USDC coin type. + public(package) fun usdc_dec_places(): u8 { + 6 + } + + /// Scaling factor for USDC coin type. + public(package) fun usdc_factor(): u256 { + ramm_math::pow(10u256, usdc_dec_places()) + } + /// ---------------- /// Aggregator utils /// ---------------- @@ -717,4 +738,44 @@ module ramm_sui::test_util { sender ) } + + #[test_only] + /// Create an SUI/USDT/USDC pool with the parameters from the first RAMM deployed to the Sui + /// mainnet. + /// + /// Initial liquidity was roughly: + /// * `SUI` - 100 + /// * `USDC` - 145 + /// * `USDT` - 148 + public(package) fun create_ramm_test_scenario_sui_usdc_usdt(sender: address): (ID, ID, ID, ID, Scenario) { + let mut asset_prices: VecMap = vec_map::empty(); + vec_map::insert(&mut asset_prices, 0, 1_500000000); + vec_map::insert(&mut asset_prices, 1, 1_000000000); + vec_map::insert(&mut asset_prices, 2, 1_000000000); + let mut asset_price_scales: VecMap = vec_map::empty(); + vec_map::insert(&mut asset_price_scales, 0, 9); + vec_map::insert(&mut asset_price_scales, 1, 9); + vec_map::insert(&mut asset_price_scales, 2, 9); + let mut asset_minimum_trade_amounts: VecMap = vec_map::empty(); + vec_map::insert(&mut asset_minimum_trade_amounts, 0, (1 * sui_factor() as u64) / 100); + vec_map::insert(&mut asset_minimum_trade_amounts, 1, (1 * usdc_factor() as u64) / 100); + vec_map::insert(&mut asset_minimum_trade_amounts, 2, (1 * usdt_factor() as u64) / 100); + let mut asset_decimal_places: VecMap = vec_map::empty(); + vec_map::insert(&mut asset_decimal_places, 0, sui_dec_places()); + vec_map::insert(&mut asset_decimal_places, 1, usdc_dec_places()); + vec_map::insert(&mut asset_decimal_places, 2, usdt_dec_places()); + let mut initial_asset_liquidity: VecMap = vec_map::empty(); + vec_map::insert(&mut initial_asset_liquidity, 0, 100 * (sui_factor() as u64)); + vec_map::insert(&mut initial_asset_liquidity, 1, 145 * (usdc_factor() as u64)); + vec_map::insert(&mut initial_asset_liquidity, 2, 148 * (usdt_factor() as u64)); + + create_populate_initialize_ramm_3_asset( + asset_prices, + asset_price_scales, + asset_minimum_trade_amounts, + asset_decimal_places, + initial_asset_liquidity, + sender + ) + } } \ No newline at end of file diff --git a/ramm-sui/tests/volatility2_tests.move b/ramm-sui/tests/volatility2_tests.move index fa4d490..e985f90 100644 --- a/ramm-sui/tests/volatility2_tests.move +++ b/ramm-sui/tests/volatility2_tests.move @@ -126,7 +126,7 @@ module ramm_sui::volatility2_tests { test_utils::assert_eq(ramm::get_balance(&ramm), 500 * test_util::eth_factor()); test_utils::assert_eq(ramm::get_typed_balance(&ramm), 500 * test_util::eth_factor()); - let total_usdt: u256 = 900000_00000000; + let total_usdt: u256 = 900000_000000; test_utils::assert_eq(ramm::get_balance(&ramm), total_usdt); test_utils::assert_eq(ramm::get_typed_balance(&ramm), total_usdt); @@ -174,9 +174,9 @@ module ramm_sui::volatility2_tests { test_utils::assert_eq(ramm::get_typed_balance(&ramm), 495_50542655); // Recall that the RAMM uses 12 decimal places for internal calculations, and that - // test USDT has 8 decimal places of precision - hence, the correction below by 10^4, - // or 10_000. - let total_trade_fee: u256 = ramm::mul3(PROTOCOL_FEE, BASE_FEE + 10 * ONE / 100, 10_000 * ONE) / 10_000; + // test USDT has 6 decimal places of precision - hence, the correction below by 10^6, + // or 1_000_000. + let total_trade_fee: u256 = ramm::mul3(PROTOCOL_FEE, BASE_FEE + 10 * ONE / 100, 10_000 * ONE) / 1_000_000; test_utils::assert_eq(ramm::get_balance(&ramm), total_usdt + (usdt_trade_amount - total_trade_fee)); test_utils::assert_eq(ramm::get_typed_balance(&ramm), total_usdt + (usdt_trade_amount - total_trade_fee)); @@ -285,7 +285,7 @@ module ramm_sui::volatility2_tests { // The trader sends 12k USDT to the RAMM let usdt_trade_amount: u256 = 12_000 * test_util::usdt_factor(); - let total_usdt: u256 = 900000_00000000; + let total_usdt: u256 = 900000_000000; // Second part of the test: a trader, Alice, wishes to buy 5 ETH // from the ETH/USDT RAMM, with the new price of 2100 USDT per ETH. test_scenario::next_tx(scenario, ALICE); diff --git a/ramm-sui/tests/volatility3_tests.move b/ramm-sui/tests/volatility3_tests.move index 328a25f..7668bca 100644 --- a/ramm-sui/tests/volatility3_tests.move +++ b/ramm-sui/tests/volatility3_tests.move @@ -157,7 +157,7 @@ module ramm_sui::volatility3_tests { test_utils::assert_eq(ramm::get_balance(&ramm), 200_000 * test_util::matic_factor()); test_utils::assert_eq(ramm::get_typed_balance(&ramm), 200_000 * test_util::matic_factor()); - let total_usdt: u256 = 400000_00000000; + let total_usdt: u256 = 400000_000000; test_utils::assert_eq(ramm::get_balance(&ramm), total_usdt); test_utils::assert_eq(ramm::get_typed_balance(&ramm), total_usdt); @@ -207,9 +207,9 @@ module ramm_sui::volatility3_tests { test_utils::assert_eq(ramm::get_typed_balance(&ramm), 195_00674016); // Recall that the RAMM uses 12 decimal places for internal calculations, and that - // test USDT has 8 decimal places of precision - hence, the correction below by 10^4, - // or 10_000. - let total_trade_fee: u256 = ramm::mul3(PROTOCOL_FEE, BASE_FEE + 10 * ONE / 100, 10_000 * ONE) / 10_000; + // test USDT has 6 decimal places of precision - hence, the correction below by 10^6, + // or 1_000_000. + let total_trade_fee: u256 = ramm::mul3(PROTOCOL_FEE, BASE_FEE + 10 * ONE / 100, 10_000 * ONE) / 1_000_000; test_utils::assert_eq(ramm::get_balance(&ramm), total_usdt + (usdt_trade_amount - total_trade_fee)); test_utils::assert_eq(ramm::get_typed_balance(&ramm), total_usdt + (usdt_trade_amount - total_trade_fee)); @@ -338,7 +338,7 @@ module ramm_sui::volatility3_tests { // The trader sends 12k USDT to the RAMM let usdt_trade_amount: u256 = 12_000 * test_util::usdt_factor(); - let total_usdt: u256 = 400000_00000000; + let total_usdt: u256 = 400000_000000; // Second part of the test: a trader, Alice, wishes to buy exactly 5 ETH // from the ETH/USDT RAMM, with the new price of 1960 USDT per ETH. test_scenario::next_tx(scenario, ALICE);