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: bulk restake and withdraw #81

Merged
merged 20 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 16 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
199 changes: 98 additions & 101 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ fake = "2.8.0"
rand = "0.8.5"
futures = "0.3.28"
num-format = "0.4.4"
itertools = "0.12.1"
ed25519-dalek = { version = "2.0.0", features = ["rand_core"] }
base64 = "0.22.0"
sha256 = "1.3.0"
Expand Down
2 changes: 1 addition & 1 deletion contract/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sweat_jar"
version = "1.0.1"
version = "2.0.0"
VladasZ marked this conversation as resolved.
Show resolved Hide resolved
authors = ["Sweat Economy"]
edition = "2021"

Expand Down
2 changes: 1 addition & 1 deletion contract/src/claim/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl Contract {
) -> PromiseOrValue<ClaimedAmountView> {
use crate::ft_interface::FungibleTokenInterface;
self.ft_contract()
.transfer(account_id, claimed_amount.get_total().0, "claim", &None)
.ft_transfer(account_id, claimed_amount.get_total().0, "claim", &None)
.then(after_claim_call(claimed_amount, jars_before_transfer, event, now))
.into()
}
Expand Down
116 changes: 52 additions & 64 deletions contract/src/claim/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![cfg(test)]

use near_sdk::{json_types::U128, test_utils::accounts, PromiseOrValue};
use near_sdk::{json_types::U128, test_utils::test_env::alice, PromiseOrValue};
use sweat_jar_model::{
api::{ClaimApi, JarApi, WithdrawApi},
claimed_amount_view::ClaimedAmountView,
Expand All @@ -11,31 +11,28 @@ use crate::{
common::{test_data::set_test_future_success, tests::Context, udecimal::UDecimal},
jar::model::Jar,
product::model::{Apy, Product},
test_utils::{admin, UnwrapPromise},
};

#[test]
fn claim_total_when_nothing_to_claim() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product();
let jar = Jar::generate(0, &alice, &product.id).principal(100_000_000);
let mut context = Context::new(admin).with_products(&[product]).with_jars(&[jar]);

context.switch_account(&alice);
let result = context.contract.claim_total(None);

let PromiseOrValue::Value(value) = result else {
panic!();
};
context.switch_account(alice);
let value = context.contract().claim_total(None).unwrap();

assert_eq!(0, value.get_total().0);
}

