Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factory: initializes the multihop from the initialize method of factory and saves the multihop address in Config #158

2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to
- Total surrender refactor: replace all errors with panics ([#140])
- Pool/Pool stable: Replace `sell_a` parameter in simulate swap messages with `offer_asset` address ([#154])
- Multihop: Implement simulate swap/reverse swap queries ([#147])
- Factory: Initializes the Multihop contract upon initializing Factory ([#158])

## Bug fixes

Expand All @@ -21,6 +22,7 @@ and this project adheres to
[#144]: https://github.com/Phoenix-Protocol-Group/phoenix-contracts/pull/144
[#147]: https://github.com/Phoenix-Protocol-Group/phoenix-contracts/pull/147
[#157]: https://github.com/Phoenix-Protocol-Group/phoenix-contracts/pull/157
[#158]: https://github.com/Phoenix-Protocol-Group/phoenix-contracts/pull/158

## [0.7.0] - 2023-10-10

Expand Down
39 changes: 30 additions & 9 deletions contracts/factory/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use soroban_sdk::{
contract, contractimpl, contractmeta, log, Address, Env, IntoVal, Symbol, Val, Vec,
use crate::storage::{
get_config, is_initialized, save_config, set_initialized, Config, DataKey, LiquidityPoolInfo,
PairTupleKey,
};

use crate::storage::{is_initialized, set_initialized, LiquidityPoolInfo, PairTupleKey};
use crate::utils::deploy_multihop_contract;
use crate::{
storage::{get_admin, get_lp_vec, save_admin, save_lp_vec, save_lp_vec_with_tuple_as_key},
storage::{get_lp_vec, save_lp_vec, save_lp_vec_with_tuple_as_key},
utils::deploy_lp_contract,
};
use phoenix::utils::{LiquidityPoolInitInfo, StakeInitInfo, TokenInitInfo};
use soroban_sdk::{
contract, contractimpl, contractmeta, log, Address, BytesN, Env, IntoVal, Symbol, Val, Vec,
};

// Metadata that is added on to the WASM custom section
contractmeta!(key = "Description", val = "Phoenix Protocol Factory");
Expand All @@ -16,7 +19,7 @@ contractmeta!(key = "Description", val = "Phoenix Protocol Factory");
pub struct Factory;

pub trait FactoryTrait {
fn initialize(env: Env, admin: Address);
fn initialize(env: Env, admin: Address, multihop_wasm_hash: BytesN<32>);

fn create_liquidity_pool(env: Env, lp_init_info: LiquidityPoolInitInfo) -> Address;

Expand All @@ -29,18 +32,29 @@ pub trait FactoryTrait {
fn query_for_pool_by_token_pair(env: Env, token_a: Address, token_b: Address) -> Address;

fn get_admin(env: Env) -> Address;

fn get_config(env: Env) -> Config;
}

#[contractimpl]
impl FactoryTrait for Factory {
fn initialize(env: Env, admin: Address) {
fn initialize(env: Env, admin: Address, multihop_wasm_hash: BytesN<32>) {
if is_initialized(&env) {
panic!("Factory: Initialize: initializing contract twice is not allowed");
}

set_initialized(&env);

save_admin(&env, admin.clone());
let multihop_address =
deploy_multihop_contract(env.clone(), admin.clone(), multihop_wasm_hash);

save_config(
&env,
Config {
admin: admin.clone(),
multihop_address,
},
);

save_lp_vec(&env, Vec::new(&env));

Expand Down Expand Up @@ -144,7 +158,14 @@ impl FactoryTrait for Factory {
}

fn get_admin(env: Env) -> Address {
get_admin(&env)
get_config(&env).admin
}

fn get_config(env: Env) -> Config {
env.storage()
.persistent()
.get(&DataKey::Config)
.expect("Factory: No multihop present in storage")
}
}

Expand Down
28 changes: 17 additions & 11 deletions contracts/factory/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ use soroban_sdk::{contracttype, Address, ConversionError, Env, TryFromVal, Val,
#[derive(Clone, Copy)]
#[repr(u32)]
pub enum DataKey {
Admin = 1,
Config = 2,
LpVec = 3,
Initialized = 4,
Config = 1,
LpVec = 2,
Initialized = 3,
}

#[derive(Clone)]
Expand All @@ -24,6 +23,13 @@ impl TryFromVal<Env, DataKey> for Val {
}
}

#[contracttype]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Config {
pub admin: Address,
pub multihop_address: Address,
}

#[contracttype]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Asset {
Expand Down Expand Up @@ -53,15 +59,15 @@ pub struct LiquidityPoolInfo {
pub total_fee_bps: i64,
}

pub fn save_admin(env: &Env, address: Address) {
env.storage().instance().set(&DataKey::Admin, &address);
pub fn save_config(env: &Env, config: Config) {
env.storage().persistent().set(&DataKey::Config, &config);
}

pub fn get_admin(env: &Env) -> Address {
pub fn get_config(env: &Env) -> Config {
env.storage()
.instance()
.get(&DataKey::Admin)
.expect("Factory: Failed to get admin from storage")
.persistent()
.get(&DataKey::Config)
.expect("Config not set")
}

pub fn get_lp_vec(env: &Env) -> Vec<Address> {
Expand Down Expand Up @@ -109,7 +115,7 @@ mod tests {
fn test_get_admin_should_panic_when_no_admin_saved() {
let env = Env::default();

get_admin(&env);
get_config(&env);
}

#[test]
Expand Down
8 changes: 6 additions & 2 deletions contracts/factory/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::contract::{Factory, FactoryClient};
use soroban_sdk::{testutils::Address as _, Address, Env};

use self::setup::install_multihop_wasm;

mod config;
mod setup;

Expand All @@ -15,6 +17,8 @@ fn test_deploy_factory_twice_should_fail() {
let admin = Address::random(&env);

let multihop = FactoryClient::new(&env, &env.register_contract(None, Factory {}));
multihop.initialize(&admin);
multihop.initialize(&admin);
let multihop_wasm_hash = install_multihop_wasm(&env);

multihop.initialize(&admin, &multihop_wasm_hash);
multihop.initialize(&admin, &multihop_wasm_hash);
}
18 changes: 18 additions & 0 deletions contracts/factory/src/tests/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use phoenix::utils::{LiquidityPoolInitInfo, StakeInitInfo, TokenInitInfo};

use soroban_sdk::arbitrary::std;
use soroban_sdk::{testutils::Address as _, Address, Env};
use soroban_sdk::{Symbol, Vec};

#[test]
fn factory_successfully_inits_itself() {
Expand All @@ -17,6 +18,23 @@ fn factory_successfully_inits_itself() {
assert_eq!(factory.get_admin(), admin);
}

#[test]
fn factory_successfully_inits_multihop() {
let env = Env::default();
env.mock_all_auths();

let admin = Address::random(&env);

let factory = deploy_factory_contract(&env, Some(admin.clone()));

let multihop_address = factory.get_config().multihop_address;

let func = Symbol::new(&env, "get_admin");
let admin_in_multihop = env.invoke_contract(&multihop_address, &func, Vec::new(&env));

assert_eq!(admin, admin_in_multihop);
}
gangov marked this conversation as resolved.
Show resolved Hide resolved

#[test]
fn factory_successfully_inits_lp() {
let env = Env::default();
Expand Down
11 changes: 9 additions & 2 deletions contracts/factory/src/tests/setup.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
use crate::contract::{Factory, FactoryClient};
use soroban_sdk::testutils::Address as _;
use soroban_sdk::{Address, BytesN, Env};

#[allow(clippy::too_many_arguments)]
pub mod lp_contract {
soroban_sdk::contractimport!(
file = "../../target/wasm32-unknown-unknown/release/phoenix_pool.wasm"
);
}

pub fn install_multihop_wasm(env: &Env) -> BytesN<32> {
soroban_sdk::contractimport!(
file = "../../target/wasm32-unknown-unknown/release/phoenix_multihop.wasm"
);
env.deployer().upload_contract_wasm(WASM)
}

pub fn install_lp_contract(env: &Env) -> BytesN<32> {
env.deployer().upload_contract_wasm(lp_contract::WASM)
}
Expand All @@ -33,7 +39,8 @@ pub fn deploy_factory_contract<'a>(
) -> FactoryClient<'a> {
let admin = admin.into().unwrap_or(Address::random(env));
let factory = FactoryClient::new(env, &env.register_contract(None, Factory {}));
let multihop_wasm_hash = install_multihop_wasm(env);

factory.initialize(&admin);
factory.initialize(&admin, &multihop_wasm_hash);
factory
}
23 changes: 22 additions & 1 deletion contracts/factory/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{xdr::ToXdr, Address, Bytes, BytesN, Env};
use soroban_sdk::{xdr::ToXdr, Address, Bytes, BytesN, Env, IntoVal, Symbol, Val, Vec};

pub fn deploy_lp_contract(
env: &Env,
Expand All @@ -21,3 +21,24 @@ pub fn deploy_lp_contract(
.with_current_contract(salt)
.deploy(lp_wasm_hash)
}

pub fn deploy_multihop_contract(
env: Env,
admin: Address,
multihop_wasm_hash: BytesN<32>,
) -> Address {
let mut salt = Bytes::new(&env);
salt.append(&admin.clone().to_xdr(&env));
let salt = env.crypto().sha256(&salt);

let multihop_address = env
.deployer()
.with_current_contract(salt)
.deploy(multihop_wasm_hash);

let init_fn = Symbol::new(&env, "initialize");
let init_args: Vec<Val> = (admin, env.current_contract_address()).into_val(&env);
env.invoke_contract::<Val>(&multihop_address, &init_fn, init_args);

multihop_address
}
15 changes: 13 additions & 2 deletions contracts/multihop/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use soroban_sdk::{contract, contractimpl, contractmeta, Address, Env, Vec};

use crate::storage::{
get_factory, is_initialized, save_admin, save_factory, set_initialized,
get_factory, is_initialized, save_factory, set_initialized, DataKey,
SimulateReverseSwapResponse, SimulateSwapResponse, Swap,
};
use crate::{factory_contract, lp_contract};
Expand All @@ -27,6 +27,8 @@ pub trait MultihopTrait {
operations: Vec<Swap>,
amount: i128,
) -> SimulateReverseSwapResponse;

fn get_admin(env: Env) -> Address;
}

#[contractimpl]
Expand All @@ -38,7 +40,9 @@ impl MultihopTrait for Multihop {

set_initialized(&env);

save_admin(&env, &admin);
env.storage()
.persistent()
.set(&DataKey::Admin, &admin.clone());

save_factory(&env, factory);

Expand Down Expand Up @@ -139,4 +143,11 @@ impl MultihopTrait for Multihop {

simulate_swap_response
}

fn get_admin(env: Env) -> Address {
env.storage()
.persistent()
.get(&DataKey::Admin)
.expect("Multihop: No admin found")
}
}
8 changes: 0 additions & 8 deletions contracts/multihop/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ pub struct PoolResponse {
pub asset_lp_share: Asset,
}

pub fn save_admin(env: &Env, admin: &Address) {
env.storage().instance().set(&DataKey::Admin, &admin);
}

pub fn _get_admin(env: &Env) -> Address {
env.storage().instance().get(&DataKey::Admin).unwrap()
}

pub fn save_factory(env: &Env, factory: Address) {
env.storage().instance().set(&DataKey::FactoryKey, &factory);
}
Expand Down
16 changes: 8 additions & 8 deletions contracts/multihop/src/tests/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,12 @@ pub fn install_stake_wasm(env: &Env) -> BytesN<32> {
env.deployer().upload_contract_wasm(WASM)
}

// pub fn deploy_liquidity_pool(e: &Env, admin: Address) -> Address {
// let factory_wasm = e.deployer().upload_contract_wasm(factory::WASM);
// let salt = Bytes::new(e);
// let salt = e.crypto().sha256(&salt);
//
// e.deployer().with_address(admin, salt).deploy(factory_wasm)
// }
pub fn install_multihop_wasm(env: &Env) -> BytesN<32> {
soroban_sdk::contractimport!(
file = "../../target/wasm32-unknown-unknown/release/phoenix_multihop.wasm"
);
env.deployer().upload_contract_wasm(WASM)
}

pub fn deploy_factory_contract(e: &Env, admin: Address) -> Address {
let factory_wasm = e.deployer().upload_contract_wasm(factory::WASM);
Expand Down Expand Up @@ -88,8 +87,9 @@ pub fn deploy_and_mint_tokens<'a>(
pub fn deploy_and_initialize_factory(env: &Env, admin: Address) -> factory::Client {
let factory_addr = deploy_factory_contract(env, admin.clone());
let factory_client = factory::Client::new(env, &factory_addr);
let multihop_wasm_hash = install_multihop_wasm(env);

factory_client.initialize(&admin.clone());
factory_client.initialize(&admin.clone(), &multihop_wasm_hash);
factory_client
}

Expand Down
1 change: 1 addition & 0 deletions contracts/pool_stable/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ test: build # because of token dependency
cargo test

build:
$(MAKE) -C ../stake build || break;
$(MAKE) -C ../token build || break;
cargo build --target wasm32-unknown-unknown --release

Expand Down
Loading