Skip to content

Commit

Permalink
Merge branch 'feat/tyescript-test-blend' of https://github.com/paltal…
Browse files Browse the repository at this point in the history
…abs/defindex into feat/tyescript-test-blend
  • Loading branch information
MattPoblete committed Dec 2, 2024
2 parents 140e2bb + 0e66d5e commit 535b1ac
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 80 deletions.
10 changes: 10 additions & 0 deletions apps/contracts/Cargo.lock

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

1 change: 1 addition & 0 deletions apps/contracts/strategies/blend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ crate-type = ["cdylib"]
[dependencies]
soroban-sdk = { workspace = true }
defindex-strategy-core = { workspace = true }
soroban-fixed-point-math = "1.2.0"

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
88 changes: 52 additions & 36 deletions apps/contracts/strategies/blend/src/blend_pool.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use soroban_sdk::{auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}, vec, Address, Env, IntoVal, Symbol, Vec};
use defindex_strategy_core::StrategyError;
use soroban_sdk::{auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}, panic_with_error, token::TokenClient, vec, Address, Env, IntoVal, Symbol, Vec};

use crate::storage::get_blend_pool;
use crate::storage::Config;

soroban_sdk::contractimport!(
file = "../external_wasms/blend/blend_pool.wasm"
);
file = "../external_wasms/blend/blend_pool.wasm"
);
pub type BlendPoolClient<'a> = Client<'a>;

// Define the RequestType enum with explicit u32 values
Expand All @@ -30,72 +31,87 @@ impl RequestType {
}
}

pub fn supply(e: &Env, from: &Address, underlying_asset: Address, amount: i128) -> Positions {
let blend_pool_address = get_blend_pool(e);
let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address);
pub fn supply(e: &Env, from: &Address, amount: &i128, config: &Config) -> i128 {
let pool_client = BlendPoolClient::new(e, &config.pool);

// Get deposit amount pre-supply
let pre_supply = pool_client
.get_positions(&e.current_contract_address())
.supply
.get(config.reserve_id)
.unwrap_or(0);

let requests: Vec<Request> = vec![&e, Request {
address: underlying_asset.clone(),
amount,
address: config.asset.clone(),
amount: amount.clone(),
request_type: RequestType::Supply.to_u32(),
}];

e.authorize_as_current_contract(vec![
&e,
InvokerContractAuthEntry::Contract(SubContractInvocation {
context: ContractContext {
contract: underlying_asset.clone(),
contract: config.asset.clone(),
fn_name: Symbol::new(&e, "transfer"),
args: (
e.current_contract_address(),
blend_pool_address.clone(),
config.pool.clone(),
amount.clone()).into_val(e),
},
sub_invocations: vec![&e],
}),
]);

blend_pool_client.submit(
&from,
let new_positions = pool_client.submit(
&e.current_contract_address(),
&e.current_contract_address(),
&from,
&requests
)
);

// Calculate the amount of bTokens received
let b_tokens_amount = new_positions.supply.get_unchecked(config.reserve_id) - pre_supply;
b_tokens_amount
}

