Skip to content

Commit

Permalink
Merge pull request #188 from blend-capital/remove-donate-usdc
Browse files Browse the repository at this point in the history
Refactored interest auction to use backstop token donations
  • Loading branch information
mootz12 authored Jan 22, 2024
2 parents 25bf8a9 + da49e30 commit 4035456
Show file tree
Hide file tree
Showing 14 changed files with 247 additions and 402 deletions.
212 changes: 0 additions & 212 deletions backstop/src/backstop/fund_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,46 +38,6 @@ pub fn execute_donate(e: &Env, from: &Address, pool_address: &Address, amount: i
storage::set_pool_balance(e, pool_address, &pool_balance);
}

/// Perform a donation of USDC to a pool's backstop
pub fn execute_donate_usdc(e: &Env, from: &Address, pool_address: &Address, amount: i128) {
require_nonnegative(e, amount);
if from == pool_address || from == &e.current_contract_address() {
panic_with_error!(e, &BackstopError::BadRequest)
}

let mut pool_usdc = storage::get_pool_usdc(e, pool_address);
require_is_from_pool_factory(e, pool_address, pool_usdc);

let usdc_token = TokenClient::new(e, &storage::get_usdc_token(e));
usdc_token.transfer(from, &e.current_contract_address(), &amount);

pool_usdc += amount;
storage::set_pool_usdc(e, pool_address, &pool_usdc);
}

/// Perform a mint of backstop LP tokens with USDC and deposit the LP tokens to the pool
pub fn execute_gulp_usdc(e: &Env, pool_address: &Address) {
let pool_usdc = storage::get_pool_usdc(e, pool_address);
if pool_usdc != 0 {
// mint LP tokens with USDC
let backstop_token = storage::get_backstop_token(e);
let usdc_token = storage::get_usdc_token(e);
let lp_tokens_minted = CometClient::new(e, &backstop_token)
.dep_tokn_amt_in_get_lp_tokns_out(
&usdc_token,
&pool_usdc,
&0,
&e.current_contract_address(),
);

// attribute shares to the pool's backstop
let mut pool_balance = storage::get_pool_balance(e, pool_address);
pool_balance.deposit(lp_tokens_minted, 0);
storage::set_pool_balance(e, pool_address, &pool_balance);
storage::set_pool_usdc(e, pool_address, &0);
}
}

/// Perform an update to the Comet LP token underlying value
pub fn execute_update_comet_token_value(
e: &Env,
Expand Down Expand Up @@ -358,178 +318,6 @@ mod tests {
});
}

#[test]
fn test_execute_donate_usdc() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);
let frodo = Address::generate(&e);

