Skip to content

Commit

Permalink
Merge pull request #137 from blend-capital/q4w-emissions-issue-135
Browse files Browse the repository at this point in the history
Q4w emissions issue 135
  • Loading branch information
mootz12 authored Oct 25, 2023
2 parents aa10c8d + 4db82ff commit ea274b7
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 127 deletions.
94 changes: 11 additions & 83 deletions backstop/src/backstop/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,10 @@ impl UserBalance {
/// ### Errors
/// If the amount to queue is greater than the available shares
pub fn queue_shares_for_withdrawal(&mut self, e: &Env, to_q: i128) {
let mut q4w_amt: i128 = 0;
for q4w in self.q4w.iter() {
q4w_amt += q4w.amount
}

if self.shares - q4w_amt < to_q {
if self.shares < to_q {
panic_with_error!(e, BackstopError::InvalidBalance);
}
self.shares = self.shares - to_q;

// user has enough tokens to withdrawal, add Q4W
// TODO: Consider capping how many active Q4Ws a user can have
Expand Down Expand Up @@ -113,19 +109,6 @@ impl UserBalance {
panic_with_error!(e, BackstopError::InvalidBalance);
}
}

/// Withdraw shares from the user
///
/// ### Arguments
/// * `to_q` - The amount of new shares to queue for withdraw
///
/// ### Errors
/// If the amount to queue is greater than the available shares
pub fn withdraw_shares(&mut self, e: &Env, to_withdraw: i128) {
self.dequeue_shares_for_withdrawal(e, to_withdraw, true);

self.shares -= to_withdraw;
}
}

#[cfg(test)]
Expand Down Expand Up @@ -240,7 +223,7 @@ mod tests {
},
];
let mut user = UserBalance {
shares: 1000,
shares: 800,
q4w: cur_q4w.clone(),
};

Expand Down Expand Up @@ -281,7 +264,7 @@ mod tests {
});

let to_wd = 1;
user.withdraw_shares(&e, to_wd);
user.dequeue_shares_for_withdrawal(&e, to_wd, false);
}

#[test]
Expand Down Expand Up @@ -312,10 +295,10 @@ mod tests {
});

let to_wd = 200;
user.withdraw_shares(&e, to_wd);
user.dequeue_shares_for_withdrawal(&e, to_wd, true);

assert_eq_vec_q4w(&user.q4w, &vec![&e]);
assert_eq!(user.shares, 800);
assert_eq!(user.shares, 1000);
}

#[test]
Expand Down Expand Up @@ -346,7 +329,7 @@ mod tests {
});

let to_wd = 150;
user.withdraw_shares(&e, to_wd);
user.dequeue_shares_for_withdrawal(&e, to_wd, false);

let expected_q4w = vec![
&e,
Expand All @@ -356,7 +339,7 @@ mod tests {
},
];
assert_eq_vec_q4w(&user.q4w, &expected_q4w);
assert_eq!(user.shares, 850);
assert_eq!(user.shares, 1000);
}

#[test]
Expand Down Expand Up @@ -395,7 +378,7 @@ mod tests {
});

let to_wd = 300;
user.withdraw_shares(&e, to_wd);
user.dequeue_shares_for_withdrawal(&e, to_wd, true);

let expected_q4w = vec![
&e,
Expand All @@ -409,7 +392,7 @@ mod tests {
},
];
assert_eq_vec_q4w(&user.q4w, &expected_q4w);
assert_eq!(user.shares, 700);
assert_eq!(user.shares, 1000);
}

#[test]
Expand Down Expand Up @@ -449,61 +432,7 @@ mod tests {
});

let to_wd = 300;
user.withdraw_shares(&e, to_wd);
}

