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

Issue 141 claim to backstop #142

Merged
merged 5 commits into from
Nov 10, 2023
Merged
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
180 changes: 155 additions & 25 deletions backstop/src/emissions/claim.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{errors::BackstopError, storage};
use sep_41_token::TokenClient;
use soroban_sdk::{panic_with_error, Address, Env, Vec};
use crate::{dependencies::CometClient, errors::BackstopError, storage};
use fixed_point_math::FixedPoint;
use soroban_sdk::{
auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation},
panic_with_error, vec, Address, Env, IntoVal, Map, Symbol, Val, Vec,
};

use super::update_emissions;

Expand All @@ -13,26 +16,74 @@ pub fn execute_claim(e: &Env, from: &Address, pool_addresses: &Vec<Address>, to:
}

let mut claimed: i128 = 0;
let mut claims: Map<Address, i128> = Map::new(e);
for pool_id in pool_addresses.iter() {
let pool_balance = storage::get_pool_balance(e, &pool_id);
let user_balance = storage::get_user_balance(e, &pool_id, from);
claimed += update_emissions(e, &pool_id, &pool_balance, from, &user_balance, true);
let claim_amt = update_emissions(e, &pool_id, &pool_balance, from, &user_balance, true);

claimed += claim_amt;
claims.set(pool_id, claim_amt);
}

if claimed > 0 {
let blnd_token = TokenClient::new(e, &storage::get_blnd_token(e));
blnd_token.transfer(&e.current_contract_address(), to, &claimed);
let blnd_id = storage::get_blnd_token(e);
let lp_id = storage::get_backstop_token(e);
let args: Vec<Val> = vec![
e,
(&e.current_contract_address()).into_val(e),
(&lp_id).into_val(e),
(&claimed).into_val(e),
];
e.authorize_as_current_contract(vec![
&e,
InvokerContractAuthEntry::Contract(SubContractInvocation {
context: ContractContext {
contract: blnd_id.clone(),
fn_name: Symbol::new(e, "transfer"),
args: args.clone(),
},
sub_invocations: vec![e],
}),
]);
let lp_tokens_out = CometClient::new(e, &lp_id).dep_tokn_amt_in_get_lp_tokns_out(
&blnd_id,
&claimed,
&0,
&e.current_contract_address(),
);
for pool_id in pool_addresses.iter() {
let claim_amount = claims.get(pool_id.clone()).unwrap();
let deposit_amount = lp_tokens_out
.fixed_mul_floor(claim_amount, claimed)
.unwrap();
let mut pool_balance = storage::get_pool_balance(e, &pool_id);
let mut user_balance = storage::get_user_balance(e, &pool_id, to);

// Deposit LP tokens into pool backstop
let to_mint = pool_balance.convert_to_shares(deposit_amount);
pool_balance.deposit(deposit_amount, to_mint);
user_balance.add_shares(to_mint);

storage::set_pool_balance(e, &pool_id, &pool_balance);
storage::set_user_balance(e, &pool_id, to, &user_balance);
e.events().publish(
(Symbol::new(&e, "deposit"), pool_id, to),
(deposit_amount, to_mint),
);
Comment on lines +60 to +73
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a massive fan of this logic being duplicated, but there doesn't seem to be that easy of a way around it without a bunch of refactoring to make things consistent

}
}

claimed
}

#[cfg(test)]
mod tests {

use crate::{
backstop::{PoolBalance, UserBalance},
storage::{BackstopEmissionConfig, BackstopEmissionsData, UserEmissionData},
testutils::{create_backstop, create_blnd_token},
testutils::{create_backstop, create_blnd_token, create_comet_lp_pool, create_usdc_token},
};

use super::*;
Expand All @@ -59,6 +110,7 @@ mod tests {
min_persistent_entry_expiration: 10,
max_entry_expiration: 2000000,
});
e.budget().reset_unlimited();

