pub fn swap_exact_in(… zero_for_one: bool ) -> Result<()> {
…
if zero_for_one {
let numerator: u128 = (reserve_b as u128)
.checked_mul(amount_in as u128)
.ok_or(AmmError::Overflow)?;
let denominator: u128 = (reserve_a as u128)
.checked_add(amount_in as u128)
.ok_or(AmmError::Overflow)?;
if denominator == 0 {
return err!(AmmError::DivisionByZero);
}
let mut amount_out: u64 = numerator.div_floor(&denominator) as u64;
let lp_fees = (amount_out as u128 * 3).div_floor(&1000) as u64;
amount_out = amount_out - lp_fees;
…
} else {
}
}
pub fn swap_exact_out(… zero_for_one: bool ) -> Result<()> {
…
if zero_for_one {
let numerator: u128 = (reserve_a as u128)
.checked_mul(amount_out as u128)
.ok_or(AmmError::Overflow)?;
let denominator: u128 = (reserve_b as u128)
.checked_sub(amount_out as u128)
.ok_or(AmmError::Underflow)?;
require!(denominator > 0, AmmError::DivisionByZero);
let amount_in_no_fee: u64 = numerator.div_floor(&denominator) as u64;
let fee_numerator_u128 = (amount_in_no_fee as u128)
.checked_mul(3)
.ok_or(AmmError::Overflow)?;
let lp_fees: u64 = fee_numerator_u128.div_floor(&1000) as u64;
let amount_in_final = (amount_in_no_fee as u128)
.checked_add(lp_fees as u128)
.ok_or(AmmError::Overflow)? as u64;
…
} else {
}
}
fn simulate_swap_exact_in() {
let reserve_a: u128 = 10_000;
let reserve_b: u128 = 20_000;
let amount_in: u128 = 1_000;
let amount_in_with_fee = amount_in * 997;
let numerator_correct = amount_in_with_fee * reserve_b;
let denominator_correct = (reserve_a * 1_000) + amount_in_with_fee;
let amount_out_correct = (numerator_correct / denominator_correct) as u64;
assert_eq!(amount_out_correct, 1_812);
let numerator_impl = reserve_b * amount_in;
let denominator_impl = reserve_a + amount_in;
let gross_out_impl = (numerator_impl / denominator_impl) as u64;
let lp_fees_impl = ((gross_out_impl as u128 * 3) / 1000) as u64;
let amount_out_impl = gross_out_impl - lp_fees_impl;
println!("Uniswap V2 gives {} vs impl gives {}", amount_out_correct, amount_out_impl);
}