Skip to content
Open
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
54 changes: 22 additions & 32 deletions contract/src/withdraw/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ impl WithdrawApi for Contract {
withdrawn_jar.lock();
*self.get_jar_mut_internal(&jar.account_id, jar.id) = withdrawn_jar;

self.transfer_withdraw(&account_id, amount, &jar, close_jar)
let fee = Self::get_fee(&product, amount);
self.transfer_withdraw(&account_id, amount, fee, &jar, close_jar)
}

fn withdraw_all(&mut self, jars: Option<Vec<JarIdView>>) -> PromiseOrValue<BulkWithdrawView> {
Expand Down Expand Up @@ -144,7 +145,7 @@ impl WithdrawApi for Contract {
jar,
should_be_closed,
amount,
fee: None,
fee: Self::get_fee(&product, amount),
}
})
.collect();
Expand Down Expand Up @@ -195,7 +196,7 @@ impl Contract {
pub(crate) fn after_bulk_withdraw_internal(
&mut self,
account_id: AccountId,
jars: Vec<JarWithdraw>,
withdrawals: Vec<JarWithdraw>,
is_promise_success: bool,
) -> BulkWithdrawView {
let mut withdrawal_result = BulkWithdrawView {
Expand All @@ -204,7 +205,7 @@ impl Contract {
};

if !is_promise_success {
for withdraw in jars {
for withdraw in withdrawals {
let jar = self.get_jar_mut_internal(&account_id, withdraw.jar.id);
jar.principal += withdraw.amount;
jar.unlock();
Expand All @@ -214,16 +215,16 @@ impl Contract {

let mut event_data = vec![];

for withdraw in jars {
if withdraw.should_be_closed {
self.delete_jar(&account_id, withdraw.jar.id);
for withdrawal in withdrawals {
if withdrawal.should_be_closed {
self.delete_jar(&account_id, withdrawal.jar.id);
} else {
self.get_jar_mut_internal(&account_id, withdraw.jar.id).unlock();
self.get_jar_mut_internal(&account_id, withdrawal.jar.id).unlock();
}

let jar_result = WithdrawView::new(withdraw.amount, self.make_fee(withdraw.fee));
let jar_result = WithdrawView::new(withdrawal.amount, self.make_fee(withdrawal.fee));

event_data.push((withdraw.jar.id, jar_result.fee, jar_result.withdrawn_amount));
event_data.push((withdrawal.jar.id, jar_result.fee, jar_result.withdrawn_amount));

withdrawal_result.total_amount.0 += jar_result.withdrawn_amount.0;
withdrawal_result.jars.push(jar_result);
Expand All @@ -234,12 +235,12 @@ impl Contract {
withdrawal_result
}

fn get_fee(product: &Product, jar: &Jar) -> Option<TokenAmount> {
fn get_fee(product: &Product, withdrawal_amount: TokenAmount) -> Option<TokenAmount> {
let fee = product.withdrawal_fee.as_ref()?;

let amount = match fee {
WithdrawalFee::Fix(amount) => *amount,
WithdrawalFee::Percent(percent) => percent * jar.principal,
WithdrawalFee::Percent(percent) => percent * withdrawal_amount,
};

amount.into()
Expand All @@ -261,12 +262,10 @@ impl Contract {
&mut self,
account_id: &AccountId,
amount: TokenAmount,
fee: Option<TokenAmount>,
jar: &Jar,
close_jar: bool,
) -> PromiseOrValue<WithdrawView> {
let product = self.get_product(&jar.product_id);
let fee = Self::get_fee(&product, jar);

self.ft_contract()
.ft_transfer(account_id, amount, "withdraw", &self.make_fee(fee))
.then(Self::after_withdraw_call(
Expand All @@ -282,32 +281,25 @@ impl Contract {
fn transfer_bulk_withdraw(
&mut self,
account_id: &AccountId,
jars: Vec<JarWithdraw>,
withdrawals: Vec<JarWithdraw>,
) -> PromiseOrValue<BulkWithdrawView> {
let total_fee: TokenAmount = jars
.iter()
.filter_map(|j| {
let product = self.get_product(&j.jar.product_id);
Self::get_fee(&product, &j.jar)
})
.sum();

let total_fee: TokenAmount = withdrawals.iter().filter_map(|j| j.fee).sum();
let total_fee = match total_fee {
0 => None,
_ => self.make_fee(total_fee.into()),
};

let total_amount = jars.iter().map(|j| j.amount).sum();
let total_amount = withdrawals.iter().map(|j| j.amount).sum();

crate::internal::assert_gas(
crate::common::gas_data::GAS_FOR_FT_TRANSFER.as_gas()
+ crate::common::gas_data::GAS_FOR_BULK_AFTER_WITHDRAW.as_gas(),
|| format!("transfer_bulk_withdraw. Number of jars: {}", jars.len()),
|| format!("transfer_bulk_withdraw. Number of jars: {}", withdrawals.len()),
);

self.ft_contract()
.ft_transfer(account_id, total_amount, "bulk_withdraw", &total_fee)
.then(Self::after_bulk_withdraw_call(account_id.clone(), jars))
.then(Self::after_bulk_withdraw_call(account_id.clone(), withdrawals))
.into()
}

Expand Down Expand Up @@ -336,12 +328,10 @@ impl Contract {
&mut self,
account_id: &AccountId,
amount: TokenAmount,
fee: Option<TokenAmount>,
jar: &Jar,
close_jar: bool,
) -> PromiseOrValue<WithdrawView> {
let product = self.get_product(&jar.product_id);
let fee = Self::get_fee(&product, jar);

let withdrawn = self.after_withdraw_internal(
account_id.clone(),
jar.id,
Expand All @@ -357,11 +347,11 @@ impl Contract {
fn transfer_bulk_withdraw(
&mut self,
account_id: &AccountId,
jars: Vec<JarWithdraw>,
withdrawals: Vec<JarWithdraw>,
) -> PromiseOrValue<BulkWithdrawView> {
let withdrawn = self.after_bulk_withdraw_internal(
account_id.clone(),
jars,
withdrawals,
crate::common::test_data::get_test_future_success(),
);

Expand Down
7 changes: 4 additions & 3 deletions contract/src/withdraw/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ fn product_with_fixed_fee() {
#[test]
fn product_with_percent_fee() {
let fee_value = UDecimal::new(5, 4);
let fee = WithdrawalFee::Percent(fee_value.clone());
let fee = WithdrawalFee::Percent(fee_value);
let product = Product::new().with_withdrawal_fee(fee);
let (alice, reference_jar, mut context) = prepare_jar(&product);

Expand All @@ -240,8 +240,9 @@ fn product_with_percent_fee() {
.withdraw(U32(0), Some(U128(withdrawn_amount)))
.unwrap();

let reference_fee = fee_value * initial_principal;
assert_eq!(withdraw.withdrawn_amount, U128(withdrawn_amount - reference_fee));
let reference_fee = fee_value * withdrawn_amount;
let reference_withdrawn_amount = withdrawn_amount - reference_fee;
assert_eq!(withdraw.withdrawn_amount.0, reference_withdrawn_amount);
assert_eq!(withdraw.fee, U128(reference_fee));

let jar = context.contract().get_jar(alice, U32(reference_jar.id));
Expand Down
Binary file modified res/sweat_jar.wasm
Binary file not shown.