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

Feat/blend backstop lp #90

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "protocols/phoenix-contracts"]
path = protocols/phoenix-contracts
url = https://github.com/Phoenix-Protocol-Group/phoenix-contracts/
[submodule "protocols/CometDEX"]
path = protocols/CometDEX
url = https://github.com/mootz12/comet-contracts-v1/
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ The Soroswap Aggregator Contract currently aggregates different Soroban based AM

Check the documentation in https://docs.soroswap.finance/ and the [Security Audit Report](./audits/2024-08-31_Soroswap_Aggregator_Audit_by_RuntimeVerification.pdf) and the [Security Audit Findings Summary](audits/2024-08-31_Soroswap_Aggregator_Audit_Summary_by_RuntimeVerification.pdf) written by [Runtime Verification](https://runtimeverification.com).


For Deployed address check the [`./public/mainnet.json`](./public/mainnet.json)


# Setup and Deployment

**For standalone development read #Development section**
Expand Down
8 changes: 8 additions & 0 deletions contracts/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions contracts/adapters/comet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "comet-adapter"
version = "0.1.0"
edition = { workspace = true }
description = "Comet-Adapter is a smart contract on the Soroban platform, tailored for use with the Soroswap-Aggregator. It facilitates efficient transaction routing through the Comet protocol."
homepage = { workspace = true }
repository = { workspace = true }
authors = ["rahimklaber <[email protected]>"]
readme = "README.md"
keywords = ["no_std", "wasm", "soroswap", "amm", "soroban"]
publish = true

[lib]
crate-type = ["cdylib"]

[dependencies]
soroban-sdk = { workspace = true }
adapter-interface = { workspace = true }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
17 changes: 17 additions & 0 deletions contracts/adapters/comet/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
default: build

all: test

test: build
cargo test

build:
cargo build --target wasm32-unknown-unknown --release
soroban contract optimize --wasm ../../target/wasm32-unknown-unknown/release/comet_adapter.wasm
@rm ../../target/wasm32-unknown-unknown/release/comet_adapter.wasm

fmt:
cargo fmt --all --check

clean:
cargo clean
Binary file not shown.
Binary file not shown.
47 changes: 47 additions & 0 deletions contracts/adapters/comet/src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//! Definition of the Events used in the contract
use soroban_sdk::{contracttype, symbol_short, Env, Address, Vec, String};

// INITIALIZED
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InitializedEvent {
pub state: bool,
pub protocol_id: String,
pub protocol_address: Address
}

pub(crate) fn initialized(e: &Env, state: bool, protocol_id: String, protocol_address: Address) {

let event: InitializedEvent = InitializedEvent {
state: state,
protocol_id,
protocol_address,
};
e.events().publish(("SoroswapAggregatorAdapter", symbol_short!("init")), event);
}

// SWAP EVENT
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SwapEvent {
pub amount_in: i128,
pub path: Vec<Address>,
pub to: Address
}

pub(crate) fn swap(
e: &Env,
amount_in: i128,
path: Vec<Address>,
to: Address
) {
let event = SwapEvent {
amount_in,
path,
to,
};

e.events().publish(("SoroswapAggregatorAdapter", symbol_short!("swap")), event);
}

// TODO IMPROVE EVENTS
123 changes: 123 additions & 0 deletions contracts/adapters/comet/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#![no_std]
use soroban_sdk::{contract, contractimpl, Address, Env, String, Vec};

mod event;
mod storage;
mod protocol_interface;
mod test;

use storage::{
extend_instance_ttl,
set_initialized,
is_initialized,
set_protocol_id,
get_protocol_id,
set_protocol_address,
get_protocol_address,
};
use adapter_interface::{AdapterTrait, AdapterError};
use protocol_interface::{protocol_swap_exact_tokens_for_tokens,
protocol_swap_tokens_for_exact_tokens};

fn check_initialized(e: &Env) -> Result<(), AdapterError> {
if is_initialized(e) {
Ok(())
} else {
Err(AdapterError::NotInitialized)
}
}

fn check_deadline(e: &Env, deadline: u64) -> Result<(), AdapterError> {
if e.ledger().timestamp() >= deadline{
Err(AdapterError::DeadlineExpired)
}else{
Ok(())
}
}

#[contract]
struct CometAggregatorAdapter;

