Skip to content

Commit

Permalink
Add checks for 0 token output and tests (solana-labs#595)
Browse files Browse the repository at this point in the history
  • Loading branch information
joncinque authored Oct 9, 2020
1 parent a965c4a commit 423d8b1
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 5 deletions.
23 changes: 18 additions & 5 deletions token-swap/program/src/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@ impl SwapResult {
let invariant = swap_source_amount.checked_mul(swap_destination_amount)?;

// debit the fee to calculate the amount swapped
let fee = source_amount
let mut fee = source_amount
.checked_mul(fee_numerator)?
.checked_div(fee_denominator)?;
if fee == 0 {
fee = 1; // minimum fee of one token
}
let new_source_amount_less_fee = swap_source_amount
.checked_add(source_amount)?
.checked_sub(fee)?;
Expand All @@ -48,6 +51,14 @@ impl SwapResult {
}
}

fn map_zero_to_none(x: u64) -> Option<u64> {
if x == 0 {
None
} else {
Some(x)
}
}

/// The Uniswap invariant calculator.
pub struct ConstantProduct {
/// Token A
Expand All @@ -72,7 +83,7 @@ impl ConstantProduct {
)?;
self.token_a = result.new_source_amount;
self.token_b = result.new_destination_amount;
Some(result.amount_swapped)
map_zero_to_none(result.amount_swapped)
}

/// Swap token b to a
Expand All @@ -86,7 +97,7 @@ impl ConstantProduct {
)?;
self.token_b = result.new_source_amount;
self.token_a = result.new_destination_amount;
Some(result.amount_swapped)
map_zero_to_none(result.amount_swapped)
}
}

Expand Down Expand Up @@ -123,18 +134,20 @@ impl PoolTokenConverter {
}
}

/// A tokens for pool tokens
/// A tokens for pool tokens, returns None if output is less than 0
pub fn token_a_rate(&self, pool_tokens: u64) -> Option<u64> {
pool_tokens
.checked_mul(self.token_a)?
.checked_div(self.supply)
.and_then(map_zero_to_none)
}

/// B tokens for pool tokens
/// B tokens for pool tokens, returns None is output is less than 0
pub fn token_b_rate(&self, pool_tokens: u64) -> Option<u64> {
pool_tokens
.checked_mul(self.token_b)?
.checked_div(self.supply)
.and_then(map_zero_to_none)
}
}

Expand Down
86 changes: 86 additions & 0 deletions token-swap/program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1938,6 +1938,33 @@ mod tests {
accounts.pool_mint_account = old_pool_account;
}

// deposit 1 pool token fails beacuse it equates to 0 swap tokens
{
let (
token_a_key,
mut token_a_account,
token_b_key,
mut token_b_account,
pool_key,
mut pool_account,
) = accounts.setup_token_accounts(&user_key, &depositor_key, deposit_a, deposit_b, 0);
assert_eq!(
Err(SwapError::CalculationFailure.into()),
accounts.deposit(
&depositor_key,
&pool_key,
&mut pool_account,
&token_a_key,
&mut token_a_account,
&token_b_key,
&mut token_b_account,
1,
deposit_a,
deposit_b / 10,
)
);
}

// slippage exceeeded
{
let (
Expand Down Expand Up @@ -2435,6 +2462,39 @@ mod tests {
accounts.pool_mint_account = old_pool_account;
}

// withdrawing 1 pool token fails because it equates to 0 output tokens
{
let (
token_a_key,
mut token_a_account,
token_b_key,
mut token_b_account,
pool_key,
mut pool_account,
) = accounts.setup_token_accounts(
&user_key,
&withdrawer_key,
initial_a,
initial_b,
initial_pool,
);
assert_eq!(
Err(SwapError::CalculationFailure.into()),
accounts.withdraw(
&withdrawer_key,
&pool_key,
&mut pool_account,
&token_a_key,
&mut token_a_account,
&token_b_key,
&mut token_b_account,
1,
minimum_a_amount * 10,
minimum_b_amount,
)
);
}

// slippage exceeeded
{
let (
Expand Down Expand Up @@ -2820,6 +2880,32 @@ mod tests {
);
}

// output token value 0
{
let (
token_a_key,
mut token_a_account,
token_b_key,
mut token_b_account,
_pool_key,
_pool_account,
) = accounts.setup_token_accounts(&user_key, &swapper_key, initial_a, initial_b, 0);
assert_eq!(
Err(SwapError::CalculationFailure.into()),
accounts.swap(
&swapper_key,
&token_b_key,
&mut token_b_account,
&swap_token_b_key,
&swap_token_a_key,
&token_a_key,
&mut token_a_account,
1,
1,
)
);
}

// slippage exceeeded: minimum out amount too high
{
let (
Expand Down

0 comments on commit 423d8b1

Please sign in to comment.