#[test]
fn claim_total_detailed_when_having_tokens() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product();
let jar_0 = Jar::generate(0, &alice, &product.id).principal(100_000_000);
Expand All @@ -53,7 +50,7 @@ fn claim_total_detailed_when_having_tokens() {
context.set_block_timestamp_in_ms(test_duration);

context.switch_account(&alice);
let result = context.contract.claim_total(Some(true));
let result = context.contract().claim_total(Some(true));

let PromiseOrValue::Value(ClaimedAmountView::Detailed(value)) = result else {
panic!();
Expand All @@ -67,8 +64,8 @@ fn claim_total_detailed_when_having_tokens() {

#[test]
fn claim_partially_detailed_when_having_tokens() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product();
let jar_0 = Jar::generate(0, &alice, &product.id).principal(100_000_000);
Expand All @@ -86,7 +83,7 @@ fn claim_partially_detailed_when_having_tokens() {
context.set_block_timestamp_in_ms(test_duration);

context.switch_account(&alice);
let result = context.contract.claim_jars(
let result = context.contract().claim_jars(
vec![U32(jar_0.id), U32(jar_1.id)],
Some(U128(jar_0_expected_interest + jar_1_expected_interest)),
Some(true),
Expand All @@ -104,8 +101,8 @@ fn claim_partially_detailed_when_having_tokens() {

#[test]
fn claim_pending_withdraw_jar() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product();
let jar_0 = Jar::generate(0, &alice, &product.id).principal(100_000_000);
Expand All @@ -126,7 +123,7 @@ fn claim_pending_withdraw_jar() {
context.set_block_timestamp_in_ms(test_duration);

context.switch_account(&alice);
let result = context.contract.claim_jars(
let result = context.contract().claim_jars(
vec![U32(jar_0.id), U32(jar_1.id)],
Some(U128(jar_0_expected_interest.0 + jar_1_expected_interest)),
Some(true),
Expand All @@ -144,8 +141,8 @@ fn claim_pending_withdraw_jar() {

#[test]
fn claim_partially_detailed_when_having_tokens_and_request_sum_of_single_deposit() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product();
let jar_0 = Jar::generate(0, &alice, &product.id).principal(100_000_000);
Expand All @@ -162,7 +159,7 @@ fn claim_partially_detailed_when_having_tokens_and_request_sum_of_single_deposit
context.set_block_timestamp_in_ms(test_duration);

context.switch_account(&alice);
let result = context.contract.claim_jars(
let result = context.contract().claim_jars(
vec![U32(jar_0.id), U32(jar_1.id)],
Some(U128(jar_0_expected_interest)),
Some(true),
Expand All @@ -180,8 +177,8 @@ fn claim_partially_detailed_when_having_tokens_and_request_sum_of_single_deposit

#[test]
fn claim_partially_when_having_tokens_to_claim() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product();
let jar = Jar::generate(0, &alice, &product.id).principal(100_000_000_000);
Expand All @@ -190,20 +187,21 @@ fn claim_partially_when_having_tokens_to_claim() {
context.set_block_timestamp_in_days(365);

context.switch_account(&alice);
let PromiseOrValue::Value(claimed) = context.contract.claim_jars(vec![U32(jar.id)], Some(U128(100)), None) else {
panic!()
};
let claimed = context
.contract()
.claim_jars(vec![U32(jar.id)], Some(U128(100)), None)
.unwrap();

assert_eq!(claimed.get_total().0, 100);

let jar = context.contract.get_jar(alice, U32(jar.id));
let jar = context.contract().get_jar(alice, U32(jar.id));
assert_eq!(100, jar.claimed_balance.0);
}

#[test]
fn dont_delete_jar_on_all_interest_claim() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product().apy(Apy::Constant(UDecimal::new(2, 1)));
let jar = Jar::generate(0, &alice, &product.id).principal(1_000_000);
Expand All @@ -213,10 +211,10 @@ fn dont_delete_jar_on_all_interest_claim() {

context.switch_account(&alice);
context
.contract
.contract()
.claim_jars(vec![U32(jar.id)], Some(U128(200_000)), None);

let jar = context.contract.get_jar_internal(&alice, jar.id);
let jar = context.contract().get_jar_internal(&alice, jar.id);
assert_eq!(200_000, jar.claimed_balance);

let Some(ref cache) = jar.cache else { panic!() };
Expand All @@ -228,8 +226,8 @@ fn dont_delete_jar_on_all_interest_claim() {
#[test]
#[should_panic(expected = "Jar with id: 0 doesn't exist")]
fn claim_all_withdraw_all_and_delete_jar() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product().apy(Apy::Constant(UDecimal::new(2, 1)));
let jar = Jar::generate(0, &alice, &product.id).principal(1_000_000);
Expand All @@ -243,38 +241,34 @@ fn claim_all_withdraw_all_and_delete_jar() {
context.set_block_timestamp_in_ms(product.get_lockup_term().unwrap() + 1);

context.switch_account(&alice);
let PromiseOrValue::Value(claimed) = context
.contract
let claimed = context
.contract()
.claim_jars(vec![U32(jar_id)], Some(U128(200_000)), None)
else {
panic!()
};
.unwrap();

assert_eq!(200_000, claimed.get_total().0);

let jar = context.contract.get_jar_internal(&alice, jar_id);
let jar = context.contract().get_jar_internal(&alice, jar_id);
assert_eq!(200_000, jar.claimed_balance);

let Some(ref cache) = jar.cache else { panic!() };

assert_eq!(cache.interest, 0);
assert_eq!(jar.principal, 1_000_000);

let PromiseOrValue::Value(withdrawn) = context.contract.withdraw(U32(jar_id), None) else {
panic!()
};
let withdrawn = context.contract().withdraw(U32(jar_id), None).unwrap();

assert_eq!(withdrawn.withdrawn_amount, U128(1_000_000));
assert_eq!(withdrawn.fee, U128(0));

let _jar = context.contract.get_jar_internal(&alice, jar_id);
let _jar = context.contract().get_jar_internal(&alice, jar_id);
}

#[test]
#[should_panic(expected = "Jar with id: 0 doesn't exist")]
fn withdraw_all_claim_all_and_delete_jar() {
let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product().apy(Apy::Constant(UDecimal::new(2, 1)));
let jar = Jar::generate(0, &alice, &product.id).principal(1_000_000);
Expand All @@ -289,35 +283,31 @@ fn withdraw_all_claim_all_and_delete_jar() {

context.switch_account(&alice);

let PromiseOrValue::Value(withdrawn) = context.contract.withdraw(U32(jar_id), None) else {
panic!()
};
let withdrawn = context.contract().withdraw(U32(jar_id), None).unwrap();

assert_eq!(withdrawn.withdrawn_amount, U128(1_000_000));
assert_eq!(withdrawn.fee, U128(0));

let jar = context.contract.get_jar_internal(&alice, jar_id);
let jar = context.contract().get_jar_internal(&alice, jar_id);

assert_eq!(jar.principal, 0);

let PromiseOrValue::Value(claimed) = context
.contract
let claimed = context
.contract()
.claim_jars(vec![U32(jar_id)], Some(U128(200_000)), None)
else {
panic!();
};
.unwrap();

assert_eq!(claimed.get_total(), U128(200_000));

let _jar = context.contract.get_jar_internal(&alice, jar_id);
let _jar = context.contract().get_jar_internal(&alice, jar_id);
}

#[test]
fn failed_future_claim() {
set_test_future_success(false);

let alice = accounts(0);
let admin = accounts(1);
let alice = alice();
let admin = admin();

let product = generate_product().apy(Apy::Constant(UDecimal::new(2, 1)));
let jar = Jar::generate(0, &alice, &product.id).principal(1_000_000);
Expand All @@ -327,18 +317,16 @@ fn failed_future_claim() {

context.switch_account(&alice);

let jar_before_claim = context.contract.get_jar_internal(&alice, jar.id).clone();
let jar_before_claim = context.contract().get_jar_internal(&alice, jar.id).clone();

let PromiseOrValue::Value(claimed) = context
.contract
let claimed = context
.contract()
.claim_jars(vec![U32(jar.id)], Some(U128(200_000)), None)
else {
panic!()
};
.unwrap();

assert_eq!(claimed.get_total().0, 0);

let jar_after_claim = context.contract.get_jar_internal(&alice, jar.id);
let jar_after_claim = context.contract().get_jar_internal(&alice, jar.id);

assert_eq!(jar_before_claim, jar_after_claim);
}
Expand Down
7 changes: 6 additions & 1 deletion contract/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,20 @@ pub mod gas_data {
/// Value is measured with `measure_withdraw_test`
/// Average gas for this method call don't exceed 3.4 `TGas`. 4 here just in case.
pub(crate) const GAS_FOR_AFTER_WITHDRAW: Gas = Gas::from_tgas(4);

/// Value is measured with `measure_withdraw_all`
/// 10 `TGas` was enough for 200 jars. 15 here just in case.
pub(crate) const GAS_FOR_BULK_AFTER_WITHDRAW: Gas = Gas::from_tgas(15);
}

#[cfg(test)]
mod test {
use crate::common::gas_data::{GAS_FOR_AFTER_CLAIM, GAS_FOR_AFTER_WITHDRAW};
use crate::common::gas_data::{GAS_FOR_AFTER_CLAIM, GAS_FOR_AFTER_WITHDRAW, GAS_FOR_BULK_AFTER_WITHDRAW};

#[test]
fn test_gas_methods() {
assert_eq!(GAS_FOR_AFTER_CLAIM.as_gas(), 20_000_000_000_000);
assert_eq!(GAS_FOR_AFTER_WITHDRAW.as_gas(), 4_000_000_000_000);
assert_eq!(GAS_FOR_BULK_AFTER_WITHDRAW.as_gas(), 15_000_000_000_000);
VladasZ marked this conversation as resolved.
Show resolved Hide resolved
}
}
Loading
Loading