pub fn withdraw(e: &Env, from: &Address, underlying_asset: Address, amount: i128) -> Positions {
let blend_pool_address = get_blend_pool(e);
let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address);
pub fn withdraw(e: &Env, from: &Address, amount: &i128, config: &Config) -> (i128, i128) {
let pool_client = BlendPoolClient::new(e, &config.pool);

let pre_supply = pool_client
.get_positions(&e.current_contract_address())
.supply
.get(config.reserve_id)
.unwrap_or_else(|| panic_with_error!(e, StrategyError::InsufficientBalance));

// Get balance pre-withdraw, as the pool can modify the withdrawal amount
let pre_withdrawal_balance = TokenClient::new(&e, &config.asset).balance(&from);

let requests: Vec<Request> = vec![&e, Request {
address: underlying_asset.clone(),
amount,
address: config.asset.clone(),
amount: amount.clone(),
request_type: RequestType::Withdraw.to_u32(),
}];

let new_positions = blend_pool_client.submit(
&from,
&from,
// Execute the withdrawal - the tokens are transferred from the pool to the vault
let new_positions = pool_client.submit(
&e.current_contract_address(),
&e.current_contract_address(),
&from,
&requests
);

new_positions
// Calculate the amount of tokens withdrawn and bTokens burnt
let post_withdrawal_balance = TokenClient::new(&e, &config.asset).balance(&from);
let real_amount = post_withdrawal_balance - pre_withdrawal_balance;

// position entry is deleted if the position is cleared
let b_tokens_amount = pre_supply - new_positions.supply.get(config.reserve_id).unwrap_or(0);
(real_amount, b_tokens_amount)
}

pub fn claim(e: &Env, from: &Address) -> i128 {
// Setting up Blend Pool client
let blend_pool_address = get_blend_pool(e);
let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address);
pub fn claim(e: &Env, from: &Address, config: &Config) -> i128 {
let pool_client = BlendPoolClient::new(e, &config.pool);

// TODO: Check reserve_token_ids and how to get the correct one
blend_pool_client.claim(from, &vec![&e, 3u32], from)
}

pub fn get_positions(e: &Env, from: &Address) -> Positions {
// Setting up Blend Pool client
let blend_pool_address = get_blend_pool(e);
let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address);

blend_pool_client.get_positions(from)
pool_client.claim(from, &vec![&e, config.reserve_id], from)
}
6 changes: 6 additions & 0 deletions apps/contracts/strategies/blend/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// 1 with 7 decimal places
pub const SCALAR_7: i128 = 1_0000000;
/// 1 with 9 decimal places
pub const SCALAR_9: i128 = 1_000_000_000;
/// The minimum amount of tokens than can be deposited or withdrawn from the vault
pub const MIN_DUST: i128 = 0_0010000;
88 changes: 63 additions & 25 deletions apps/contracts/strategies/blend/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#![no_std]
use constants::MIN_DUST;
use soroban_sdk::{
contract, contractimpl, token::TokenClient, Address, Env, IntoVal, String, Val, Vec};
contract, contractimpl, panic_with_error, token::TokenClient, Address, Env, IntoVal, String, Val, Vec};

mod blend_pool;
mod constants;
mod reserves;
mod storage;

use storage::{
extend_instance_ttl, get_reserve_id, get_underlying_asset, is_initialized, set_blend_pool, set_initialized, set_reserve_id, set_underlying_asset
};
use storage::{extend_instance_ttl, is_initialized, set_initialized, Config};