let backstop_address = create_backstop(&e);
let pool_1_id = Address::random(&e);
Expand All @@ -67,9 +119,9 @@ mod tests {
let samwise = Address::random(&e);
let frodo = Address::random(&e);

let (_, blnd_token_client) = create_blnd_token(&e, &backstop_address, &bombadil);
let (blnd_address, blnd_token_client) = create_blnd_token(&e, &backstop_address, &bombadil);
let (usdc_address, _) = create_usdc_token(&e, &backstop_address, &bombadil);
blnd_token_client.mint(&backstop_address, &100_0000000);

let backstop_1_emissions_config = BackstopEmissionConfig {
expiration: 1500000000 + 7 * 24 * 60 * 60,
eps: 0_1000000,
Expand All @@ -95,13 +147,17 @@ mod tests {
index: 0,
accrued: 0,
};
let (lp_address, lp_client) =
create_comet_lp_pool(&e, &bombadil, &blnd_address, &usdc_address);
e.as_contract(&backstop_address, || {
storage::set_backstop_emis_config(&e, &pool_1_id, &backstop_1_emissions_config);
storage::set_backstop_emis_data(&e, &pool_1_id, &backstop_1_emissions_data);
storage::set_user_emis_data(&e, &pool_1_id, &samwise, &user_1_emissions_data);
storage::set_backstop_emis_config(&e, &pool_2_id, &backstop_2_emissions_config);
storage::set_backstop_emis_data(&e, &pool_2_id, &backstop_2_emissions_data);
storage::set_user_emis_data(&e, &pool_2_id, &samwise, &user_2_emissions_data);
storage::set_backstop_token(&e, &lp_address);
storage::set_blnd_token(&e, &blnd_address);

storage::set_pool_balance(
&e,
Expand Down Expand Up @@ -139,19 +195,44 @@ mod tests {
q4w: vec![&e],
},
);

let backstop_lp_balance = lp_client.balance(&backstop_address);
let pre_frodo_balance_1 = storage::get_user_balance(&e, &pool_1_id, &frodo).shares;
let pre_frodo_balance_2 = storage::get_user_balance(&e, &pool_2_id, &frodo).shares;
let pre_pool_tokens_1 = storage::get_pool_balance(&e, &pool_1_id).tokens;
let pre_pool_tokens_2 = storage::get_pool_balance(&e, &pool_2_id).tokens;
let pre_pool_shares_1 = storage::get_pool_balance(&e, &pool_1_id).shares;
let pre_pool_shares_2 = storage::get_pool_balance(&e, &pool_2_id).shares;
e.budget().reset_default();
let result = execute_claim(
&e,
&samwise,
&vec![&e, pool_1_id.clone(), pool_2_id.clone()],
&frodo,
);
assert_eq!(result, 75_3145677 + 6_2904190);
assert_eq!(blnd_token_client.balance(&frodo), 75_3145677 + 6_2904190);
assert_eq!(
lp_client.balance(&backstop_address),
backstop_lp_balance + 6_5244800
);
assert_eq!(
blnd_token_client.balance(&backstop_address),
100_0000000 - (75_3145677 + 6_2904190)
);
let sam_balance_1 = storage::get_user_balance(&e, &pool_1_id, &samwise);
assert_eq!(sam_balance_1.shares, 9_0000000);
let frodo_balance_1 = storage::get_user_balance(&e, &pool_1_id, &frodo);
assert_eq!(frodo_balance_1.shares, pre_frodo_balance_1 + 4_5761820);
let sam_balance_2 = storage::get_user_balance(&e, &pool_2_id, &samwise);
assert_eq!(sam_balance_2.shares, 7_5000000);
let frodo_balance_2 = storage::get_user_balance(&e, &pool_2_id, &frodo);
assert_eq!(frodo_balance_2.shares, pre_frodo_balance_2 + 0_3947102);

let pool_balance_1 = storage::get_pool_balance(&e, &pool_1_id);
assert_eq!(pool_balance_1.tokens, pre_pool_tokens_1 + 6_1015761);
assert_eq!(pool_balance_1.shares, pre_pool_shares_1 + 4_5761820);
let pool_balance_2 = storage::get_pool_balance(&e, &pool_2_id);
assert_eq!(pool_balance_2.tokens, pre_pool_tokens_2 + 0_4229038);
assert_eq!(pool_balance_2.shares, pre_pool_shares_2 + 0_3947102);

let new_backstop_1_data =
storage::get_backstop_emis_data(&e, &pool_1_id).unwrap_optimized();
Expand Down Expand Up @@ -198,7 +279,8 @@ mod tests {
let samwise = Address::random(&e);
let frodo = Address::random(&e);

let (_, blnd_token_client) = create_blnd_token(&e, &backstop_address, &bombadil);
let (blnd_address, blnd_token_client) = create_blnd_token(&e, &backstop_address, &bombadil);
let (usdc_address, _) = create_usdc_token(&e, &backstop_address, &bombadil);
blnd_token_client.mint(&backstop_address, &200_0000000);

let backstop_1_emissions_config = BackstopEmissionConfig {
Expand Down Expand Up @@ -226,14 +308,17 @@ mod tests {
index: 0,
accrued: 0,
};
let (lp_address, lp_client) =
create_comet_lp_pool(&e, &bombadil, &blnd_address, &usdc_address);
e.as_contract(&backstop_address, || {
storage::set_backstop_emis_config(&e, &pool_1_id, &backstop_1_emissions_config);
storage::set_backstop_emis_data(&e, &pool_1_id, &backstop_1_emissions_data);
storage::set_user_emis_data(&e, &pool_1_id, &samwise, &user_1_emissions_data);
storage::set_backstop_emis_config(&e, &pool_2_id, &backstop_2_emissions_config);
storage::set_backstop_emis_data(&e, &pool_2_id, &backstop_2_emissions_data);
storage::set_user_emis_data(&e, &pool_2_id, &samwise, &user_2_emissions_data);

storage::set_backstop_token(&e, &lp_address);
storage::set_blnd_token(&e, &blnd_address);
storage::set_pool_balance(
&e,
&pool_1_id,
Expand Down Expand Up @@ -270,19 +355,43 @@ mod tests {
q4w: vec![&e],
},
);

let backstop_lp_balance = lp_client.balance(&backstop_address);
let pre_frodo_balance_1 = storage::get_user_balance(&e, &pool_1_id, &frodo).shares;
let pre_frodo_balance_2 = storage::get_user_balance(&e, &pool_2_id, &frodo).shares;
let pre_pool_tokens_1 = storage::get_pool_balance(&e, &pool_1_id).tokens;
let pre_pool_tokens_2 = storage::get_pool_balance(&e, &pool_2_id).tokens;
let pre_pool_shares_1 = storage::get_pool_balance(&e, &pool_1_id).shares;
let pre_pool_shares_2 = storage::get_pool_balance(&e, &pool_2_id).shares;
let result = execute_claim(
&e,
&samwise,
&vec![&e, pool_1_id.clone(), pool_2_id.clone()],
&frodo,
);
assert_eq!(result, 75_3145677 + 6_2904190);
assert_eq!(blnd_token_client.balance(&frodo), 75_3145677 + 6_2904190);
assert_eq!(
lp_client.balance(&backstop_address),
backstop_lp_balance + 6_5244800
);
assert_eq!(
blnd_token_client.balance(&backstop_address),
200_0000000 - (75_3145677 + 6_2904190)
);
let sam_balance_1 = storage::get_user_balance(&e, &pool_1_id, &samwise);
assert_eq!(sam_balance_1.shares, 9_0000000);
let frodo_balance_1 = storage::get_user_balance(&e, &pool_1_id, &frodo);
assert_eq!(frodo_balance_1.shares, pre_frodo_balance_1 + 4_5761820);
let sam_balance_2 = storage::get_user_balance(&e, &pool_2_id, &samwise);
assert_eq!(sam_balance_2.shares, 7_5000000);
let frodo_balance_2 = storage::get_user_balance(&e, &pool_2_id, &frodo);
assert_eq!(frodo_balance_2.shares, pre_frodo_balance_2 + 0_3947102);

let pool_balance_1 = storage::get_pool_balance(&e, &pool_1_id);
assert_eq!(pool_balance_1.tokens, pre_pool_tokens_1 + 6_1015761);
assert_eq!(pool_balance_1.shares, pre_pool_shares_1 + 4_5761820);
let pool_balance_2 = storage::get_pool_balance(&e, &pool_2_id);
assert_eq!(pool_balance_2.tokens, pre_pool_tokens_2 + 0_4229038);
assert_eq!(pool_balance_2.shares, pre_pool_shares_2 + 0_3947102);

let new_backstop_1_data =
storage::get_backstop_emis_data(&e, &pool_1_id).unwrap_optimized();
Expand Down Expand Up @@ -313,39 +422,60 @@ mod tests {
min_persistent_entry_expiration: 10,
max_entry_expiration: 2000000,
});
let backstop_lp_balance = backstop_lp_balance + 6_5244800;
let pre_frodo_balance_1 = storage::get_user_balance(&e, &pool_1_id, &frodo).shares;
let pre_frodo_balance_2 = storage::get_user_balance(&e, &pool_2_id, &frodo).shares;
let pre_pool_tokens_1 = storage::get_pool_balance(&e, &pool_1_id).tokens;
let pre_pool_tokens_2 = storage::get_pool_balance(&e, &pool_2_id).tokens;
let pre_pool_shares_1 = storage::get_pool_balance(&e, &pool_1_id).shares;
let pre_pool_shares_2 = storage::get_pool_balance(&e, &pool_2_id).shares;
let result_1 = execute_claim(
&e,
&samwise,
&vec![&e, pool_1_id.clone(), pool_2_id.clone()],
&frodo,
);
assert_eq!(result_1, 1029168100);
assert_eq!(result_1, 1005009202);
assert_eq!(
blnd_token_client.balance(&frodo),
75_3145677 + 6_2904190 + 1029168100
blnd_token_client.balance(&backstop_address),
200_0000000 - (75_3145677 + 6_2904190) - (1005009202)
);
assert_eq!(
blnd_token_client.balance(&backstop_address),
200_0000000 - (75_3145677 + 6_2904190) - (1029168100)
lp_client.balance(&backstop_address),
backstop_lp_balance + 7_9137036
);

let sam_balance_1 = storage::get_user_balance(&e, &pool_1_id, &samwise);
assert_eq!(sam_balance_1.shares, 9_0000000);
let frodo_balance_1 = storage::get_user_balance(&e, &pool_1_id, &frodo);
assert_eq!(frodo_balance_1.shares, pre_frodo_balance_1 + 4_3004891);
let sam_balance_2 = storage::get_user_balance(&e, &pool_2_id, &samwise);
assert_eq!(sam_balance_2.shares, 7_5000000);
let frodo_balance_2 = storage::get_user_balance(&e, &pool_2_id, &frodo);
assert_eq!(frodo_balance_2.shares, pre_frodo_balance_2 + 2_0344033);

let pool_balance_1 = storage::get_pool_balance(&e, &pool_1_id);
assert_eq!(pool_balance_1.tokens, pre_pool_tokens_1 + 5_7339856);
assert_eq!(pool_balance_1.shares, pre_pool_shares_1 + 4_3004891);
let pool_balance_2 = storage::get_pool_balance(&e, &pool_2_id);
assert_eq!(pool_balance_2.tokens, pre_pool_tokens_2 + 2_1797179);
assert_eq!(pool_balance_2.shares, pre_pool_shares_2 + 2_0344033);
let new_backstop_1_data =
storage::get_backstop_emis_data(&e, &pool_1_id).unwrap_optimized();
let new_user_1_data =
storage::get_user_emis_data(&e, &pool_1_id, &samwise).unwrap_optimized();
assert_eq!(new_backstop_1_data.last_time, block_timestamp_1);
assert_eq!(new_backstop_1_data.index, 166846546);
assert_eq!(new_backstop_1_data.index, 164344784);
assert_eq!(new_user_1_data.accrued, 0);
assert_eq!(new_user_1_data.index, 166846546);
assert_eq!(new_user_1_data.index, 164344784);

let new_backstop_2_data =
storage::get_backstop_emis_data(&e, &pool_2_id).unwrap_optimized();
let new_user_2_data =
storage::get_user_emis_data(&e, &pool_2_id, &samwise).unwrap_optimized();
assert_eq!(new_backstop_2_data.last_time, block_timestamp_1);
assert_eq!(new_backstop_2_data.index, 44180450);
assert_eq!(new_backstop_2_data.index, 43961378);
assert_eq!(new_user_2_data.accrued, 0);
assert_eq!(new_user_2_data.index, 44180450);
assert_eq!(new_user_2_data.index, 43961378);
});
}

Expand Down
12 changes: 8 additions & 4 deletions test-suites/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,17 @@ pub fn create_fixture_with_data<'a>(wasm: bool) -> TestFixture<'a> {
fixture.tokens[TokenIndex::WETH].mint(&frodo, &(100 * 10i128.pow(9)));

// mint LP tokens with whale
fixture.tokens[TokenIndex::BLND].mint(&frodo, &(500_001 * SCALAR_7));
fixture.tokens[TokenIndex::BLND].mint(&frodo, &(500_0010_000_0000_0000 * SCALAR_7));
// fixture.tokens[TokenIndex::BLND].approve(&frodo, &fixture.lp.address, &i128::MAX, &99999);
fixture.tokens[TokenIndex::USDC].mint(&frodo, &(12_501 * SCALAR_7));
fixture.tokens[TokenIndex::USDC].mint(&frodo, &(12_5010_000_0000_0000 * SCALAR_7));
// fixture.tokens[TokenIndex::USDC].approve(&frodo, &fixture.lp.address, &i128::MAX, &99999);
fixture.lp.join_pool(
&(50_000 * SCALAR_7),
&vec![&fixture.env, 500_001 * SCALAR_7, 12_501 * SCALAR_7],
&(500_000_0000 * SCALAR_7),
&vec![
&fixture.env,
500_0010_000_0000_0000 * SCALAR_7,
12_5010_000_0000_0000 * SCALAR_7,
],
&frodo,
);

Expand Down
16 changes: 10 additions & 6 deletions test-suites/tests/test_backstop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ fn test_backstop() {
// Mint some backstop tokens
// assumes Sam makes up 20% of the backstop after depositing (50k / 0.8 * 0.2 = 12.5k)
// -> mint 12.5k LP tokens to sam
fixture.tokens[TokenIndex::BLND].mint(&sam, &(125_001 * SCALAR_7)); // 10 BLND per LP token
fixture.tokens[TokenIndex::BLND].mint(&sam, &(125_001_000_0000_0000_000_000 * SCALAR_7)); // 10 BLND per LP token
fixture.tokens[TokenIndex::BLND].approve(&sam, &bstop_token.address, &i128::MAX, &99999);
fixture.tokens[TokenIndex::USDC].mint(&sam, &(3_126 * SCALAR_7)); // 0.25 USDC per LP token
fixture.tokens[TokenIndex::USDC].mint(&sam, &(3_126_000_0000_0000_000_000 * SCALAR_7)); // 0.25 USDC per LP token
fixture.tokens[TokenIndex::USDC].approve(&sam, &bstop_token.address, &i128::MAX, &99999);
bstop_token.join_pool(
&(12_500 * SCALAR_7),
&vec![&fixture.env, 125_001 * SCALAR_7, 3_126 * SCALAR_7],
&vec![
&fixture.env,
125_001_000_0000_0000_000 * SCALAR_7,
3_126_000_0000_0000_000 * SCALAR_7,
],
&sam,
);

Expand Down Expand Up @@ -410,8 +414,8 @@ fn test_backstop() {
);

// Sam claims emissions earned on the backstop deposit
let sam_blnd_balance = &fixture.tokens[TokenIndex::BLND].balance(&sam);
let bstop_blend_balance = &fixture.tokens[TokenIndex::BLND].balance(&fixture.backstop.address);
let comet_blend_balance = &fixture.tokens[TokenIndex::BLND].balance(&fixture.lp.address);
fixture
.backstop
.claim(&sam, &vec![&fixture.env, pool.address.clone()], &sam);
Expand Down Expand Up @@ -447,8 +451,8 @@ fn test_backstop() {
.unwrap();

assert_approx_eq_abs(
fixture.tokens[TokenIndex::BLND].balance(&sam),
sam_blnd_balance + emitted_blnd_1 + emitted_blnd_2,
fixture.tokens[TokenIndex::BLND].balance(&fixture.lp.address),
comet_blend_balance + emitted_blnd_1 + emitted_blnd_2,
SCALAR_7,
);
assert_approx_eq_abs(
Expand Down
4 changes: 0 additions & 4 deletions test-suites/tests/test_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ fn test_emitter() {
let emitter_blnd_balance = blnd_token.balance(&fixture.emitter.address);
let mut backstop_blnd_balance = blnd_token.balance(&fixture.backstop.address);

// println!("checking events...");
// let events = fixture.env.events().all();
// println!("events: {:?}", events);

// Verify initialization can't be re-run
let result = fixture.emitter.try_initialize(
&Address::random(&fixture.env),
Expand Down
Loading