#[contractimpl]
impl AdapterTrait for CometAggregatorAdapter {
fn initialize(
e: Env,
protocol_id: String,
protocol_address: Address,
) -> Result<(), AdapterError> {
if check_initialized(&e).is_ok() {
return Err(AdapterError::AlreadyInitialized);
}

set_protocol_id(&e, protocol_id.clone());
set_protocol_address(&e, protocol_address.clone());

set_initialized(&e);
event::initialized(&e, true, protocol_id, protocol_address);
extend_instance_ttl(&e);
Ok(())
}

fn swap_exact_tokens_for_tokens(
e: Env,
amount_in: i128,
amount_out_min: i128,
path: Vec<Address>,
to: Address,
deadline: u64,
) -> Result<Vec<i128>, AdapterError> {
check_initialized(&e)?;
extend_instance_ttl(&e);
check_deadline(&e, deadline)?;
to.require_auth();

let swap_result = protocol_swap_exact_tokens_for_tokens(
&e,
&amount_in,
&amount_out_min,
&path,
&to,
)?;

event::swap(&e, amount_in, path, to);
Ok(swap_result)
}

fn swap_tokens_for_exact_tokens(
e: Env,
amount_out: i128,
amount_in_max: i128,
path: Vec<Address>,
to: Address,
deadline: u64,
) -> Result<Vec<i128>, AdapterError> {
check_initialized(&e)?;
extend_instance_ttl(&e);
check_deadline(&e, deadline)?;
to.require_auth();

let swap_result = protocol_swap_tokens_for_exact_tokens(
&e,
&amount_out,
&amount_in_max,
&path,
&to,
)?;

event::swap(&e, amount_in_max, path, to);
Ok(swap_result)
}

/* *** Read only functions: *** */
fn get_protocol_id(e: &Env) -> Result<String, AdapterError> {
check_initialized(&e)?;
extend_instance_ttl(&e);
Ok(get_protocol_id(e)?)
}

fn get_protocol_address(e: &Env) -> Result<Address, AdapterError> {
check_initialized(&e)?;
extend_instance_ttl(&e);
Ok(get_protocol_address(e)?)
}
}
54 changes: 54 additions & 0 deletions contracts/adapters/comet/src/protocol_interface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use soroban_sdk::{vec, Address, Env, Vec};
use crate::storage::get_protocol_address;
use adapter_interface::AdapterError;

soroban_sdk::contractimport!(
file = "./comet_contracts/comet_pool.wasm"
);
pub type CometPoolClient<'a> = Client<'a>;

pub fn protocol_swap_exact_tokens_for_tokens(
e: &Env,
amount_in: &i128,
amount_out_min: &i128,
path: &Vec<Address>,
to: &Address,
) -> Result<Vec<i128>, AdapterError> {

let comet_pool_address = get_protocol_address(&e)?;
let comet_client = CometPoolClient::new(&e, &comet_pool_address);

let (amount_out, _) = comet_client.swap_exact_amount_in(
&path.get(0).unwrap(),
amount_in,
&path.get(1).unwrap(),
amount_out_min,
&i128::MAX,
to
);

Ok(vec![e, *amount_in, amount_out])
}

pub fn protocol_swap_tokens_for_exact_tokens(
e: &Env,
amount_out: &i128,
amount_in_max: &i128,
path: &Vec<Address>,
to: &Address,
) -> Result<Vec<i128>, AdapterError> {

let comet_pool_address = get_protocol_address(&e)?;
let comet_client = CometPoolClient::new(&e, &comet_pool_address);

let (amount_in, _) = comet_client.swap_exact_amount_out(
&path.get(0).unwrap(),
amount_in_max,
&path.get(1).unwrap(),
amount_out,
&i128::MAX,
to
);

Ok(vec![e, amount_in, *amount_out])
}
51 changes: 51 additions & 0 deletions contracts/adapters/comet/src/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use soroban_sdk::{contracttype, Env, Address, String};
use adapter_interface::AdapterError;

#[derive(Clone)]
#[contracttype]

enum DataKey {
Initialized,
ProtocolId,
ProtocolAddress,
}

const DAY_IN_LEDGERS: u32 = 17280;
const INSTANCE_BUMP_AMOUNT: u32 = 60 * DAY_IN_LEDGERS;
const INSTANCE_LIFETIME_THRESHOLD: u32 = INSTANCE_BUMP_AMOUNT - DAY_IN_LEDGERS;

pub fn extend_instance_ttl(e: &Env) {
e.storage()
.instance()
.extend_ttl(INSTANCE_LIFETIME_THRESHOLD, INSTANCE_BUMP_AMOUNT);
}

/* INITIALIZED */
pub fn set_initialized(e: &Env) {
e.storage().instance().set(&DataKey::Initialized, &true);
}

pub fn is_initialized(e: &Env) -> bool {
e.storage().instance().has(&DataKey::Initialized)
}


/* PROTOCOL ID - STRING */
pub fn set_protocol_id(e: &Env, protocol_id: String) {
e.storage().instance().set(&DataKey::ProtocolId, &protocol_id);
}

pub fn get_protocol_id(e: &Env) -> Result<String, AdapterError> {
e.storage().instance().get(&DataKey::ProtocolId).ok_or(AdapterError::NotInitialized)
}


/* PROTOCOL ADDRESS */
pub fn set_protocol_address(e: &Env, address: Address) {
e.storage().instance().set(&DataKey::ProtocolAddress, &address);
}

pub fn get_protocol_address(e: &Env) -> Result<Address, AdapterError> {
e.storage().instance().get(&DataKey::ProtocolAddress).ok_or(AdapterError::NotInitialized)
}

Loading