diff --git a/contracts/adapters/phoenix/src/lib.rs b/contracts/adapters/phoenix/src/lib.rs
index d8a6843b..59fa7f18 100644
--- a/contracts/adapters/phoenix/src/lib.rs
+++ b/contracts/adapters/phoenix/src/lib.rs
@@ -1,23 +1,26 @@
#![no_std]
use soroban_sdk::{contract, contractimpl, Address, Env, Vec, String};
-
mod event;
mod storage;
mod protocol_interface;
mod test;
use storage::{
- extend_instance_ttl,
- set_initialized,
- is_initialized,
+ extend_instance_ttl,
+ set_initialized,
+ is_initialized,
set_protocol_id,
get_protocol_id,
- set_protocol_address,
- get_protocol_address,
+ set_protocol_address,
+ get_protocol_address,
+};
+use soroswap_aggregator_adapter_interface::{
+ SoroswapAggregatorAdapterTrait, AdapterError
+};
+use protocol_interface::{
+ protocol_swap_exact_tokens_for_tokens,
+ protocol_swap_tokens_for_exact_tokens
};
-use soroswap_aggregator_adapter_interface::{SoroswapAggregatorAdapterTrait, AdapterError};
-use protocol_interface::{protocol_swap_exact_tokens_for_tokens,
- protocol_swap_tokens_for_exact_tokens};
pub fn check_nonnegative_amount(amount: i128) -> Result<(), AdapterError> {
if amount < 0 {
@@ -49,7 +52,18 @@ struct SoroswapAggregatorPhoenixAdapter;
#[contractimpl]
impl SoroswapAggregatorAdapterTrait for SoroswapAggregatorPhoenixAdapter {
- /// Initializes the contract and sets the phoenix multihop address
+
+ /// Initializes the contract and sets the Phoenix multihop address.
+ ///
+ /// # Arguments
+ ///
+ /// * `e` - The contract environment.
+ /// * `protocol_id` - The identifier for the protocol.
+ /// * `protocol_address` - The address associated with the protocol.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the contract is already initialized (`AdapterError::AlreadyInitialized`).
fn initialize(
e: Env,
protocol_id: String,
diff --git a/contracts/adapters/phoenix/src/protocol_interface.rs b/contracts/adapters/phoenix/src/protocol_interface.rs
index 64219ee7..5fa6e0a2 100644
--- a/contracts/adapters/phoenix/src/protocol_interface.rs
+++ b/contracts/adapters/phoenix/src/protocol_interface.rs
@@ -1,6 +1,6 @@
// based on https://github.com/Phoenix-Protocol-Group/phoenix_contracts/tree/v1.0.0
-use soroban_sdk::{Env, Address, Vec, vec};
+use soroban_sdk::{Env, Address, Vec, token::Client as TokenClient};
use crate::storage::{get_protocol_address};
use soroswap_aggregator_adapter_interface::{AdapterError};
@@ -9,18 +9,34 @@ soroban_sdk::contractimport!(
);
pub type PhoenixMultihopClient<'a> = Client<'a>;
-fn convert_to_swaps(e: &Env, addresses: &Vec
) -> Vec {
+fn convert_to_swaps(e: &Env, path: &Vec) -> Vec {
let mut swaps = Vec::new(e);
- // Iterate through the addresses, creating a Swap for each pair
- // Skip the last address since it cannot be an offer_asset without a corresponding ask_asset
- for i in 0..(addresses.len() - 1) {
- let offer_asset = addresses.get(i).expect("Failed to get offer asset");
- let ask_asset = addresses.get(i + 1).expect("Failed to get ask asset");
+ // Iterate through the addresses in the path, creating a Swap object for each pair
+ // If path is [token0, token1, token2, token3], swaps should be
+ // swap_0 = Swap{
+ // offer_asset: token0,
+ // ask_asset: token1,
+ // ask_asset_min_amount: None,
+ // },
+ // swap_1 = Swap{
+ // offer_asset: token1,
+ // ask_asset: token2,
+ // ask_asset_min_amount: None,
+ // },
+ // swap_2 = Swap{
+ // offer_asset: token2,
+ // ask_asset: token3,
+ // ask_asset_min_amount: None,
+ // }
+
+ for i in 0..(path.len() - 1) {
+ let offer_asset = path.get(i).expect("Failed to get offer asset");
+ let ask_asset = path.get(i + 1).expect("Failed to get ask a sset");
swaps.push_back(Swap {
- ask_asset: ask_asset.clone(),
- offer_asset: offer_asset.clone(),
+ offer_asset: offer_asset.clone(), // asset being sold (token_in)
+ ask_asset: ask_asset.clone(), // asset buying (token_out)
ask_asset_min_amount: None,
});
}
@@ -28,25 +44,48 @@ fn convert_to_swaps(e: &Env, addresses: &Vec) -> Vec {
swaps
}
-
pub fn protocol_swap_exact_tokens_for_tokens(
e: &Env,
amount_in: &i128,
amount_out_min: &i128,
path: &Vec,
to: &Address,
- deadline: &u64,
+ _deadline: &u64,
) -> Result, AdapterError> {
let phoenix_multihop_address = get_protocol_address(&e)?;
let phoenix_multihop_client = PhoenixMultihopClient::new(&e, &phoenix_multihop_address);
let operations = convert_to_swaps(e, path);
+
+ // TODO: Remove this checks if we want to reduce the number of total instructions
+ // TODO: Do benchmarking
+ let token_out_address = path.get(path.len() - 1).expect("Failed to get token out address");
+ let initial_token_out_balance = TokenClient::new(&e, &token_out_address).balance(&to);
+
+ // By using max_spread_bps = None, the Phoenix LP will use the maximum allowed slippage
+ // amount_in is the amount being sold of the first token in the operations.
+ phoenix_multihop_client.swap(
+ &to, // recipient: Address,
+ &operations, // operations: Vec,
+ &None, // max_spread_bps: Option.
+ &amount_in); //amout: i128. Amount being sold. Input from the user,
+
+ let final_token_out_balance = TokenClient::new(&e, &token_out_address).balance(&to);
+
+ // check if the amount of token_out received is greater than the minimum amount expected
+ // TODO: Remove this checks if we want to reduce the number of total instructions
+ // TODO: Do benchmarking
+ let final_amount_out = final_token_out_balance.checked_sub(initial_token_out_balance).unwrap();
+ if final_amount_out < *amount_out_min {
+ // panic
+ panic!("Amount of token out received is less than the minimum amount expected");
+ }
- // TODO: CHECK AND TEST
- phoenix_multihop_client.swap(&to, &operations, &None, &amount_in);
+ let mut swap_amounts: Vec = Vec::new(e);
+ swap_amounts.push_back(amount_in.clone());
+ swap_amounts.push_back(final_amount_out);
- // Returning empty array (should check phoenix response if it return amounts, apparently it doesnt)
- Ok(vec![&e])
+ Ok(swap_amounts)
}
pub fn protocol_swap_tokens_for_exact_tokens(
@@ -55,16 +94,61 @@ pub fn protocol_swap_tokens_for_exact_tokens(
amount_in_max: &i128,
path: &Vec,
to: &Address,
- deadline: &u64,
+ _deadline: &u64,
) -> Result, AdapterError> {
let phoenix_multihop_address = get_protocol_address(&e)?;
let phoenix_multihop_client = PhoenixMultihopClient::new(&e, &phoenix_multihop_address);
let operations = convert_to_swaps(e, path);
- // TODO: CHECK AND TEST
- phoenix_multihop_client.swap(&to, &operations, &None, &amount_in_max);
+ // We first need to get the "reverse_amount from phoenix.simulate_reverse_swap"
+ // however here, if the path is [t0, t1, t2, t3, t4], the operations should be
+ // swap_0 = Swap{
+ // offer_asset: t3,
+ // ask_asset: t4,
+ // ask_asset_min_amount: None,
+ // },
+ // swap_1 = Swap{
+ // offer_asset: t2,
+ // ask_asset: t3,
+ // ask_asset_min_amount: None,
+ // },
+ // swap_2 = Swap{
+ // offer_asset: t1,
+ // ask_asset: t2,
+ // ask_asset_min_amount: None,
+ // },
+ // swap_3 = Swap{
+ // offer_asset: t0,
+ // ask_asset: t1,
+ // ask_asset_min_amount: None,
+ // }
+
+ let mut operations_reversed = soroban_sdk::Vec::new(&e);
+ for op in operations.iter().rev() {
+ operations_reversed.push_back(op.clone());
+ }
+ let reverse_simulated_swap = phoenix_multihop_client.simulate_reverse_swap(
+ &operations_reversed, //operations: Vec,
+ amount_out); //amount: i128,
+
+ // TODO: Eliminate this check. The overall in max is checked by the Aggregator
+ // Removing this check will reduce the amount of instructions/
+ // TODO: Do Benchmarking
+ if reverse_simulated_swap.offer_amount > *amount_in_max {
+ panic!("Amount of token in required is greater than the maximum amount expected");
+ }
+
+ phoenix_multihop_client.swap(
+ &to, // recipient: Address,
+ &operations, // operations: Vec,
+ &None, // max_spread_bps: Option.
+ &reverse_simulated_swap.offer_amount); //amout: i128. Amount being sold. Input from the user,
+
+ // Here we trust in the amounts returned by Phoenix contracts
+ let mut swap_amounts: Vec = Vec::new(e);
+ swap_amounts.push_back(reverse_simulated_swap.offer_amount);
+ swap_amounts.push_back(*amount_out);
- // Returning empty array (should check phoenix response if it return amounts, apparently it doesnt)
- Ok(vec![&e])
+ Ok(swap_amounts)
}
\ No newline at end of file
diff --git a/contracts/adapters/phoenix/src/test.rs b/contracts/adapters/phoenix/src/test.rs
index c6ffb572..7fcf5ac0 100644
--- a/contracts/adapters/phoenix/src/test.rs
+++ b/contracts/adapters/phoenix/src/test.rs
@@ -8,18 +8,19 @@ use soroban_sdk::{
};
use crate::{SoroswapAggregatorPhoenixAdapter, SoroswapAggregatorPhoenixAdapterClient};
-use phoenix_setup::{PhoenixTest, MultihopClient, TokenClient};
+use phoenix_setup::{PhoenixTest, MultihopClient, TokenClient, PhoenixFactory};
// use factory::SoroswapFactoryClient;
// use router::SoroswapRouterClient;
// PhoenixAggregatorAdapter Contract
-fn create_soroswap_aggregator_adapter<'a>(e: &Env) -> SoroswapAggregatorPhoenixAdapterClient<'a> {
+fn create_soroswap_aggregator_phoenix_adapter<'a>(e: &Env) -> SoroswapAggregatorPhoenixAdapterClient<'a> {
SoroswapAggregatorPhoenixAdapterClient::new(e, &e.register_contract(None, SoroswapAggregatorPhoenixAdapter {}))
}
pub struct PhoenixAggregatorAdapterTest<'a> {
env: Env,
adapter_client: SoroswapAggregatorPhoenixAdapterClient<'a>,
+ factory_client: PhoenixFactory<'a>,
multihop_client: MultihopClient<'a>,
token_0: TokenClient<'a>,
token_1: TokenClient<'a>,
@@ -33,11 +34,12 @@ impl<'a> PhoenixAggregatorAdapterTest<'a> {
fn setup() -> Self {
let test = PhoenixTest::phoenix_setup();
- let adapter_client = create_soroswap_aggregator_adapter(&test.env);
+ let adapter_client = create_soroswap_aggregator_phoenix_adapter(&test.env);
PhoenixAggregatorAdapterTest {
env: test.env,
adapter_client,
+ factory_client: test.factory_client,
multihop_client: test.multihop_client,
token_0: test.token_0,
token_1: test.token_1,
@@ -51,4 +53,4 @@ impl<'a> PhoenixAggregatorAdapterTest<'a> {
pub mod initialize;
pub mod swap_exact_tokens_for_tokens;
-// pub mod swap_tokens_for_exact_tokens;
\ No newline at end of file
+pub mod swap_tokens_for_exact_tokens;
\ No newline at end of file
diff --git a/contracts/adapters/phoenix/src/test/phoenix_setup.rs b/contracts/adapters/phoenix/src/test/phoenix_setup.rs
index 58e302a6..38169cc7 100644
--- a/contracts/adapters/phoenix/src/test/phoenix_setup.rs
+++ b/contracts/adapters/phoenix/src/test/phoenix_setup.rs
@@ -2,7 +2,7 @@
// extern crate std;
use soroban_sdk::{
vec,
- IntoVal,
+ // IntoVal,
String,
Env,
Bytes,
@@ -32,7 +32,7 @@ pub fn deploy_factory_contract(e: &Env, admin: & Address) -> Address {
e.deployer().with_address(admin.clone(), salt).deploy(factory_wasm)
}
-use factory::Client as PhoenixFactory;
+pub use factory::Client as PhoenixFactory;
/* ************* MULTIHOP ************* */
#[allow(clippy::too_many_arguments)]
@@ -72,20 +72,20 @@ pub mod token_contract {
pub use token_contract::Client as TokenClient;
-pub fn create_token_contract_with_metadata<'a>(
- env: &Env,
- admin: &Address,
- decimals: u32,
- name: String,
- symbol: String,
- amount: i128,
-) -> TokenClient<'a> {
- let token =
- TokenClient::new(env, &env.register_contract_wasm(None, token_contract::WASM));
- token.initialize(admin, &decimals, &name.into_val(env), &symbol.into_val(env));
- token.mint(admin, &amount);
- token
-}
+// pub fn create_token_contract_with_metadata<'a>(
+// env: &Env,
+// admin: &Address,
+// decimals: u32,
+// name: String,
+// symbol: String,
+// amount: i128,
+// ) -> TokenClient<'a> {
+// let token =
+// TokenClient::new(env, &env.register_contract_wasm(None, token_contract::WASM));
+// token.initialize(admin, &decimals, &name.into_val(env), &symbol.into_val(env));
+// token.mint(admin, &amount);
+// token
+// }
pub fn install_token_wasm(env: &Env) -> BytesN<32> {
soroban_sdk::contractimport!(
@@ -280,11 +280,11 @@ impl<'a> PhoenixTest<'a> {
// Setup multihop
let multihop_client = deploy_multihop_contract(&env, admin.clone(), &factory_client.address);
- token_0.mint(&user, &50i128);
+ token_0.mint(&user, &1000i128);
// Check initial user value of every token:
- assert_eq!(token_0.balance(&user), 50i128);
+ assert_eq!(token_0.balance(&user), 1000i128);
assert_eq!(token_1.balance(&user), 0i128);
assert_eq!(token_2.balance(&user), 0i128);
assert_eq!(token_3.balance(&user), 0i128);
diff --git a/contracts/adapters/phoenix/src/test/swap_exact_tokens_for_tokens.rs b/contracts/adapters/phoenix/src/test/swap_exact_tokens_for_tokens.rs
index 333d5a3d..160e35b7 100644
--- a/contracts/adapters/phoenix/src/test/swap_exact_tokens_for_tokens.rs
+++ b/contracts/adapters/phoenix/src/test/swap_exact_tokens_for_tokens.rs
@@ -1,5 +1,5 @@
use soroban_sdk::{Address, vec, Vec, String};
-use crate::test::{PhoenixAggregatorAdapterTest};
+use crate::test::{PhoenixAggregatorAdapterTest, phoenix_setup::deploy_and_initialize_lp};
use soroswap_aggregator_adapter_interface::{AdapterError};
@@ -145,7 +145,8 @@ fn try_swap_exact_tokens_for_tokens_insufficient_input_amount() {
#[test]
-#[should_panic] // TODO: Test the imported error
+// #[should_panic] // TODO: Change to an error object (If we dont delete this check)
+#[should_panic(expected = "Amount of token out received is less than the minimum amount expected")]
fn swap_exact_tokens_for_tokens_insufficient_output_amount() {
let test = PhoenixAggregatorAdapterTest::setup();
test.adapter_client.initialize(
@@ -161,10 +162,8 @@ fn swap_exact_tokens_for_tokens_insufficient_output_amount() {
path.push_back(test.token_3.address.clone());
let amount_in = 50i128;
-
- //(1000000×997×4000000000000000000)÷(1000000000000000000×1000+997×1000000) = 3987999,9
-
- let expected_amount_out = 50;
+ // The next taken from phoenix contract tests
+ let expected_amount_out = 50i128;
test.env.budget().reset_unlimited();
test.adapter_client.swap_exact_tokens_for_tokens(
@@ -175,57 +174,121 @@ fn swap_exact_tokens_for_tokens_insufficient_output_amount() {
&deadline, // deadline
);
- // TODO TEST THAT WE GET THE RIGHT ERROR
- assert_eq!(test.token_0.balance(&test.user), 0);
- assert_eq!(test.token_1.balance(&test.user), 0);
- assert_eq!(test.token_2.balance(&test.user), 0);
- assert_eq!(test.token_3.balance(&test.user), 50);
+}
+
+
+
+#[test]
+fn swap_exact_tokens_for_tokens_enough_output_amount() {
+ let test = PhoenixAggregatorAdapterTest::setup();
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
+
+ let deadline: u64 = test.env.ledger().timestamp() + 1000;
+
+ let mut path: Vec = Vec::new(&test.env);
+
+ path.push_back(test.token_0.address.clone());
+ path.push_back(test.token_1.address.clone());
+ path.push_back(test.token_2.address.clone());
+ path.push_back(test.token_3.address.clone());
+
+ let amount_in = 500i128;
+ // The next taken from phoenix contract tests
+ // TODO: Check with future versions of phoenix
+ let expected_amount_out = 500i128;
+
+ let initial_user_balance_0 = test.token_0.balance(&test.user);
+ let initial_user_balance_1 = test.token_1.balance(&test.user);
+ let initial_user_balance_2 = test.token_2.balance(&test.user);
+ let initial_user_balance_3 = test.token_3.balance(&test.user);
+
+ let token_out_address = path.get(path.len() - 1).expect("Failed to get token out address");
+
+ assert_eq!(token_out_address, test.token_3.address);
+
+ test.env.budget().reset_unlimited();
+ let executed_amounts = test.adapter_client.swap_exact_tokens_for_tokens(
+ &amount_in, // amount_in
+ &(expected_amount_out), // amount_out_min
+ &path, // path
+ &test.user, // to
+ &deadline, // deadline
+ );
+
- // assert_eq!(
- // result,
- // Err(Ok(CombinedRouterError::RouterInsufficientOutputAmount))
- // );
+ assert_eq!(test.token_0.balance(&test.user), initial_user_balance_0 - amount_in);
+ assert_eq!(test.token_1.balance(&test.user), initial_user_balance_1);
+ assert_eq!(test.token_2.balance(&test.user), initial_user_balance_2);
+ assert_eq!(test.token_3.balance(&test.user), initial_user_balance_3 + expected_amount_out);
+
+ // WE NEED TO RETURN THE VALUES
+ assert_eq!(executed_amounts.get(0).unwrap(), amount_in);
+ assert_eq!(executed_amounts.get(1).unwrap(), expected_amount_out);
}
-// #[test]
-// fn swap_exact_tokens_for_tokens_enough_output_amount() {
-// let test = PhoenixAggregatorAdapterTest::setup();
-// test.adapter_client.initialize(
-// &String::from_str(&test.env, "phoenix"),
-// &test.multihop_client.address);
+#[test]
+fn swap_exact_tokens_for_tokens_enough_output_amount_with_fees() {
+ let test = PhoenixAggregatorAdapterTest::setup();
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
-// let deadline: u64 = test.env.ledger().timestamp() + 1000;
+ // we will make a pool betwern token 0 and token 2 with fees
+ deploy_and_initialize_lp(
+ &test.env,
+ &test.factory_client,
+ test.admin.clone(),
+ test.token_0.address.clone(),
+ 1_000_000,
+ test.token_2.address.clone(),
+ 1_000_000,
+ Some(2000),
+ );
-// let mut path: Vec = Vec::new(&test.env);
-// path.push_back(test.token_0.address.clone());
-// path.push_back(test.token_1.address.clone());
-// path.push_back(test.token_0.address.clone());
-// path.push_back(test.token_1.address.clone());
-// path.push_back(test.token_2.address.clone());
-// path.push_back(test.token_3.address.clone());
+ let deadline: u64 = test.env.ledger().timestamp() + 1000;
-// let amount_in = 50i128;
+ let mut path: Vec = Vec::new(&test.env);
-// //(1000000×997×4000000000000000000)÷(1000000000000000000×1000+997×1000000) = 3987999,9
+ path.push_back(test.token_0.address.clone());
+ // path.push_back(test.token_1.address.clone());
+ path.push_back(test.token_2.address.clone());
+ // path.push_back(test.token_3.address.clone());
+
+ let amount_in = 300i128;
+ // The next taken from phoenix contract tests
+ // TODO: Check with future versions of phoenix
+ // 1000 tokens initially
+ // swap 300 from token0 to token1 with 2000 bps (20%)
+ // tokens1 will be 240
+ let expected_amount_out = 240i128;
+
+ let initial_user_balance_0 = test.token_0.balance(&test.user);
+ // let initial_user_balance_1 = test.token_1.balance(&test.user);
+ let initial_user_balance_2 = test.token_2.balance(&test.user);
+ // let initial_user_balance_3 = test.token_3.balance(&test.user);
+
+ test.env.budget().reset_unlimited();
+ let executed_amounts = test.adapter_client.swap_exact_tokens_for_tokens(
+ &amount_in, // amount_in
+ &(expected_amount_out), // amount_out_min
+ &path, // path
+ &test.user, // to
+ &deadline, // deadline
+ );
-// let expected_amount_out = 50;
-// test.env.budget().reset_unlimited();
-// let executed_amounts = test.adapter_client.swap_exact_tokens_for_tokens(
-// &amount_in, // amount_in
-// &(expected_amount_out), // amount_out_min
-// &path, // path
-// &test.user, // to
-// &deadline, // deadline
-// );
+ assert_eq!(test.token_0.balance(&test.user), initial_user_balance_0 - amount_in);
+ assert_eq!(test.token_2.balance(&test.user), initial_user_balance_2 + expected_amount_out);
-// // WE NEED TO RETURN THE VALUES
-// assert_eq!(executed_amounts.get(0).unwrap(), amount_in);
-// assert_eq!(executed_amounts.get(1).unwrap(), expected_amount_out);
-// }
+ // WE NEED TO RETURN THE VALUES
+ assert_eq!(executed_amounts.get(0).unwrap(), amount_in);
+ assert_eq!(executed_amounts.get(1).unwrap(), expected_amount_out);
+}
// use crate::factory_contract::PoolType;
diff --git a/contracts/adapters/phoenix/src/test/swap_tokens_for_exact_tokens.rs b/contracts/adapters/phoenix/src/test/swap_tokens_for_exact_tokens.rs
index 6ac963ec..1e2db538 100644
--- a/contracts/adapters/phoenix/src/test/swap_tokens_for_exact_tokens.rs
+++ b/contracts/adapters/phoenix/src/test/swap_tokens_for_exact_tokens.rs
@@ -1,16 +1,17 @@
use soroban_sdk::{Address, vec, Vec, String};
-use soroban_sdk::testutils::Ledger;
-use crate::test::{SoroswapAggregatorAdapterTest};
+use crate::test::{PhoenixAggregatorAdapterTest};
use soroswap_aggregator_adapter_interface::{AdapterError};
+use soroban_sdk::testutils::Ledger;
+
#[test]
fn swap_tokens_for_exact_tokens_not_initialized() {
- let test = SoroswapAggregatorAdapterTest::setup();
+ let test = PhoenixAggregatorAdapterTest::setup();
test.env.budget().reset_unlimited();
let path: Vec = Vec::new(&test.env);
- let result = test.adapter_contract.try_swap_tokens_for_exact_tokens(
+ let result = test.adapter_client.try_swap_tokens_for_exact_tokens(
&0, // amount_out
&0, // amount_in_max
&path, // path
@@ -24,17 +25,16 @@ fn swap_tokens_for_exact_tokens_not_initialized() {
#[test]
fn swap_tokens_for_exact_tokens_amount_out_negative() {
- let test = SoroswapAggregatorAdapterTest::setup();
+ let test = PhoenixAggregatorAdapterTest::setup();
test.env.budget().reset_unlimited();
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
-
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let path: Vec = Vec::new(&test.env);
- let result = test.adapter_contract.try_swap_tokens_for_exact_tokens(
+ let result = test.adapter_client.try_swap_tokens_for_exact_tokens(
&-1, // amount_out
&0, // amount_in_max
&path, // path
@@ -50,17 +50,16 @@ fn swap_tokens_for_exact_tokens_amount_out_negative() {
#[test]
fn swap_tokens_for_exact_tokens_amount_in_max_negative() {
- let test = SoroswapAggregatorAdapterTest::setup();
+ let test = PhoenixAggregatorAdapterTest::setup();
test.env.budget().reset_unlimited();
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
-
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let path: Vec = Vec::new(&test.env);
- let result = test.adapter_contract.try_swap_tokens_for_exact_tokens(
+ let result = test.adapter_client.try_swap_tokens_for_exact_tokens(
&0, // amount_out
&-1, // amount_in_max
&path, // path
@@ -76,16 +75,15 @@ fn swap_tokens_for_exact_tokens_amount_in_max_negative() {
#[test]
fn swap_tokens_for_exact_tokens_expired() {
- let test = SoroswapAggregatorAdapterTest::setup();
-
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
+ let test = PhoenixAggregatorAdapterTest::setup();
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let path: Vec = Vec::new(&test.env);
- let result = test.adapter_contract.try_swap_tokens_for_exact_tokens(
+ let result = test.adapter_client.try_swap_tokens_for_exact_tokens(
&0, // amount_out
&0, // amount_in_max
&path, // path
@@ -103,18 +101,17 @@ fn swap_tokens_for_exact_tokens_expired() {
#[test]
#[should_panic] // TODO: Test the imported error
fn try_swap_tokens_for_exact_tokens_invalid_path() {
- let test = SoroswapAggregatorAdapterTest::setup();
-
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
+ let test = PhoenixAggregatorAdapterTest::setup();
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let deadline: u64 = test.env.ledger().timestamp() + 1000;
let path: Vec = vec![&test.env, test.token_0.address.clone()];
- let result = test.adapter_contract.swap_tokens_for_exact_tokens( // add try_ to test the error
+ test.adapter_client.swap_tokens_for_exact_tokens( // add try_ to test the error
&0, // amount_out
&0, // amount_in_max
&path, // path
@@ -130,22 +127,21 @@ fn try_swap_tokens_for_exact_tokens_invalid_path() {
// Panics because LP does not exist; here panics with a Error(Storage, MissingValue)
// We should implement a pair_address.exist() without needing to call the Factory
#[should_panic]
-fn swap_tokens_for_exact_tokens_pair_does_not_exist() {
- let test = SoroswapAggregatorAdapterTest::setup();
-
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
+fn try_swap_tokens_for_exact_tokens_pair_does_not_exist() {
+ let test = PhoenixAggregatorAdapterTest::setup();
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let deadline: u64 = test.env.ledger().timestamp() + 1000;
let mut path: Vec = Vec::new(&test.env);
path.push_back(test.token_0.address.clone());
- path.push_back(test.token_1.address.clone());
+ path.push_back(test.token_3.address.clone());
- test.adapter_contract.swap_tokens_for_exact_tokens(
- &0, //amount_out
+ test.adapter_client.swap_tokens_for_exact_tokens(
+ &1, //amount_out
&0, // amount_in_max
&path, // path
&test.user, // to
@@ -156,12 +152,11 @@ fn swap_tokens_for_exact_tokens_pair_does_not_exist() {
#[test]
#[should_panic] // TODO: Test the imported error
fn try_swap_tokens_for_exact_tokens_insufficient_output_amount() {
- let test = SoroswapAggregatorAdapterTest::setup();
-
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
+ let test = PhoenixAggregatorAdapterTest::setup();
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let deadline: u64 = test.env.ledger().timestamp() + 1000;
@@ -171,7 +166,7 @@ fn try_swap_tokens_for_exact_tokens_insufficient_output_amount() {
test.env.budget().reset_unlimited();
- let result = test.adapter_contract.swap_tokens_for_exact_tokens(
+ test.adapter_client.swap_tokens_for_exact_tokens(
&0, // amount_out
&0, // amount_in_max
&path, // path
@@ -182,15 +177,14 @@ fn try_swap_tokens_for_exact_tokens_insufficient_output_amount() {
}
#[test]
-#[should_panic] // TODO: Test the imported error
-fn swap_tokens_for_exact_tokens_amount_in_max_not_enough() {
- let test = SoroswapAggregatorAdapterTest::setup();
+#[should_panic(expected = "Amount of token in required is greater than the maximum amount expected")] // TODO: Test the imported error
+fn try_swap_tokens_for_exact_tokens_amount_in_max_not_enough() {
+ let test = PhoenixAggregatorAdapterTest::setup();
test.env.budget().reset_unlimited();
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
-
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let deadline: u64 = test.env.ledger().timestamp() + 1000;
@@ -198,71 +192,34 @@ fn swap_tokens_for_exact_tokens_amount_in_max_not_enough() {
path.push_back(test.token_0.address.clone());
path.push_back(test.token_1.address.clone());
- let expected_amount_out = 5_000_000;
+ let expected_amount_out = 50;
+ // From Phoenix tests
+ let amount_in_should = 50;
- let result = test.adapter_contract.swap_tokens_for_exact_tokens(
+ test.adapter_client.swap_tokens_for_exact_tokens(
&expected_amount_out, // amount_out
- &0, // amount_in_max
+ &(amount_in_should-1), // amount_in_max
&path, // path
&test.user, // to
&deadline, // deadline
);
- // assert_eq!(
- // result,
- // Err(Ok(CombinedRouterError::RouterExcessiveInputAmount))
- // );
-}
-
-#[test]
-#[should_panic] // TODO: Test the imported error
-fn swap_tokens_for_exact_tokens_amount_in_max_not_enough_amount_in_should_minus_1() {
- let test = SoroswapAggregatorAdapterTest::setup();
- test.env.budget().reset_unlimited();
-
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
-
-
- let deadline: u64 = test.env.ledger().timestamp() + 1000;
-
- let mut path: Vec = Vec::new(&test.env);
- path.push_back(test.token_0.address.clone());
- path.push_back(test.token_1.address.clone());
-
-
- let expected_amount_out = 5_000_000;
- let amount_in_should = test
- .router_contract
- .router_get_amounts_in(&expected_amount_out, &path)
- .get(0)
- .unwrap();
-
- let result = test.adapter_contract.swap_tokens_for_exact_tokens(
- &expected_amount_out, // amount_out
- &(amount_in_should - 1), // amount_in_max
- &path, // path
- &test.user, // to
- &deadline, // deadline
- );
+ // TODO: Evaluate if change panic message with error object (check benchmark)
// assert_eq!(
// result,
// Err(Ok(CombinedRouterError::RouterExcessiveInputAmount))
// );
}
-
#[test]
fn swap_tokens_for_exact_tokens_amount_in_should() {
- let test = SoroswapAggregatorAdapterTest::setup();
+ let test = PhoenixAggregatorAdapterTest::setup();
test.env.budget().reset_unlimited();
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
-
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let deadline: u64 = test.env.ledger().timestamp() + 1000;
@@ -270,13 +227,14 @@ fn swap_tokens_for_exact_tokens_amount_in_should() {
path.push_back(test.token_0.address.clone());
path.push_back(test.token_1.address.clone());
- let amount_0: i128 = 1_000_000_000_000_000_000;
- let amount_1: i128 = 4_000_000_000_000_000_000;
+ let expected_amount_out = 50;
+ // From Phoenix tests
+ let amount_in_should = 50;
- let expected_amount_out = 5_000_000;
- let amount_in_should = test.router_contract.router_get_amounts_in(&expected_amount_out, &path).get(0).unwrap();
+ let initial_user_balance_0 = test.token_0.balance(&test.user);
+ let initial_user_balance_1 = test.token_1.balance(&test.user);
- let amounts = test.adapter_contract.swap_tokens_for_exact_tokens(
+ let amounts = test.adapter_client.swap_tokens_for_exact_tokens(
&expected_amount_out, //amount_out
&(amount_in_should), // amount_in_max
&path, // path
@@ -286,49 +244,21 @@ fn swap_tokens_for_exact_tokens_amount_in_should() {
assert_eq!(amounts.get(0).unwrap(), amount_in_should);
assert_eq!(amounts.get(1).unwrap(), expected_amount_out);
- let initial_user_balance = 20_000_000_000_000_000_000;
-
- // pub fn get_amount_in(amount_out: i128, reserve_in: i128, reserve_out: i128) -> Result {
- // if amount_out <= 0 {
- // return Err(SoroswapLibraryError::InsufficientOutputAmount);
- // }
- // if reserve_in <= 0 || reserve_out <= 0 {
- // return Err(SoroswapLibraryError::InsufficientLiquidity);
- // }
- // let numerator = reserve_in.checked_mul(amount_out).unwrap().checked_mul(1000).unwrap();
- // let denominator = reserve_out.checked_sub(amount_out).unwrap().checked_mul(997).unwrap();
- // Ok(numerator.checked_ceiling_div(denominator).unwrap().checked_add(1).unwrap())
- // }
-
- // numerator = 1_000_000_000_000_000_000 * 5_000_000 * 1_000 = 5_000_000_000_000_000_000_000_000_000
- // denominator = (4000000000000000000 - 5000000) * 997 = 3999999999995000000 * 997 = 3987999999995015000000
-
- // num/den +1 = 5000000000000000000000000000 / 3987999999995015000000 +1 = ceil(1253761.283853122) +1
- // = 1253762 + 1 = 1253763
-
- let expected_amount_0_in = 1253763;
- assert_eq!(amounts.get(0).unwrap(), expected_amount_0_in);
-
- assert_eq!(test.token_0.balance(&test.user), initial_user_balance - amount_0 - expected_amount_0_in);
- assert_eq!(test.token_1.balance(&test.user), initial_user_balance - amount_1*2 + expected_amount_out);
-
- let pair_address = test.factory_contract.get_pair(&test.token_0.address, &test.token_1.address);
- assert_eq!(test.token_0.balance(&pair_address), amount_0 + expected_amount_0_in);
- assert_eq!(test.token_1.balance(&pair_address), amount_1 - expected_amount_out);
+ assert_eq!(test.token_0.balance(&test.user), initial_user_balance_0 - amount_in_should);
+ assert_eq!(test.token_1.balance(&test.user), initial_user_balance_1 + expected_amount_out);
}
#[test]
-fn swap_tokens_for_exact_tokens_2_hops() {
- let test = SoroswapAggregatorAdapterTest::setup();
+fn swap_tokens_for_exact_tokens_3_hops() {
+ let test = PhoenixAggregatorAdapterTest::setup();
test.env.budget().reset_unlimited();
- test.adapter_contract.initialize(
- &String::from_str(&test.env, "soroswap"),
- &test.router_contract.address);
-
+ test.adapter_client.initialize(
+ &String::from_str(&test.env, "phoenix"),
+ &test.multihop_client.address);
let ledger_timestamp = 100;
let desired_deadline = 1000;
@@ -337,37 +267,22 @@ fn swap_tokens_for_exact_tokens_2_hops() {
li.timestamp = ledger_timestamp;
});
- let initial_user_balance = 20_000_000_000_000_000_000;
-
- let amount_0: i128 = 1_000_000_000_000_000_000;
- let amount_1: i128 = 4_000_000_000_000_000_000;
- let amount_2: i128 = 8_000_000_000_000_000_000;
-
let mut path: Vec = Vec::new(&test.env);
path.push_back(test.token_0.address.clone());
path.push_back(test.token_1.address.clone());
path.push_back(test.token_2.address.clone());
+ path.push_back(test.token_3.address.clone());
+
+ let expected_amount_out = 50;
+ // From Phoenix tests
+ let amount_in_should =50;
+
+ let initial_user_balance_0 = test.token_0.balance(&test.user);
+ let initial_user_balance_1 = test.token_1.balance(&test.user);
+ let initial_user_balance_2 = test.token_2.balance(&test.user);
+ let initial_user_balance_3 = test.token_3.balance(&test.user);
- let expected_amount_out = 123_456_789;
- // pair token_1, token_2
- // token_1 is r_in, token_2 is r_out
- // (r_in*amount_out)*1000 / (r_out - amount_out)*997
- // (4_000_000_000_000_000_000*123456789)*1000 / ((8_000_000_000_000_000_000 - 123456789)*997) + 1 =
- // 493827156000000000000000000000 / (7999999999876543211 * 997) +1 =
- // 493827156000000000000000000000 / 7975999999876913581367 +1 = CEIL(61914136.911687662) +1 = 61914137 +1 = 61914138
- //
- let middle_amount_in =61914138;
-
- // pair token_0, token_1
- // token_0 is r_in, token_1 is r_out
- // first amount in =
- // (1_000_000_000_000_000_000*61914138)*1000 / ((4_000_000_000_000_000_000 - 61914138)*997) + 1 =
- // 61914138000000000000000000000 / (3999999999938085862 * 997) + 1 =
- // CEIL (61914138000000000000000000000 / 3987999999938271604414) +1 = ceil(15525109.8) +1 = 15525111
-
- let amount_in_should =15525111;
-
- let amounts = test.adapter_contract.swap_tokens_for_exact_tokens(
+ let amounts = test.adapter_client.swap_tokens_for_exact_tokens(
&expected_amount_out, //amount_out
&amount_in_should, // amount_in_max
&path, // path
@@ -376,18 +291,10 @@ fn swap_tokens_for_exact_tokens_2_hops() {
assert_eq!(amounts.get(0).unwrap(), amount_in_should);
- assert_eq!(amounts.get(1).unwrap(), middle_amount_in);
- assert_eq!(amounts.get(2).unwrap(), expected_amount_out);
-
- assert_eq!(test.token_0.balance(&test.user), initial_user_balance - amount_0 - amount_in_should);
- assert_eq!(test.token_1.balance(&test.user), initial_user_balance - amount_1*2);
- assert_eq!(test.token_2.balance(&test.user), initial_user_balance - amount_2 + expected_amount_out);
-
- let pair_address_0_1 = test.factory_contract.get_pair(&test.token_0.address, &test.token_1.address);
- assert_eq!(test.token_0.balance(&pair_address_0_1), amount_0 + amount_in_should);
- assert_eq!(test.token_1.balance(&pair_address_0_1), amount_1 - middle_amount_in);
+ assert_eq!(amounts.get(1).unwrap(), expected_amount_out);
- let pair_address_1_2 = test.factory_contract.get_pair(&test.token_1.address, &test.token_2.address);
- assert_eq!(test.token_1.balance(&pair_address_1_2), amount_1 + middle_amount_in);
- assert_eq!(test.token_2.balance(&pair_address_1_2), amount_2 - expected_amount_out);
+ assert_eq!(test.token_0.balance(&test.user), initial_user_balance_0 - amount_in_should);
+ assert_eq!(test.token_1.balance(&test.user), initial_user_balance_1);
+ assert_eq!(test.token_2.balance(&test.user), initial_user_balance_2);
+ assert_eq!(test.token_3.balance(&test.user), initial_user_balance_3 + expected_amount_out);
}
diff --git a/contracts/aggregator/src/test.rs b/contracts/aggregator/src/test.rs
index d4827e1e..3468b98a 100644
--- a/contracts/aggregator/src/test.rs
+++ b/contracts/aggregator/src/test.rs
@@ -7,99 +7,60 @@ use soroban_sdk::{
vec, Address, BytesN, Env, String, Vec,
};
+mod soroswap_setup;
+use soroswap_setup::{
+ create_soroswap_adapter,
+ create_soroswap_factory,
+ create_soroswap_router,
+ SoroswapAggregatorAdapterForSoroswapClient,
+ SoroswapRouterClient,
+};
+
+mod phoenix_setup;
+use phoenix_setup::{
+ create_phoenix_adapter,
+ deploy_and_initialize_factory as phoenix_deploy_and_initialize_factory,
+ deploy_and_initialize_lp as phoenix_deploy_and_initialize_lp,
+ deploy_multihop_contract as phoenix_deploy_multihop_contract,
+ SoroswapAggregatorAdapterForPhoenixClient
+};
+
+// SoroswapAggregator Contract [THE MAIN CONTRACT]
+fn create_soroswap_aggregator<'a>(e: &Env) -> SoroswapAggregatorClient<'a> {
+ SoroswapAggregatorClient::new(e, &e.register_contract(None, SoroswapAggregator {}))
+}
+
+
// Token Contract
mod token {
soroban_sdk::contractimport!(file = "../adapters/soroswap/soroswap_contracts/soroban_token_contract.wasm");
pub type TokenClient<'a> = Client<'a>;
}
use token::TokenClient;
-
pub fn create_token_contract<'a>(e: &Env, admin: &Address) -> TokenClient<'a> {
TokenClient::new(&e, &e.register_stellar_asset_contract(admin.clone()))
}
-// // Pair Contract
-// mod pair {
-// soroban_sdk::contractimport!(file = "../../protocols/soroswap/contracts/pair/target/wasm32-unknown-unknown/release/soroswap_pair.wasm");
-// pub type SoroswapPairClient<'a> = Client<'a>;
-// }
-// use pair::SoroswapPairClient;
-
-fn pair_contract_wasm(e: &Env) -> BytesN<32> {
- soroban_sdk::contractimport!(
- file = "../adapters/soroswap/soroswap_contracts/soroswap_pair.wasm"
- );
- e.deployer().upload_contract_wasm(WASM)
-}
-
-// SoroswapFactory Contract
-mod factory {
- soroban_sdk::contractimport!(file = "../adapters/soroswap/soroswap_contracts/soroswap_factory.wasm");
- pub type SoroswapFactoryClient<'a> = Client<'a>;
-}
-use factory::SoroswapFactoryClient;
-
-fn create_soroswap_factory<'a>(e: &Env, setter: &Address) -> SoroswapFactoryClient<'a> {
- let pair_hash = pair_contract_wasm(&e);
- let factory_address = &e.register_contract_wasm(None, factory::WASM);
- let factory = SoroswapFactoryClient::new(e, factory_address);
- factory.initialize(&setter, &pair_hash);
- factory
-}
-
-// SoroswapRouter Contract
-mod router {
- soroban_sdk::contractimport!(file = "../adapters/soroswap/soroswap_contracts/soroswap_router.optimized.wasm");
- pub type SoroswapRouterClient<'a> = Client<'a>;
-}
-use router::SoroswapRouterClient;
-
-// SoroswapRouter Contract
-pub fn create_soroswap_router<'a>(e: &Env) -> SoroswapRouterClient<'a> {
- let router_address = &e.register_contract_wasm(None, router::WASM);
- let router = SoroswapRouterClient::new(e, router_address);
- router
-}
-// SoroswapAggregatorAdapter Contract
-// For Soroswap
-mod soroswap_adapter {
- soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/soroswap_adapter.optimized.wasm");
- pub type SoroswapAggregatorAdapterForSoroswapClient<'a> = Client<'a>;
-}
-use soroswap_adapter::SoroswapAggregatorAdapterForSoroswapClient;
-
-// Adapter for Soroswap
-fn create_soroswap_adapter<'a>(e: &Env) -> SoroswapAggregatorAdapterForSoroswapClient<'a> {
- let adapter_address = &e.register_contract_wasm(None, soroswap_adapter::WASM);
- let adapter = SoroswapAggregatorAdapterForSoroswapClient::new(e, adapter_address);
- adapter
-}
-
-// SoroswapAggregatorAdapter Contract
-// For Phoenix
-mod phoenix_adapter {
+pub fn install_token_wasm(env: &Env) -> BytesN<32> {
soroban_sdk::contractimport!(
- file =
- "../target/wasm32-unknown-unknown/release/phoenix_adapter.optimized.wasm"
+ file = "../adapters/soroswap/soroswap_contracts/soroban_token_contract.wasm"
);
- pub type SoroswapAggregatorAdapterForPhoenixClient<'a> = Client<'a>;
-}
-use phoenix_adapter::SoroswapAggregatorAdapterForPhoenixClient;
-
-// Adapter for phoenix
-fn create_phoenix_adapter<'a>(e: &Env) -> SoroswapAggregatorAdapterForPhoenixClient<'a> {
- let adapter_address = &e.register_contract_wasm(None, phoenix_adapter::WASM);
- let adapter = SoroswapAggregatorAdapterForPhoenixClient::new(e, adapter_address);
- adapter
+ env.deployer().upload_contract_wasm(WASM)
}
-// SoroswapAggregator Contract
-fn create_soroswap_aggregator<'a>(e: &Env) -> SoroswapAggregatorClient<'a> {
- SoroswapAggregatorClient::new(e, &e.register_contract(None, SoroswapAggregator {}))
-}
// Helper function to initialize / update soroswap aggregator protocols
pub fn create_protocols_addresses(test: &SoroswapAggregatorTest) -> Vec {
+ vec![
+ &test.env,
+ Adapter {
+ protocol_id: String::from_str(&test.env, "soroswap"),
+ address: test.soroswap_adapter_contract.address.clone(),
+ paused: false,
+ }
+ ]
+}
+pub fn create_soroswap_phoenix_addresses(test: &SoroswapAggregatorTest) -> Vec {
vec![
&test.env,
Adapter {
@@ -107,6 +68,11 @@ pub fn create_protocols_addresses(test: &SoroswapAggregatorTest) -> Vec
address: test.soroswap_adapter_contract.address.clone(),
paused: false,
},
+ Adapter {
+ protocol_id: String::from_str(&test.env, "phoenix"),
+ address: test.phoenix_adapter_contract.address.clone(),
+ paused: false,
+ },
]
}
@@ -115,7 +81,7 @@ pub fn new_update_adapters_addresses(test: &SoroswapAggregatorTest) -> Vec Vec Vec Vec {
env: Env,
aggregator_contract: SoroswapAggregatorClient<'a>,
- router_contract: SoroswapRouterClient<'a>,
- // factory_contract: SoroswapFactoryClient<'a>,
+ soroswap_router_contract: SoroswapRouterClient<'a>,
+ // soroswap_factory_contract: SoroswapFactoryClient<'a>,
soroswap_adapter_contract: SoroswapAggregatorAdapterForSoroswapClient<'a>,
- // phoenix_adapter_contract: SoroswapAggregatorAdapterForPhoenixClient<'a>,
+ phoenix_adapter_contract: SoroswapAggregatorAdapterForPhoenixClient<'a>,
token_0: TokenClient<'a>,
token_1: TokenClient<'a>,
token_2: TokenClient<'a>,
@@ -158,11 +124,6 @@ impl<'a> SoroswapAggregatorTest<'a> {
let env = Env::default();
env.mock_all_auths();
let aggregator_contract = create_soroswap_aggregator(&env);
- let router_contract = create_soroswap_router(&env);
- let soroswap_adapter_contract = create_soroswap_adapter(&env);
- let _phoenix_adapter_contract = create_phoenix_adapter(&env);
-
- let initial_user_balance = 20_000_000_000_000_000_000;
let admin = Address::generate(&env);
let user = Address::generate(&env);
@@ -171,19 +132,31 @@ impl<'a> SoroswapAggregatorTest<'a> {
let token_0 = create_token_contract(&env, &admin);
let token_1 = create_token_contract(&env, &admin);
let token_2 = create_token_contract(&env, &admin);
+ let token_3 = create_token_contract(&env, &admin);
+ let initial_user_balance = 20_000_000_000_000_000_000;
token_0.mint(&user, &initial_user_balance);
token_1.mint(&user, &initial_user_balance);
token_2.mint(&user, &initial_user_balance);
-
- let factory_contract = create_soroswap_factory(&env, &admin);
+ token_3.mint(&user, &initial_user_balance);
+
+ token_0.mint(&admin, &initial_user_balance);
+ token_1.mint(&admin, &initial_user_balance);
+ token_2.mint(&admin, &initial_user_balance);
+ token_3.mint(&admin, &initial_user_balance);
+
+
+
+ /* INITIALIZE SOROSWAP FACTORY, ROUTER AND LPS */
+ /************************************************/
env.budget().reset_unlimited();
+ let soroswap_router_contract = create_soroswap_router(&env);
+ let soroswap_factory_contract = create_soroswap_factory(&env, &admin);
+ soroswap_router_contract.initialize(&soroswap_factory_contract.address);
let ledger_timestamp = 100;
let desired_deadline = 1000;
-
assert!(desired_deadline > ledger_timestamp);
-
env.ledger().with_mut(|li| {
li.timestamp = ledger_timestamp;
});
@@ -198,13 +171,12 @@ impl<'a> SoroswapAggregatorTest<'a> {
assert_eq!(token_1.balance(&user), initial_user_balance);
assert_eq!(token_2.balance(&user), initial_user_balance);
- router_contract.initialize(&factory_contract.address);
assert_eq!(
- factory_contract.pair_exists(&token_0.address, &token_1.address),
+ soroswap_factory_contract.pair_exists(&token_0.address, &token_1.address),
false
);
- let (added_token_0_0, added_token_1_0, added_liquidity_0_1) = router_contract
+ let (added_token_0_0, added_token_1_0, added_liquidity_0_1) = soroswap_router_contract
.add_liquidity(
&token_0.address, // token_a: Address,
&token_1.address, // token_b: Address,
@@ -216,7 +188,7 @@ impl<'a> SoroswapAggregatorTest<'a> {
&desired_deadline, // deadline: u64,
);
- let (added_token_1_1, added_token_2_0, added_liquidity_1_2) = router_contract
+ let (added_token_1_1, added_token_2_0, added_liquidity_1_2) = soroswap_router_contract
.add_liquidity(
&token_1.address, // token_a: Address,
&token_2.address, // token_b: Address,
@@ -228,25 +200,12 @@ impl<'a> SoroswapAggregatorTest<'a> {
&desired_deadline, // deadline: u64,
);
- // let (added_token_0_1, added_token_2_1, added_liquidity_0_2) = router_contract.add_liquidity(
- // &token_0.address, // token_a: Address,
- // &token_2.address, // token_b: Address,
- // &amount_0, // amount_a_desired: i128,
- // &amount_1, // amount_b_desired: i128,
- // &0, // amount_a_min: i128,
- // &0 , // amount_b_min: i128,
- // &user, // to: Address,
- // &desired_deadline// deadline: u64,
- // );
-
static MINIMUM_LIQUIDITY: i128 = 1000;
assert_eq!(added_token_0_0, amount_0);
assert_eq!(added_token_1_0, amount_1);
assert_eq!(added_token_1_1, amount_1);
assert_eq!(added_token_2_0, amount_2);
- // assert_eq!(added_token_0_1, amount_0);
- // assert_eq!(added_token_2_1, amount_1);
assert_eq!(
added_liquidity_0_1,
@@ -259,19 +218,71 @@ impl<'a> SoroswapAggregatorTest<'a> {
assert_eq!(token_1.balance(&user), 12_000_000_000_000_000_000);
assert_eq!(token_2.balance(&user), 12_000_000_000_000_000_000);
- // Initializing Soroswap Adapter Contract
+
+ /* INITIALIZE PHOENIX FACTORY, LP AND MULTIHOP */
+ /************************************************/
+ let phoenix_factory_client = phoenix_deploy_and_initialize_factory(&env.clone(), admin.clone());
+
+
+ phoenix_deploy_and_initialize_lp(
+ &env,
+ &phoenix_factory_client,
+ admin.clone(),
+ token_0.address.clone(),
+ 1_000_000_000_000_000_000,
+ token_1.address.clone(),
+ 1_000_000_000_000_000_000,
+ None,
+ );
+ phoenix_deploy_and_initialize_lp(
+ &env,
+ &phoenix_factory_client,
+ admin.clone(),
+ token_1.address.clone(),
+ 1_000_000_000_000_000_000,
+ token_2.address.clone(),
+ 1_000_000_000_000_000_000,
+ None,
+ );
+ phoenix_deploy_and_initialize_lp(
+ &env,
+ &phoenix_factory_client,
+ admin.clone(),
+ token_2.address.clone(),
+ 1_000_000_000_000_000_000,
+ token_3.address.clone(),
+ 1_000_000_000_000_000_000,
+ None,
+ );
+
+ let phoenix_multihop_client = phoenix_deploy_multihop_contract(
+ &env,
+ admin.clone(),
+ &phoenix_factory_client.address);
+
+
+ /* CREATE ADAPTERS */
+ // Create and Initializing Soroswap Adapter Contract
+ let soroswap_adapter_contract = create_soroswap_adapter(&env);
soroswap_adapter_contract.initialize(
&String::from_str(&env, "soroswap"),
- &router_contract.address,
+ &soroswap_router_contract.address,
+ );
+
+ let phoenix_adapter_contract = create_phoenix_adapter(&env);
+ phoenix_adapter_contract.initialize(
+ &String::from_str(&env, "phoenix"),
+ &phoenix_multihop_client.address
);
+
SoroswapAggregatorTest {
env,
aggregator_contract,
- router_contract,
- // factory_contract,
+ soroswap_router_contract,
+ // soroswap_factory_contract,
soroswap_adapter_contract,
- // phoenix_adapter_contract,
+ phoenix_adapter_contract,
token_0,
token_1,
token_2,
diff --git a/contracts/aggregator/src/test/events.rs b/contracts/aggregator/src/test/events.rs
index b53b8ce4..1c9faca7 100644
--- a/contracts/aggregator/src/test/events.rs
+++ b/contracts/aggregator/src/test/events.rs
@@ -381,7 +381,7 @@ fn swap_tokens_for_exact_tokens_event() {
let expected_amount_out = 5_000_000;
let amount_in_should = test
- .router_contract
+ .soroswap_router_contract
.router_get_amounts_in(&expected_amount_out, &path)
.get(0)
.unwrap();
diff --git a/contracts/aggregator/src/test/phoenix_setup.rs b/contracts/aggregator/src/test/phoenix_setup.rs
new file mode 100644
index 00000000..92581d00
--- /dev/null
+++ b/contracts/aggregator/src/test/phoenix_setup.rs
@@ -0,0 +1,188 @@
+
+// For Phoenix
+mod phoenix_adapter {
+ soroban_sdk::contractimport!(
+ file =
+ "../target/wasm32-unknown-unknown/release/phoenix_adapter.optimized.wasm"
+ );
+ pub type SoroswapAggregatorAdapterForPhoenixClient<'a> = Client<'a>;
+}
+pub use phoenix_adapter::SoroswapAggregatorAdapterForPhoenixClient;
+use crate::test::install_token_wasm;
+// Adapter for phoenix
+pub fn create_phoenix_adapter<'a>(e: &Env) -> SoroswapAggregatorAdapterForPhoenixClient<'a> {
+ let adapter_address = &e.register_contract_wasm(None, phoenix_adapter::WASM);
+ let adapter = SoroswapAggregatorAdapterForPhoenixClient::new(e, adapter_address);
+ adapter
+}
+
+
+// #![cfg(test)]
+// extern crate std;
+use soroban_sdk::{
+ vec,
+ // IntoVal,
+ String,
+ Env,
+ Bytes,
+ BytesN,
+ Address,
+ testutils::{
+ arbitrary::std,
+ Address as _,
+ },
+};
+
+/* ************* PHOENIX FACTORY ************* */
+
+#[allow(clippy::too_many_arguments)]
+pub mod factory {
+ soroban_sdk::contractimport!(
+ file = "../adapters/phoenix/phoenix_contracts/phoenix_factory.wasm"
+ );
+}
+use factory::{LiquidityPoolInitInfo, StakeInitInfo, TokenInitInfo};
+
+pub fn deploy_factory_contract(e: &Env, admin: & Address) -> Address {
+ let factory_wasm = e.deployer().upload_contract_wasm(factory::WASM);
+ let salt = Bytes::new(&e.clone());
+ let salt = e.crypto().sha256(&salt);
+
+ e.deployer().with_address(admin.clone(), salt).deploy(factory_wasm)
+}
+
+pub use factory::Client as PhoenixFactory;
+
+/* ************* MULTIHOP ************* */
+#[allow(clippy::too_many_arguments)]
+pub mod multihop {
+ soroban_sdk::contractimport!(file = "../adapters/phoenix/phoenix_contracts/phoenix_multihop.wasm");
+ pub type MultihopClient<'a> = Client<'a>;
+}
+pub use multihop::MultihopClient;
+
+pub fn install_multihop_wasm(env: &Env) -> BytesN<32> {
+ soroban_sdk::contractimport!(
+ file = "../adapters/phoenix/phoenix_contracts/phoenix_multihop.wasm"
+ );
+ env.deployer().upload_contract_wasm(WASM)
+}
+pub fn deploy_multihop_contract<'a>(
+ env: &Env,
+ admin: impl Into