pub use defindex_strategy_core::{
DeFindexStrategyTrait,
Expand Down Expand Up @@ -46,14 +47,19 @@ impl DeFindexStrategyTrait for BlendStrategy {
return Err(StrategyError::AlreadyInitialized);
}

let blend_pool_address = init_args.get(0).ok_or(StrategyError::InvalidArgument)?.into_val(&e);
let reserve_id = init_args.get(1).ok_or(StrategyError::InvalidArgument)?.into_val(&e);
let blend_pool_address: Address = init_args.get(0).ok_or(StrategyError::InvalidArgument)?.into_val(&e);
let reserve_id: u32 = init_args.get(1).ok_or(StrategyError::InvalidArgument)?.into_val(&e);

set_initialized(&e);
set_blend_pool(&e, blend_pool_address);
set_reserve_id(&e, reserve_id);
set_underlying_asset(&e, &asset);

let config = Config {
asset: asset.clone(),
pool: blend_pool_address.clone(),
reserve_id: reserve_id.clone(),
};

storage::set_config(&e, config);

event::emit_initialize(&e, String::from_str(&e, STARETEGY_NAME), asset);
extend_instance_ttl(&e);
Ok(())
Expand All @@ -63,7 +69,7 @@ impl DeFindexStrategyTrait for BlendStrategy {
check_initialized(&e)?;
extend_instance_ttl(&e);

Ok(get_underlying_asset(&e))
Ok(storage::get_config(&e).asset)
}

fn deposit(
Expand All @@ -76,11 +82,28 @@ impl DeFindexStrategyTrait for BlendStrategy {
extend_instance_ttl(&e);
from.require_auth();

// transfer tokens from the vault to the contract
let underlying_asset = get_underlying_asset(&e);
TokenClient::new(&e, &underlying_asset).transfer(&from, &e.current_contract_address(), &amount);
// protect against rouding of reserve_vault::update_rate, as small amounts
// can cause incorrect b_rate calculations due to the pool rounding
if amount < MIN_DUST {
return Err(StrategyError::InvalidArgument); //TODO: create a new error type for this
}

// Harvest if rewards exceed threshold
// let rewards = blend_pool::claim_rewards(&e);
// if rewards > REWARD_THRESHOLD {
// blend_pool::reinvest_rewards(&e, rewards);
// }

let reserves = storage::get_strategy_reserves(&e);

blend_pool::supply(&e, &from, underlying_asset, amount);
let config = storage::get_config(&e);
// transfer tokens from the vault to the strategy contract
TokenClient::new(&e, &config.asset).transfer(&from, &e.current_contract_address(), &amount);

let b_tokens_minted = blend_pool::supply(&e, &from, &amount, &config);

// Keeping track of the total deposited amount and the total bTokens owned by the strategy depositors
reserves::deposit(&e, reserves, &from, amount, b_tokens_minted);

event::emit_deposit(&e, String::from_str(&e, STARETEGY_NAME), amount, from);
Ok(())
Expand All @@ -89,9 +112,15 @@ impl DeFindexStrategyTrait for BlendStrategy {
fn harvest(e: Env, from: Address) -> Result<(), StrategyError> {
check_initialized(&e)?;
extend_instance_ttl(&e);
from.require_auth();
from.require_auth();

let config = storage::get_config(&e);
let _harvested_blend = blend_pool::claim(&e, &from, &config);

blend_pool::claim(&e, &from);
// should swap to usdc
// should supply to the pool

// etcetc

event::emit_harvest(&e, String::from_str(&e, STARETEGY_NAME), 0i128, from);
Ok(())
Expand All @@ -106,13 +135,24 @@ impl DeFindexStrategyTrait for BlendStrategy {
check_nonnegative_amount(amount)?;
extend_instance_ttl(&e);
from.require_auth();

let underlying_asset = get_underlying_asset(&e);
blend_pool::withdraw(&e, &from, underlying_asset, amount);

// protect against rouding of reserve_vault::update_rate, as small amounts
// can cause incorrect b_rate calculations due to the pool rounding
if amount < MIN_DUST {
return Err(StrategyError::InvalidArgument) //TODO: create a new error type for this
}

let reserves = storage::get_strategy_reserves(&e);

let config = storage::get_config(&e);

let (tokens_withdrawn, b_tokens_burnt) = blend_pool::withdraw(&e, &from, &amount, &config);

let _burnt_shares = reserves::withdraw(&e, reserves, &from, tokens_withdrawn, b_tokens_burnt);

event::emit_withdraw(&e, String::from_str(&e, STARETEGY_NAME), amount, from);

Ok(amount)
Ok(tokens_withdrawn)
}

fn balance(
Expand All @@ -122,12 +162,10 @@ impl DeFindexStrategyTrait for BlendStrategy {
check_initialized(&e)?;
extend_instance_ttl(&e);

let positions = blend_pool::get_positions(&e, &from);
let reserve_id = get_reserve_id(&e);
let vault_shares = storage::get_vault_shares(&e, &from);

let supply = positions.supply.get(reserve_id).unwrap_or(0i128);
Ok(supply)
Ok(vault_shares)
}
}

mod test;
// mod test;
Loading

0 comments on commit 535b1ac

Please sign in to comment.