let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);
usdc_token_client.mint(&frodo, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_id, || {
execute_donate_usdc(&e, &samwise, &pool_0_id, 30_0000000);
let new_pool_usdc = storage::get_pool_usdc(&e, &pool_0_id);
assert_eq!(new_pool_usdc, 30_0000000);
assert_eq!(usdc_token_client.balance(&samwise), 70_0000000);
assert_eq!(usdc_token_client.balance(&backstop_id), 30_0000000);

execute_donate_usdc(&e, &frodo, &pool_0_id, 10_0000000);
let new_pool_usdc = storage::get_pool_usdc(&e, &pool_0_id);
assert_eq!(new_pool_usdc, 40_0000000);
assert_eq!(usdc_token_client.balance(&frodo), 90_0000000);
assert_eq!(usdc_token_client.balance(&backstop_id), 40_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #8)")]
fn test_execute_donate_usdc_negative_amount() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_id, || {
execute_donate_usdc(&e, &samwise, &pool_0_id, -30_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1000)")]
fn test_execute_donate_usdc_from_is_to() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_id, || {
execute_donate_usdc(&e, &pool_0_id, &pool_0_id, 10_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1000)")]
fn test_execute_donate_usdc_from_is_self() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_id, || {
execute_donate_usdc(&e, &backstop_id, &pool_0_id, 10_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1004)")]
fn test_execute_donate_usdc_not_pool() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);

create_mock_pool_factory(&e, &backstop_id);

e.as_contract(&backstop_id, || {
execute_donate_usdc(&e, &samwise, &pool_0_id, 30_0000000);
});
}

#[test]
fn test_execute_gulp_usdc() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (usdc_token, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);

let (blnd_token, blnd_token_client) = create_blnd_token(&e, &backstop_id, &bombadil);
blnd_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

let (comet_id, comet_client) =
create_comet_lp_pool(&e, &bombadil, &blnd_token, &usdc_token);

// initialize pool 0 with funds and a donation
e.as_contract(&backstop_id, || {
storage::set_backstop_token(&e, &comet_id);
execute_deposit(&e, &bombadil, &pool_0_id, 10_0000000);
execute_donate_usdc(&e, &samwise, &pool_0_id, 5_0000000);
usdc_token_client.approve(&e.current_contract_address(), &comet_id, &i128::MAX, &500);
});

e.as_contract(&backstop_id, || {
execute_gulp_usdc(&e, &pool_0_id);

let new_pool_usdc = storage::get_pool_usdc(&e, &pool_0_id);
assert_eq!(new_pool_usdc, 0);
assert_eq!(usdc_token_client.balance(&backstop_id), 0);

let new_pool_balance = storage::get_pool_balance(&e, &pool_0_id);
assert_eq!(new_pool_balance.shares, 10_0000000);
assert_eq!(new_pool_balance.tokens, 13_9904000);

let comet_balance = comet_client.balance(&backstop_id);
assert_eq!(comet_balance, 13_9904000);
});
}

#[test]
fn test_execute_update_comet_token_value() {
let e = Env::default();
Expand Down
5 changes: 1 addition & 4 deletions backstop/src/backstop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ mod deposit;
pub use deposit::execute_deposit;

mod fund_management;
pub use fund_management::{
execute_donate, execute_donate_usdc, execute_draw, execute_gulp_usdc,
execute_update_comet_token_value,
};
pub use fund_management::{execute_donate, execute_draw, execute_update_comet_token_value};

mod withdrawal;
pub use withdrawal::{execute_dequeue_withdrawal, execute_queue_withdrawal, execute_withdraw};
Expand Down
39 changes: 0 additions & 39 deletions backstop/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,28 +160,6 @@ pub trait Backstop {
/// If the `pool_address` is not valid
fn donate(e: Env, from: Address, pool_address: Address, amount: i128);

/// Sends USDC from "from" to a pools backstop to be queued for donation
///
/// NOTE: This is not a deposit, and "from" will permanently lose access to the funds
///
/// ### Arguments
/// * `from` - tge
/// * `pool_address` - The address of the pool
/// * `amount` - The amount of BLND to add
///
/// ### Errors
/// If the `pool_address` is not valid
fn donate_usdc(e: Env, from: Address, pool_address: Address, amount: i128);

/// Consume donated USDC for a pool and mint LP tokens into the pool's backstop
///
/// ### Arguments
/// * `pool_address` - The address of the pool
///
/// ### Errors
/// If the `pool_address` is not valid
fn gulp_usdc(e: Env, pool_address: Address);

/// Updates the underlying value of 1 backstop token
///
/// ### Returns
Expand Down Expand Up @@ -352,23 +330,6 @@ impl Backstop for BackstopContract {
.publish((Symbol::new(&e, "donate"), pool_address, from), amount);
}

fn donate_usdc(e: Env, from: Address, pool_address: Address, amount: i128) {
storage::extend_instance(&e);
from.require_auth();

backstop::execute_donate_usdc(&e, &from, &pool_address, amount);
e.events()
.publish((Symbol::new(&e, "donate_usdc"), pool_address, from), amount);
}

fn gulp_usdc(e: Env, pool_address: Address) {
storage::extend_instance(&e);

backstop::execute_gulp_usdc(&e, &pool_address);
e.events()
.publish((Symbol::new(&e, "gulp_usdc"), pool_address), ());
}

fn update_tkn_val(e: Env) -> (i128, i128) {
storage::extend_instance(&e);

Expand Down
5 changes: 3 additions & 2 deletions backstop/src/emissions/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ pub fn gulp_emissions(e: &Env) -> i128 {
.fixed_div_floor(total_non_queued_tokens, SCALAR_7)
.unwrap_optimized();

// store pool EPS and distribute pool's emissions via allowances to pool
// store new emissions for pool
let new_pool_emissions = share
.fixed_mul_floor(total_pool_emissions, SCALAR_7)
.unwrap_optimized();
let current_emissions = storage::get_pool_emissions(e, &rz_pool);
storage::set_pool_emissions(e, &rz_pool, current_emissions + new_pool_emissions);

// distribute backstop depositor emissions
// distribute backstop depositor emissions and store backstop EPS
let new_pool_backstop_tokens = share
.fixed_mul_floor(total_backstop_emissions, SCALAR_7)
.unwrap_optimized();
Expand All @@ -128,6 +128,7 @@ pub fn gulp_pool_emissions(e: &Env, pool_id: &Address) -> i128 {
panic_with_error!(e, BackstopError::BadRequest);
}

// distribute pool emissions via allowance to pools
let blnd_token_client = TokenClient::new(e, &storage::get_blnd_token(e));
let current_allowance = blnd_token_client.allowance(&e.current_contract_address(), pool_id);
let new_tokens = current_allowance + pool_emissions;
Expand Down
24 changes: 0 additions & 24 deletions backstop/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,30 +278,6 @@ pub fn set_pool_balance(e: &Env, pool: &Address, balance: &PoolBalance) {
.extend_ttl(&key, LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED);
}

/// Fetch the balances for a given pool
///
/// ### Arguments
/// * `pool` - The pool the deposit is associated with
pub fn get_pool_usdc(e: &Env, pool: &Address) -> i128 {
let key = BackstopDataKey::PoolUSDC(pool.clone());
get_persistent_default(e, &key, 0i128, LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED)
}

/// Set the balances for a pool
///
/// ### Arguments
/// * `pool` - The pool the deposit is associated with
/// * `balance` - The pool balances
pub fn set_pool_usdc(e: &Env, pool: &Address, balance: &i128) {
let key = BackstopDataKey::PoolUSDC(pool.clone());
e.storage()
.persistent()
.set::<BackstopDataKey, i128>(&key, balance);
e.storage()
.persistent()
.extend_ttl(&key, LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED);
}

/********** Distribution / Reward Zone **********/

/// Get the timestamp of when the next emission cycle begins
Expand Down
Loading

0 comments on commit 4035456

Please sign in to comment.