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

Disallow deposit/withdrawal when all amounts are 0 #34

Merged
merged 4 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
37 changes: 29 additions & 8 deletions amm/contracts/stable_pool/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,11 @@ pub mod stable_pool {
amounts.len() == self.pool.tokens.len(),
StablePoolError::IncorrectAmountsCount
);
// Check that at least one amount is non-zero
ensure!(
amounts.iter().any(|&amount| amount > 0),
StablePoolError::InsufficientAmounts
);

// Make sure rates are up to date before we attempt any calculations
let rates = self.get_scaled_rates()?;
Expand All @@ -559,12 +564,14 @@ pub mod stable_pool {

// transfer amounts
for (id, &token) in self.pool.tokens.iter().enumerate() {
self.token_by_address(token).transfer_from(
self.env().caller(),
self.env().account_id(),
amounts[id],
vec![],
)?;
if amounts[id] > 0 {
self.token_by_address(token).transfer_from(
self.env().caller(),
self.env().account_id(),
amounts[id],
vec![],
)?;
}
}

// mint shares
Expand Down Expand Up @@ -620,10 +627,17 @@ pub mod stable_pool {
.all(|(amount, min_amount)| amount >= min_amount),
StablePoolError::InsufficientOutputAmount
);
// Check that at least one amount is non-zero
ensure!(
amounts.iter().any(|&amount| amount > 0),
StablePoolError::InsufficientAmounts
);

// transfer tokens
for (&token, &amount) in self.pool.tokens.iter().zip(amounts.iter()) {
self.token_by_address(token).transfer(to, amount, vec![])?;
if amount > 0 {
self.token_by_address(token).transfer(to, amount, vec![])?;
}
}

// update reserves
Expand Down Expand Up @@ -658,6 +672,11 @@ pub mod stable_pool {
amounts.len() == self.pool.tokens.len(),
StablePoolError::IncorrectAmountsCount
);
// Check that at least one amount is non-zero
ensure!(
amounts.iter().any(|&amount| amount > 0),
StablePoolError::InsufficientAmounts
);

let rates = self.get_scaled_rates()?;

Expand Down Expand Up @@ -689,7 +708,9 @@ pub mod stable_pool {
}
// transfer tokens
for (&token, &amount) in self.pool.tokens.iter().zip(amounts.iter()) {
self.token_by_address(token).transfer(to, amount, vec![])?;
if amount > 0 {
self.token_by_address(token).transfer(to, amount, vec![])?;
}
}
// update reserves
for (i, &amount) in amounts.iter().enumerate() {
Expand Down
144 changes: 144 additions & 0 deletions amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1225,3 +1225,147 @@ fn test_lp_withdraw_all_but_no_more() {
)
.expect_err("Should not successfully remove liquidity");
}

#[drink::test]
fn test_for_zero_deposit(mut session: Session) {
seed_account(&mut session, CHARLIE);
seed_account(&mut session, DAVE);
seed_account(&mut session, EVA);

let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC];
let initial_supply = initial_reserves
.iter()
.map(|amount| amount * 100_000_000_000)
.collect::<Vec<u128>>();
let (stable_swap, tokens) = setup_stable_swap_with_tokens(
&mut session,
vec![18, 6, 6],
initial_supply.clone(),
10_000,
2_500_000,
200_000_000,
BOB,
vec![],
);

_ = stable_swap::add_liquidity(
&mut session,
stable_swap,
BOB,
1,
initial_reserves.clone(),
bob(),
)
.expect("Should successfully add liquidity");

// setup max allowance for stable swap contract on both tokens
transfer_and_increase_allowance(
&mut session,
stable_swap,
tokens.clone(),
CHARLIE,
vec![500 * ONE_DAI, 500 * ONE_USDT, 500 * ONE_USDC],
BOB,
);

let err = stable_swap::add_liquidity(
&mut session,
stable_swap,
CHARLIE,
0,
vec![0, 0, 0],
charlie(),
)
.expect_err("Should return an error");

assert_eq!(
err,
StablePoolError::InsufficientAmounts(),
"Should return appropriate error"
);

_ = stable_swap::add_liquidity(
&mut session,
stable_swap,
CHARLIE,
0,
vec![1, 0, 0],
charlie(),
)
.expect("Should min liqudity");
}

#[drink::test]
fn test_for_zero_withdrawal(mut session: Session) {
seed_account(&mut session, CHARLIE);
seed_account(&mut session, DAVE);
seed_account(&mut session, EVA);

let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC];
let initial_supply = initial_reserves
.iter()
.map(|amount| amount * 100_000_000_000)
.collect::<Vec<u128>>();
let (stable_swap, _) = setup_stable_swap_with_tokens(
&mut session,
vec![18, 6, 6],
initial_supply.clone(),
10_000,
2_500_000,
200_000_000,
BOB,
vec![],
);

_ = stable_swap::add_liquidity(
&mut session,
stable_swap,
BOB,
1,
initial_reserves.clone(),
bob(),
)
.expect("Should successfully add liquidity");

let err = stable_swap::remove_liquidity_by_shares(
&mut session,
stable_swap,
BOB,
1,
vec![0, 0, 0],
bob(),
)
.expect_err("Should return an error");

assert_eq!(
err,
StablePoolError::InsufficientAmounts(),
"Should return appropriate error"
);

let err = stable_swap::remove_liquidity_by_amounts(
&mut session,
stable_swap,
BOB,
0,
vec![0, 0, 0],
bob(),
)
.expect_err("Should return an error");

assert_eq!(
err,
StablePoolError::InsufficientAmounts(),
"Should return appropriate error"
);

_ = stable_swap::remove_liquidity_by_amounts(
&mut session,
stable_swap,
BOB,
1,
vec![1, 0, 0],
bob(),
)
.expect("Should burn liquidity");
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn test_swap_exact_in(
[0, expected_protocol_fee_part].to_vec(),
bob(),
)
.expect("swap_exact_in: Should remove liquidity");
.unwrap_or((0, 0));
assert_eq!(
total_lp_required - lp_fee_part,
protocol_fee_lp,
Expand All @@ -181,7 +181,7 @@ fn test_swap_exact_in(
[0, expected_protocol_fee_part].to_vec(),
bob(),
)
.expect("swap_received: Should remove liquidity");
.unwrap_or((0, 0));
assert_eq!(
total_lp_required - lp_fee_part,
protocol_fee_lp,
Expand Down
2 changes: 1 addition & 1 deletion amm/traits/stable_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ pub enum StablePoolError {
InvalidTokenId(AccountId),
IdenticalTokenId,
IncorrectAmountsCount,
InvalidAmpCoef,
InsufficientAmounts,
Copy link
Contributor

@woocash2 woocash2 Aug 16, 2024

Choose a reason for hiding this comment

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

If this is used only for 0 amounts, maybe call it ZeroAmounts (or something like that)?

InsufficientLiquidityMinted,
InsufficientLiquidityBurned,
InsufficientOutputAmount,
Expand Down
Loading