#[test]
fn test_dequeue_shares() {
let e = Env::default();

let cur_q4w = vec![
&e,
Q4W {
amount: 125,
exp: 10000000,
},
Q4W {
amount: 200,
exp: 12592000,
},
Q4W {
amount: 50,
exp: 19592000,
},
];
let mut user = UserBalance {
shares: 1000,
q4w: cur_q4w.clone(),
};

e.ledger().set(LedgerInfo {
protocol_version: 20,
sequence_number: 1,
timestamp: 11192000,
network_id: Default::default(),
base_reserve: 10,
min_temp_entry_expiration: 10,
min_persistent_entry_expiration: 10,
max_entry_expiration: 2000000,
});
let to_dequeue = 300;

// verify exp is ignored if only dequeueing
user.dequeue_shares_for_withdrawal(&e, to_dequeue, false);

let expected_q4w = vec![
&e,
Q4W {
amount: 25,
exp: 12592000,
},
Q4W {
amount: 50,
exp: 19592000,
},
];
assert_eq_vec_q4w(&user.q4w, &expected_q4w);
assert_eq!(user.shares, 1000);
user.dequeue_shares_for_withdrawal(&e, to_wd, true);
}

#[test]
Expand Down Expand Up @@ -545,7 +474,6 @@ mod tests {
// verify exp is respected when specified
user.dequeue_shares_for_withdrawal(&e, to_dequeue, true);
}

#[test]
#[should_panic(expected = "Error(Contract, #2)")]
fn test_try_withdraw_shares_over_total() {
Expand Down
22 changes: 16 additions & 6 deletions backstop/src/backstop/withdrawal.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use crate::{contract::require_nonnegative, dependencies::TokenClient, emissions, storage};
use crate::{
contract::require_nonnegative,
dependencies::TokenClient,
emissions::{self},
storage,
};
use soroban_sdk::{unwrap::UnwrapOptimized, Address, Env};

use super::Q4W;
Expand All @@ -15,6 +20,9 @@ pub fn execute_queue_withdrawal(
let mut pool_balance = storage::get_pool_balance(e, pool_address);
let mut user_balance = storage::get_user_balance(e, pool_address, from);

// update emissions
emissions::update_emissions(e, pool_address, &pool_balance, from, &user_balance, false);

user_balance.queue_shares_for_withdrawal(e, amount);
pool_balance.queue_for_withdraw(amount);

Expand All @@ -31,7 +39,11 @@ pub fn execute_dequeue_withdrawal(e: &Env, from: &Address, pool_address: &Addres
let mut pool_balance = storage::get_pool_balance(e, pool_address);
let mut user_balance = storage::get_user_balance(e, pool_address, from);

// update emissions
emissions::update_emissions(e, pool_address, &pool_balance, from, &user_balance, false);

user_balance.dequeue_shares_for_withdrawal(e, amount, false);
user_balance.add_shares(amount);
pool_balance.dequeue_q4w(e, amount);

storage::set_user_balance(e, pool_address, from, &user_balance);
Expand All @@ -45,9 +57,7 @@ pub fn execute_withdraw(e: &Env, from: &Address, pool_address: &Address, amount:
let mut pool_balance = storage::get_pool_balance(e, pool_address);
let mut user_balance = storage::get_user_balance(e, pool_address, from);

emissions::update_emissions(e, pool_address, &pool_balance, from, &user_balance, false);

user_balance.withdraw_shares(e, amount);
user_balance.dequeue_shares_for_withdrawal(e, amount, true);

let to_return = pool_balance.convert_to_tokens(amount);
pool_balance.withdraw(e, to_return, amount);
Expand Down Expand Up @@ -108,7 +118,7 @@ mod tests {
execute_queue_withdrawal(&e, &samwise, &pool_address, 42_0000000);

let new_user_balance = storage::get_user_balance(&e, &pool_address, &samwise);
assert_eq!(new_user_balance.shares, 100_0000000);
assert_eq!(new_user_balance.shares, 58_0000000);
let expected_q4w = vec![
&e,
Q4W {
Expand Down Expand Up @@ -213,7 +223,7 @@ mod tests {
execute_dequeue_withdrawal(&e, &samwise, &pool_address, 30_0000000);

let new_user_balance = storage::get_user_balance(&e, &pool_address, &samwise);
assert_eq!(new_user_balance.shares, 75_0000000);
assert_eq!(new_user_balance.shares, 40_0000000);
let expected_q4w = vec![
&e,
Q4W {
Expand Down
42 changes: 21 additions & 21 deletions backstop/src/emissions/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,30 +145,30 @@ mod tests {
&vec![&e, pool_1_id.clone(), pool_2_id.clone()],
&frodo,
);
assert_eq!(result, 75_3145677 + 5_0250000);
assert_eq!(blnd_token_client.balance(&frodo), 75_3145677 + 5_0250000);
assert_eq!(result, 75_3145677 + 6_2904190);
assert_eq!(blnd_token_client.balance(&frodo), 75_3145677 + 6_2904190);
assert_eq!(
blnd_token_client.balance(&backstop_address),
100_0000000 - (75_3145677 + 5_0250000)
100_0000000 - (75_3145677 + 6_2904190)
);

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);
assert_eq!(new_backstop_1_data.index, 82322222);
assert_eq!(new_backstop_1_data.index, 83434384);
assert_eq!(new_user_1_data.accrued, 0);
assert_eq!(new_user_1_data.index, 82322222);
assert_eq!(new_user_1_data.index, 83434384);

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);
assert_eq!(new_backstop_2_data.index, 6700000);
assert_eq!(new_backstop_2_data.index, 7052631);
assert_eq!(new_user_2_data.accrued, 0);
assert_eq!(new_user_2_data.index, 6700000);
assert_eq!(new_user_2_data.index, 7052631);
});
}

Expand Down Expand Up @@ -276,30 +276,30 @@ mod tests {
&vec![&e, pool_1_id.clone(), pool_2_id.clone()],
&frodo,
);
assert_eq!(result, 75_3145677 + 5_0250000);
assert_eq!(blnd_token_client.balance(&frodo), 75_3145677 + 5_0250000);
assert_eq!(result, 75_3145677 + 6_2904190);
assert_eq!(blnd_token_client.balance(&frodo), 75_3145677 + 6_2904190);
assert_eq!(
blnd_token_client.balance(&backstop_address),
200_0000000 - (75_3145677 + 5_0250000)
200_0000000 - (75_3145677 + 6_2904190)
);

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);
assert_eq!(new_backstop_1_data.index, 82322222);
assert_eq!(new_backstop_1_data.index, 83434384);
assert_eq!(new_user_1_data.accrued, 0);
assert_eq!(new_user_1_data.index, 82322222);
assert_eq!(new_user_1_data.index, 83434384);

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);
assert_eq!(new_backstop_2_data.index, 6700000);
assert_eq!(new_backstop_2_data.index, 7052631);
assert_eq!(new_user_2_data.accrued, 0);
assert_eq!(new_user_2_data.index, 6700000);
assert_eq!(new_user_2_data.index, 7052631);

let block_timestamp_1 = 1500000000 + 12345 + 12345;
e.ledger().set(LedgerInfo {
Expand All @@ -318,33 +318,33 @@ mod tests {
&vec![&e, pool_1_id.clone(), pool_2_id.clone()],
&frodo,
);
assert_eq!(result_1, 1005235710);
assert_eq!(result_1, 1029168100);
assert_eq!(
blnd_token_client.balance(&frodo),
75_3145677 + 5_0250000 + 1005235710
75_3145677 + 6_2904190 + 1029168100
);
assert_eq!(
blnd_token_client.balance(&backstop_address),
200_0000000 - (75_3145677 + 5_0250000) - (1005235710)
200_0000000 - (75_3145677 + 6_2904190) - (1029168100)
);

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, 164622222);
assert_eq!(new_backstop_1_data.index, 166846546);
assert_eq!(new_user_1_data.accrued, 0);
assert_eq!(new_user_1_data.index, 164622222);
assert_eq!(new_user_1_data.index, 166846546);

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, 41971428);
assert_eq!(new_backstop_2_data.index, 44180450);
assert_eq!(new_user_2_data.accrued, 0);
assert_eq!(new_user_2_data.index, 41971428);
assert_eq!(new_user_2_data.index, 44180450);
});
}

Expand Down
Loading

0 comments on commit ea274b7

Please sign in to comment.