Use u128 for all the math but store in u64 (#711)
* Use u128 for all the math but store in u64 * tests * missing changes * bulds * specific conversion failure * fix tests * use large numbers * Rebase and fix merge issue from new tests Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
This commit is contained in:
parent
7473fa0035
commit
64a362c059
|
@ -626,13 +626,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
source = "git+https://github.com/garious/curve25519-dalek?rev=60efef3553d6bf3d7f3b09b5f97acd54d72529ff#60efef3553d6bf3d7f3b09b5f97acd54d72529ff"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh",
|
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"digest 0.8.1",
|
"digest 0.8.1",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"serde",
|
|
||||||
"subtle 2.2.3",
|
"subtle 2.2.3",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
@ -640,12 +639,13 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/garious/curve25519-dalek?rev=60efef3553d6bf3d7f3b09b5f97acd54d72529ff#60efef3553d6bf3d7f3b09b5f97acd54d72529ff"
|
||||||
checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"borsh",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"digest 0.8.1",
|
"digest 0.8.1",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
"serde",
|
||||||
"subtle 2.2.3",
|
"subtle 2.2.3",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
|
@ -10,10 +10,10 @@ use std::convert::{TryFrom, TryInto};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
/// Initial amount of pool tokens for swap contract, hard-coded to something
|
/// Initial amount of pool tokens for swap contract, hard-coded to something
|
||||||
/// "sensible" given a maximum of u64.
|
/// "sensible" given a maximum of u128.
|
||||||
/// Note that on Ethereum, Uniswap uses the geometric mean of all provided
|
/// Note that on Ethereum, Uniswap uses the geometric mean of all provided
|
||||||
/// input amounts, and Balancer uses 100 * 10 ^ 18.
|
/// input amounts, and Balancer uses 100 * 10 ^ 18.
|
||||||
pub const INITIAL_SWAP_POOL_AMOUNT: u64 = 1_000_000_000;
|
pub const INITIAL_SWAP_POOL_AMOUNT: u128 = 1_000_000_000;
|
||||||
|
|
||||||
/// Curve types supported by the token-swap program.
|
/// Curve types supported by the token-swap program.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -141,20 +141,20 @@ pub trait CurveCalculator: Debug + DynPack {
|
||||||
/// of source token.
|
/// of source token.
|
||||||
fn swap(
|
fn swap(
|
||||||
&self,
|
&self,
|
||||||
source_amount: u64,
|
source_amount: u128,
|
||||||
swap_source_amount: u64,
|
swap_source_amount: u128,
|
||||||
swap_destination_amount: u64,
|
swap_destination_amount: u128,
|
||||||
) -> Option<SwapResult>;
|
) -> Option<SwapResult>;
|
||||||
|
|
||||||
/// Calculate the withdraw fee in pool tokens
|
/// Calculate the withdraw fee in pool tokens
|
||||||
/// Default implementation assumes no fee
|
/// Default implementation assumes no fee
|
||||||
fn owner_withdraw_fee(&self, _pool_tokens: u64) -> Option<u64> {
|
fn owner_withdraw_fee(&self, _pool_tokens: u128) -> Option<u128> {
|
||||||
Some(0)
|
Some(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the trading fee in trading tokens
|
/// Calculate the trading fee in trading tokens
|
||||||
/// Default implementation assumes no fee
|
/// Default implementation assumes no fee
|
||||||
fn trading_fee(&self, _trading_tokens: u64) -> Option<u64> {
|
fn trading_fee(&self, _trading_tokens: u128) -> Option<u128> {
|
||||||
Some(0)
|
Some(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,11 +165,11 @@ pub trait CurveCalculator: Debug + DynPack {
|
||||||
/// value.
|
/// value.
|
||||||
fn owner_fee_to_pool_tokens(
|
fn owner_fee_to_pool_tokens(
|
||||||
&self,
|
&self,
|
||||||
owner_fee: u64,
|
owner_fee: u128,
|
||||||
trading_token_amount: u64,
|
trading_token_amount: u128,
|
||||||
pool_supply: u64,
|
pool_supply: u128,
|
||||||
tokens_in_pool: u64,
|
tokens_in_pool: u128,
|
||||||
) -> Option<u64> {
|
) -> Option<u128> {
|
||||||
// Get the trading fee incurred if the owner fee is swapped for the other side
|
// Get the trading fee incurred if the owner fee is swapped for the other side
|
||||||
let trade_fee = self.trading_fee(owner_fee)?;
|
let trade_fee = self.trading_fee(owner_fee)?;
|
||||||
let owner_fee = owner_fee.checked_sub(trade_fee)?;
|
let owner_fee = owner_fee.checked_sub(trade_fee)?;
|
||||||
|
@ -181,7 +181,7 @@ pub trait CurveCalculator: Debug + DynPack {
|
||||||
|
|
||||||
/// Get the supply for a new pool
|
/// Get the supply for a new pool
|
||||||
/// The default implementation is a Balancer-style fixed initial supply
|
/// The default implementation is a Balancer-style fixed initial supply
|
||||||
fn new_pool_supply(&self) -> u64 {
|
fn new_pool_supply(&self) -> u128 {
|
||||||
INITIAL_SWAP_POOL_AMOUNT
|
INITIAL_SWAP_POOL_AMOUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,10 +191,10 @@ pub trait CurveCalculator: Debug + DynPack {
|
||||||
/// trading tokens correspond to a certain number of pool tokens
|
/// trading tokens correspond to a certain number of pool tokens
|
||||||
fn pool_tokens_to_trading_tokens(
|
fn pool_tokens_to_trading_tokens(
|
||||||
&self,
|
&self,
|
||||||
pool_tokens: u64,
|
pool_tokens: u128,
|
||||||
pool_token_supply: u64,
|
pool_token_supply: u128,
|
||||||
total_trading_tokens: u64,
|
total_trading_tokens: u128,
|
||||||
) -> Option<u64> {
|
) -> Option<u128> {
|
||||||
pool_tokens
|
pool_tokens
|
||||||
.checked_mul(total_trading_tokens)?
|
.checked_mul(total_trading_tokens)?
|
||||||
.checked_div(pool_token_supply)
|
.checked_div(pool_token_supply)
|
||||||
|
@ -205,19 +205,19 @@ pub trait CurveCalculator: Debug + DynPack {
|
||||||
/// Encodes all results of swapping from a source token to a destination token
|
/// Encodes all results of swapping from a source token to a destination token
|
||||||
pub struct SwapResult {
|
pub struct SwapResult {
|
||||||
/// New amount of source token
|
/// New amount of source token
|
||||||
pub new_source_amount: u64,
|
pub new_source_amount: u128,
|
||||||
/// New amount of destination token
|
/// New amount of destination token
|
||||||
pub new_destination_amount: u64,
|
pub new_destination_amount: u128,
|
||||||
/// Amount of destination token swapped
|
/// Amount of destination token swapped
|
||||||
pub amount_swapped: u64,
|
pub amount_swapped: u128,
|
||||||
/// Amount of source tokens going to pool holders
|
/// Amount of source tokens going to pool holders
|
||||||
pub trade_fee: u64,
|
pub trade_fee: u128,
|
||||||
/// Amount of source tokens going to owner
|
/// Amount of source tokens going to owner
|
||||||
pub owner_fee: u64,
|
pub owner_fee: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function for mapping to SwapError::CalculationFailure
|
/// Helper function for mapping to SwapError::CalculationFailure
|
||||||
fn map_zero_to_none(x: u64) -> Option<u64> {
|
fn map_zero_to_none(x: u128) -> Option<u128> {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -242,7 +242,7 @@ pub struct FlatCurve {
|
||||||
pub owner_withdraw_fee_denominator: u64,
|
pub owner_withdraw_fee_denominator: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_fee(token_amount: u64, fee_numerator: u64, fee_denominator: u64) -> Option<u64> {
|
fn calculate_fee(token_amount: u128, fee_numerator: u128, fee_denominator: u128) -> Option<u128> {
|
||||||
if fee_numerator == 0 {
|
if fee_numerator == 0 {
|
||||||
Some(0)
|
Some(0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -261,20 +261,20 @@ impl CurveCalculator for FlatCurve {
|
||||||
/// Flat curve swap always returns 1:1 (minus fee)
|
/// Flat curve swap always returns 1:1 (minus fee)
|
||||||
fn swap(
|
fn swap(
|
||||||
&self,
|
&self,
|
||||||
source_amount: u64,
|
source_amount: u128,
|
||||||
swap_source_amount: u64,
|
swap_source_amount: u128,
|
||||||
swap_destination_amount: u64,
|
swap_destination_amount: u128,
|
||||||
) -> Option<SwapResult> {
|
) -> Option<SwapResult> {
|
||||||
// debit the fee to calculate the amount swapped
|
// debit the fee to calculate the amount swapped
|
||||||
let trade_fee = calculate_fee(
|
let trade_fee = calculate_fee(
|
||||||
source_amount,
|
source_amount,
|
||||||
self.trade_fee_numerator,
|
u128::try_from(self.trade_fee_numerator).ok()?,
|
||||||
self.trade_fee_denominator,
|
u128::try_from(self.trade_fee_denominator).ok()?,
|
||||||
)?;
|
)?;
|
||||||
let owner_fee = calculate_fee(
|
let owner_fee = calculate_fee(
|
||||||
source_amount,
|
source_amount,
|
||||||
self.owner_trade_fee_numerator,
|
u128::try_from(self.owner_trade_fee_numerator).ok()?,
|
||||||
self.owner_trade_fee_denominator,
|
u128::try_from(self.owner_trade_fee_denominator).ok()?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let amount_swapped = source_amount
|
let amount_swapped = source_amount
|
||||||
|
@ -294,11 +294,11 @@ impl CurveCalculator for FlatCurve {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the withdraw fee in pool tokens
|
/// Calculate the withdraw fee in pool tokens
|
||||||
fn owner_withdraw_fee(&self, pool_tokens: u64) -> Option<u64> {
|
fn owner_withdraw_fee(&self, pool_tokens: u128) -> Option<u128> {
|
||||||
calculate_fee(
|
calculate_fee(
|
||||||
pool_tokens,
|
pool_tokens,
|
||||||
self.owner_withdraw_fee_numerator,
|
u128::try_from(self.owner_withdraw_fee_numerator).ok()?,
|
||||||
self.owner_withdraw_fee_denominator,
|
u128::try_from(self.owner_withdraw_fee_denominator).ok()?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,16 +379,16 @@ impl CurveCalculator for ConstantProductCurve {
|
||||||
/// Constant product swap ensures x * y = constant
|
/// Constant product swap ensures x * y = constant
|
||||||
fn swap(
|
fn swap(
|
||||||
&self,
|
&self,
|
||||||
source_amount: u64,
|
source_amount: u128,
|
||||||
swap_source_amount: u64,
|
swap_source_amount: u128,
|
||||||
swap_destination_amount: u64,
|
swap_destination_amount: u128,
|
||||||
) -> Option<SwapResult> {
|
) -> Option<SwapResult> {
|
||||||
// debit the fee to calculate the amount swapped
|
// debit the fee to calculate the amount swapped
|
||||||
let trade_fee = self.trading_fee(source_amount)?;
|
let trade_fee = self.trading_fee(source_amount)?;
|
||||||
let owner_fee = calculate_fee(
|
let owner_fee = calculate_fee(
|
||||||
source_amount,
|
source_amount,
|
||||||
self.owner_trade_fee_numerator,
|
u128::try_from(self.owner_trade_fee_numerator).ok()?,
|
||||||
self.owner_trade_fee_denominator,
|
u128::try_from(self.owner_trade_fee_denominator).ok()?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let invariant = swap_source_amount.checked_mul(swap_destination_amount)?;
|
let invariant = swap_source_amount.checked_mul(swap_destination_amount)?;
|
||||||
|
@ -412,20 +412,20 @@ impl CurveCalculator for ConstantProductCurve {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the withdraw fee in pool tokens
|
/// Calculate the withdraw fee in pool tokens
|
||||||
fn owner_withdraw_fee(&self, pool_tokens: u64) -> Option<u64> {
|
fn owner_withdraw_fee(&self, pool_tokens: u128) -> Option<u128> {
|
||||||
calculate_fee(
|
calculate_fee(
|
||||||
pool_tokens,
|
pool_tokens,
|
||||||
self.owner_withdraw_fee_numerator,
|
u128::try_from(self.owner_withdraw_fee_numerator).ok()?,
|
||||||
self.owner_withdraw_fee_denominator,
|
u128::try_from(self.owner_withdraw_fee_denominator).ok()?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the trading fee in trading tokens
|
/// Calculate the trading fee in trading tokens
|
||||||
fn trading_fee(&self, trading_tokens: u64) -> Option<u64> {
|
fn trading_fee(&self, trading_tokens: u128) -> Option<u128> {
|
||||||
calculate_fee(
|
calculate_fee(
|
||||||
trading_tokens,
|
trading_tokens,
|
||||||
self.trade_fee_numerator,
|
u128::try_from(self.trade_fee_numerator).ok()?,
|
||||||
self.trade_fee_denominator,
|
u128::try_from(self.trade_fee_denominator).ok()?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,7 +508,7 @@ mod tests {
|
||||||
assert_eq!(calculator.new_pool_supply(), INITIAL_SWAP_POOL_AMOUNT);
|
assert_eq!(calculator.new_pool_supply(), INITIAL_SWAP_POOL_AMOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pool_token_rate(token_a: u64, deposit: u64, supply: u64, expected: Option<u64>) {
|
fn check_pool_token_rate(token_a: u128, deposit: u128, supply: u128, expected: Option<u128>) {
|
||||||
let trade_fee_numerator = 0;
|
let trade_fee_numerator = 0;
|
||||||
let trade_fee_denominator = 1;
|
let trade_fee_denominator = 1;
|
||||||
let owner_trade_fee_numerator = 0;
|
let owner_trade_fee_numerator = 0;
|
||||||
|
@ -535,21 +535,21 @@ mod tests {
|
||||||
check_pool_token_rate(10, 5, 10, Some(5));
|
check_pool_token_rate(10, 5, 10, Some(5));
|
||||||
check_pool_token_rate(5, 5, 10, Some(2));
|
check_pool_token_rate(5, 5, 10, Some(2));
|
||||||
check_pool_token_rate(5, 5, 10, Some(2));
|
check_pool_token_rate(5, 5, 10, Some(2));
|
||||||
check_pool_token_rate(u64::MAX, 5, 10, None);
|
check_pool_token_rate(u128::MAX, 5, 10, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn constant_product_swap_calculation_trade_fee() {
|
fn constant_product_swap_calculation_trade_fee() {
|
||||||
// calculation on https://github.com/solana-labs/solana-program-library/issues/341
|
// calculation on https://github.com/solana-labs/solana-program-library/issues/341
|
||||||
let swap_source_amount: u64 = 1000;
|
let swap_source_amount = 1000;
|
||||||
let swap_destination_amount: u64 = 50000;
|
let swap_destination_amount = 50000;
|
||||||
let trade_fee_numerator: u64 = 1;
|
let trade_fee_numerator = 1;
|
||||||
let trade_fee_denominator: u64 = 100;
|
let trade_fee_denominator = 100;
|
||||||
let owner_trade_fee_numerator: u64 = 0;
|
let owner_trade_fee_numerator = 0;
|
||||||
let owner_trade_fee_denominator: u64 = 0;
|
let owner_trade_fee_denominator = 0;
|
||||||
let owner_withdraw_fee_numerator: u64 = 0;
|
let owner_withdraw_fee_numerator = 0;
|
||||||
let owner_withdraw_fee_denominator: u64 = 0;
|
let owner_withdraw_fee_denominator = 0;
|
||||||
let source_amount: u64 = 100;
|
let source_amount = 100;
|
||||||
let curve = ConstantProductCurve {
|
let curve = ConstantProductCurve {
|
||||||
trade_fee_numerator,
|
trade_fee_numerator,
|
||||||
trade_fee_denominator,
|
trade_fee_denominator,
|
||||||
|
@ -571,15 +571,15 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn constant_product_swap_calculation_owner_fee() {
|
fn constant_product_swap_calculation_owner_fee() {
|
||||||
// calculation on https://github.com/solana-labs/solana-program-library/issues/341
|
// calculation on https://github.com/solana-labs/solana-program-library/issues/341
|
||||||
let swap_source_amount: u64 = 1000;
|
let swap_source_amount = 1000;
|
||||||
let swap_destination_amount: u64 = 50000;
|
let swap_destination_amount = 50000;
|
||||||
let trade_fee_numerator: u64 = 0;
|
let trade_fee_numerator = 0;
|
||||||
let trade_fee_denominator: u64 = 0;
|
let trade_fee_denominator = 0;
|
||||||
let owner_trade_fee_numerator: u64 = 1;
|
let owner_trade_fee_numerator = 1;
|
||||||
let owner_trade_fee_denominator: u64 = 100;
|
let owner_trade_fee_denominator = 100;
|
||||||
let owner_withdraw_fee_numerator: u64 = 0;
|
let owner_withdraw_fee_numerator = 0;
|
||||||
let owner_withdraw_fee_denominator: u64 = 0;
|
let owner_withdraw_fee_denominator = 0;
|
||||||
let source_amount: u64 = 100;
|
let source_amount: u128 = 100;
|
||||||
let curve = ConstantProductCurve {
|
let curve = ConstantProductCurve {
|
||||||
trade_fee_numerator,
|
trade_fee_numerator,
|
||||||
trade_fee_denominator,
|
trade_fee_denominator,
|
||||||
|
@ -600,9 +600,9 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn constant_product_swap_no_fee() {
|
fn constant_product_swap_no_fee() {
|
||||||
let swap_source_amount: u64 = 1000;
|
let swap_source_amount: u128 = 1000;
|
||||||
let swap_destination_amount: u64 = 50000;
|
let swap_destination_amount: u128 = 50000;
|
||||||
let source_amount: u64 = 100;
|
let source_amount: u128 = 100;
|
||||||
let curve = ConstantProductCurve::default();
|
let curve = ConstantProductCurve::default();
|
||||||
let result = curve
|
let result = curve
|
||||||
.swap(source_amount, swap_source_amount, swap_destination_amount)
|
.swap(source_amount, swap_source_amount, swap_destination_amount)
|
||||||
|
@ -614,15 +614,15 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flat_swap_calculation() {
|
fn flat_swap_calculation() {
|
||||||
let swap_source_amount: u64 = 1000;
|
let swap_source_amount = 1000;
|
||||||
let swap_destination_amount: u64 = 50000;
|
let swap_destination_amount = 50000;
|
||||||
let trade_fee_numerator: u64 = 1;
|
let trade_fee_numerator = 1;
|
||||||
let trade_fee_denominator: u64 = 100;
|
let trade_fee_denominator = 100;
|
||||||
let owner_trade_fee_numerator: u64 = 2;
|
let owner_trade_fee_numerator = 2;
|
||||||
let owner_trade_fee_denominator: u64 = 100;
|
let owner_trade_fee_denominator = 100;
|
||||||
let owner_withdraw_fee_numerator: u64 = 2;
|
let owner_withdraw_fee_numerator = 2;
|
||||||
let owner_withdraw_fee_denominator: u64 = 100;
|
let owner_withdraw_fee_denominator = 100;
|
||||||
let source_amount: u64 = 100;
|
let source_amount: u128 = 100;
|
||||||
let curve = FlatCurve {
|
let curve = FlatCurve {
|
||||||
trade_fee_numerator,
|
trade_fee_numerator,
|
||||||
trade_fee_denominator,
|
trade_fee_denominator,
|
||||||
|
|
|
@ -73,6 +73,9 @@ pub enum SwapError {
|
||||||
/// The fee calculation failed due to overflow, underflow, or unexpected 0
|
/// The fee calculation failed due to overflow, underflow, or unexpected 0
|
||||||
#[error("Fee calculation failed due to overflow, underflow, or unexpected 0")]
|
#[error("Fee calculation failed due to overflow, underflow, or unexpected 0")]
|
||||||
FeeCalculationFailure,
|
FeeCalculationFailure,
|
||||||
|
/// ConversionFailure
|
||||||
|
#[error("Conversion to u64 failed with an overflow or underflow")]
|
||||||
|
ConversionFailure,
|
||||||
}
|
}
|
||||||
impl From<SwapError> for ProgramError {
|
impl From<SwapError> for ProgramError {
|
||||||
fn from(e: SwapError) -> Self {
|
fn from(e: SwapError) -> Self {
|
||||||
|
|
|
@ -13,6 +13,7 @@ use solana_program::{
|
||||||
program_pack::Pack,
|
program_pack::Pack,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
};
|
};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
/// Hardcode the number of token types in a pool, used to calculate the
|
/// Hardcode the number of token types in a pool, used to calculate the
|
||||||
/// equivalent pool tokens for the owner trading fee.
|
/// equivalent pool tokens for the owner trading fee.
|
||||||
|
@ -211,7 +212,7 @@ impl Processor {
|
||||||
destination_info.clone(),
|
destination_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
nonce,
|
nonce,
|
||||||
initial_amount,
|
to_u64(initial_amount)?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let obj = SwapInfo {
|
let obj = SwapInfo {
|
||||||
|
@ -286,9 +287,13 @@ impl Processor {
|
||||||
let result = token_swap
|
let result = token_swap
|
||||||
.swap_curve
|
.swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.swap(amount_in, source_account.amount, dest_account.amount)
|
.swap(
|
||||||
|
to_u128(amount_in)?,
|
||||||
|
to_u128(source_account.amount)?,
|
||||||
|
to_u128(dest_account.amount)?,
|
||||||
|
)
|
||||||
.ok_or(SwapError::ZeroTradingTokens)?;
|
.ok_or(SwapError::ZeroTradingTokens)?;
|
||||||
if result.amount_swapped < minimum_amount_out {
|
if result.amount_swapped < to_u128(minimum_amount_out)? {
|
||||||
return Err(SwapError::ExceededSlippage.into());
|
return Err(SwapError::ExceededSlippage.into());
|
||||||
}
|
}
|
||||||
Self::token_transfer(
|
Self::token_transfer(
|
||||||
|
@ -307,7 +312,7 @@ impl Processor {
|
||||||
destination_info.clone(),
|
destination_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
result.amount_swapped,
|
to_u64(result.amount_swapped)?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// mint pool tokens equivalent to the owner fee
|
// mint pool tokens equivalent to the owner fee
|
||||||
|
@ -317,9 +322,9 @@ impl Processor {
|
||||||
.calculator
|
.calculator
|
||||||
.owner_fee_to_pool_tokens(
|
.owner_fee_to_pool_tokens(
|
||||||
result.owner_fee,
|
result.owner_fee,
|
||||||
source_account.amount,
|
to_u128(source_account.amount)?,
|
||||||
pool_mint.supply,
|
to_u128(pool_mint.supply)?,
|
||||||
TOKENS_IN_POOL,
|
to_u128(TOKENS_IN_POOL)?,
|
||||||
)
|
)
|
||||||
.ok_or(SwapError::FeeCalculationFailure)?;
|
.ok_or(SwapError::FeeCalculationFailure)?;
|
||||||
if pool_token_amount > 0 {
|
if pool_token_amount > 0 {
|
||||||
|
@ -330,7 +335,7 @@ impl Processor {
|
||||||
pool_fee_account_info.clone(),
|
pool_fee_account_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
pool_token_amount,
|
to_u64(pool_token_amount)?,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -378,19 +383,29 @@ impl Processor {
|
||||||
let token_a = Self::unpack_token_account(&token_a_info.data.borrow())?;
|
let token_a = Self::unpack_token_account(&token_a_info.data.borrow())?;
|
||||||
let token_b = Self::unpack_token_account(&token_b_info.data.borrow())?;
|
let token_b = Self::unpack_token_account(&token_b_info.data.borrow())?;
|
||||||
let pool_mint = Self::unpack_mint(&pool_mint_info.data.borrow())?;
|
let pool_mint = Self::unpack_mint(&pool_mint_info.data.borrow())?;
|
||||||
|
let pool_token_amount = to_u128(pool_token_amount)?;
|
||||||
|
let pool_mint_supply = to_u128(pool_mint.supply)?;
|
||||||
|
|
||||||
let calculator = token_swap.swap_curve.calculator;
|
let calculator = token_swap.swap_curve.calculator;
|
||||||
|
|
||||||
let a_amount = calculator
|
let a_amount = calculator
|
||||||
.pool_tokens_to_trading_tokens(pool_token_amount, pool_mint.supply, token_a.amount)
|
.pool_tokens_to_trading_tokens(
|
||||||
|
pool_token_amount,
|
||||||
|
pool_mint_supply,
|
||||||
|
to_u128(token_a.amount)?,
|
||||||
|
)
|
||||||
.ok_or(SwapError::ZeroTradingTokens)?;
|
.ok_or(SwapError::ZeroTradingTokens)?;
|
||||||
if a_amount > maximum_token_a_amount {
|
if a_amount > to_u128(maximum_token_a_amount)? {
|
||||||
return Err(SwapError::ExceededSlippage.into());
|
return Err(SwapError::ExceededSlippage.into());
|
||||||
}
|
}
|
||||||
let b_amount = calculator
|
let b_amount = calculator
|
||||||
.pool_tokens_to_trading_tokens(pool_token_amount, pool_mint.supply, token_b.amount)
|
.pool_tokens_to_trading_tokens(
|
||||||
|
pool_token_amount,
|
||||||
|
pool_mint_supply,
|
||||||
|
to_u128(token_b.amount)?,
|
||||||
|
)
|
||||||
.ok_or(SwapError::ZeroTradingTokens)?;
|
.ok_or(SwapError::ZeroTradingTokens)?;
|
||||||
if b_amount > maximum_token_b_amount {
|
if b_amount > to_u128(maximum_token_b_amount)? {
|
||||||
return Err(SwapError::ExceededSlippage.into());
|
return Err(SwapError::ExceededSlippage.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +416,7 @@ impl Processor {
|
||||||
token_a_info.clone(),
|
token_a_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
a_amount,
|
to_u64(a_amount)?,
|
||||||
)?;
|
)?;
|
||||||
Self::token_transfer(
|
Self::token_transfer(
|
||||||
swap_info.key,
|
swap_info.key,
|
||||||
|
@ -410,7 +425,7 @@ impl Processor {
|
||||||
token_b_info.clone(),
|
token_b_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
b_amount,
|
to_u64(b_amount)?,
|
||||||
)?;
|
)?;
|
||||||
Self::token_mint_to(
|
Self::token_mint_to(
|
||||||
swap_info.key,
|
swap_info.key,
|
||||||
|
@ -419,7 +434,7 @@ impl Processor {
|
||||||
dest_info.clone(),
|
dest_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
pool_token_amount,
|
to_u64(pool_token_amount)?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -474,27 +489,36 @@ impl Processor {
|
||||||
|
|
||||||
let calculator = token_swap.swap_curve.calculator;
|
let calculator = token_swap.swap_curve.calculator;
|
||||||
|
|
||||||
let withdraw_fee = if *pool_fee_account_info.key == *source_info.key {
|
let withdraw_fee: u128 = if *pool_fee_account_info.key == *source_info.key {
|
||||||
// withdrawing from the fee account, don't assess withdraw fee
|
// withdrawing from the fee account, don't assess withdraw fee
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
calculator
|
calculator
|
||||||
.owner_withdraw_fee(pool_token_amount)
|
.owner_withdraw_fee(to_u128(pool_token_amount)?)
|
||||||
.ok_or(SwapError::FeeCalculationFailure)?
|
.ok_or(SwapError::FeeCalculationFailure)?
|
||||||
};
|
};
|
||||||
let pool_token_amount = pool_token_amount
|
let pool_token_amount = to_u128(pool_token_amount)?
|
||||||
.checked_sub(withdraw_fee)
|
.checked_sub(withdraw_fee)
|
||||||
.ok_or(SwapError::CalculationFailure)?;
|
.ok_or(SwapError::CalculationFailure)?;
|
||||||
|
|
||||||
let a_amount = calculator
|
let a_amount = calculator
|
||||||
.pool_tokens_to_trading_tokens(pool_token_amount, pool_mint.supply, token_a.amount)
|
.pool_tokens_to_trading_tokens(
|
||||||
|
pool_token_amount,
|
||||||
|
to_u128(pool_mint.supply)?,
|
||||||
|
to_u128(token_a.amount)?,
|
||||||
|
)
|
||||||
.ok_or(SwapError::ZeroTradingTokens)?;
|
.ok_or(SwapError::ZeroTradingTokens)?;
|
||||||
if a_amount < minimum_token_a_amount {
|
if a_amount < to_u128(minimum_token_a_amount)? {
|
||||||
return Err(SwapError::ExceededSlippage.into());
|
return Err(SwapError::ExceededSlippage.into());
|
||||||
}
|
}
|
||||||
let b_amount = calculator
|
let b_amount = calculator
|
||||||
.pool_tokens_to_trading_tokens(pool_token_amount, pool_mint.supply, token_b.amount)
|
.pool_tokens_to_trading_tokens(
|
||||||
|
pool_token_amount,
|
||||||
|
to_u128(pool_mint.supply)?,
|
||||||
|
to_u128(token_b.amount)?,
|
||||||
|
)
|
||||||
.ok_or(SwapError::ZeroTradingTokens)?;
|
.ok_or(SwapError::ZeroTradingTokens)?;
|
||||||
|
let b_amount = to_u64(b_amount)?;
|
||||||
if b_amount < minimum_token_b_amount {
|
if b_amount < minimum_token_b_amount {
|
||||||
return Err(SwapError::ExceededSlippage.into());
|
return Err(SwapError::ExceededSlippage.into());
|
||||||
}
|
}
|
||||||
|
@ -506,7 +530,7 @@ impl Processor {
|
||||||
dest_token_a_info.clone(),
|
dest_token_a_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
a_amount,
|
to_u64(a_amount)?,
|
||||||
)?;
|
)?;
|
||||||
Self::token_transfer(
|
Self::token_transfer(
|
||||||
swap_info.key,
|
swap_info.key,
|
||||||
|
@ -525,7 +549,7 @@ impl Processor {
|
||||||
pool_fee_account_info.clone(),
|
pool_fee_account_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
withdraw_fee,
|
to_u64(withdraw_fee)?,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Self::token_burn(
|
Self::token_burn(
|
||||||
|
@ -535,7 +559,7 @@ impl Processor {
|
||||||
pool_mint_info.clone(),
|
pool_mint_info.clone(),
|
||||||
authority_info.clone(),
|
authority_info.clone(),
|
||||||
token_swap.nonce,
|
token_swap.nonce,
|
||||||
pool_token_amount,
|
to_u64(pool_token_amount)?,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -637,10 +661,19 @@ impl PrintProgramError for SwapError {
|
||||||
SwapError::FeeCalculationFailure => info!(
|
SwapError::FeeCalculationFailure => info!(
|
||||||
"Error: The fee calculation failed due to overflow, underflow, or unexpected 0"
|
"Error: The fee calculation failed due to overflow, underflow, or unexpected 0"
|
||||||
),
|
),
|
||||||
|
SwapError::ConversionFailure => info!("Error: Conversion to or from u64 failed."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_u128(val: u64) -> Result<u128, SwapError> {
|
||||||
|
val.try_into().map_err(|_| SwapError::ConversionFailure)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_u64(val: u128) -> Result<u64, SwapError> {
|
||||||
|
val.try_into().map_err(|_| SwapError::ConversionFailure)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -1858,7 +1891,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -1893,7 +1926,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -1927,7 +1960,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -1960,7 +1993,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -1987,7 +2020,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2022,7 +2055,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&wrong_token_key,
|
&wrong_token_key,
|
||||||
&mut wrong_token_account,
|
&mut wrong_token_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2053,7 +2086,7 @@ mod tests {
|
||||||
&accounts.token_b_key,
|
&accounts.token_b_key,
|
||||||
&accounts.pool_mint_key,
|
&accounts.pool_mint_key,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2098,7 +2131,7 @@ mod tests {
|
||||||
&accounts.token_b_key,
|
&accounts.token_b_key,
|
||||||
&accounts.pool_mint_key,
|
&accounts.pool_mint_key,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2146,7 +2179,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2172,7 +2205,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2209,7 +2242,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2267,7 +2300,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a / 10,
|
deposit_a / 10,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2283,7 +2316,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b / 10,
|
deposit_b / 10,
|
||||||
)
|
)
|
||||||
|
@ -2315,7 +2348,7 @@ mod tests {
|
||||||
&mut swap_token_b_account,
|
&mut swap_token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2340,7 +2373,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&pool_key,
|
&pool_key,
|
||||||
&mut pool_account,
|
&mut pool_account,
|
||||||
pool_amount,
|
pool_amount.try_into().unwrap(),
|
||||||
deposit_a,
|
deposit_a,
|
||||||
deposit_b,
|
deposit_b,
|
||||||
)
|
)
|
||||||
|
@ -2422,7 +2455,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2457,7 +2490,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2479,7 +2512,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
withdraw_amount / 2,
|
to_u64(withdraw_amount).unwrap() / 2u64,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(TokenError::InsufficientFunds.into()),
|
Err(TokenError::InsufficientFunds.into()),
|
||||||
|
@ -2491,7 +2524,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount / 2,
|
minimum_a_amount / 2,
|
||||||
minimum_b_amount / 2,
|
minimum_b_amount / 2,
|
||||||
)
|
)
|
||||||
|
@ -2512,7 +2545,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(TokenError::MintMismatch.into()),
|
Err(TokenError::MintMismatch.into()),
|
||||||
|
@ -2524,7 +2557,7 @@ mod tests {
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
&token_a_key,
|
&token_a_key,
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2545,7 +2578,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
let (
|
let (
|
||||||
wrong_token_a_key,
|
wrong_token_a_key,
|
||||||
|
@ -2557,9 +2590,9 @@ mod tests {
|
||||||
) = accounts.setup_token_accounts(
|
) = accounts.setup_token_accounts(
|
||||||
&user_key,
|
&user_key,
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
initial_b,
|
initial_b,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(TokenError::MintMismatch.into()),
|
Err(TokenError::MintMismatch.into()),
|
||||||
|
@ -2571,7 +2604,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2592,7 +2625,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
let (
|
let (
|
||||||
_token_a_key,
|
_token_a_key,
|
||||||
|
@ -2606,7 +2639,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
let old_pool_fee_account = accounts.pool_fee_account;
|
let old_pool_fee_account = accounts.pool_fee_account;
|
||||||
let old_pool_fee_key = accounts.pool_fee_key;
|
let old_pool_fee_key = accounts.pool_fee_key;
|
||||||
|
@ -2622,7 +2655,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
),
|
),
|
||||||
|
@ -2640,7 +2673,13 @@ mod tests {
|
||||||
mut token_b_account,
|
mut token_b_account,
|
||||||
pool_key,
|
pool_key,
|
||||||
mut pool_account,
|
mut pool_account,
|
||||||
) = accounts.setup_token_accounts(&user_key, &withdrawer_key, 0, 0, withdraw_amount);
|
) = accounts.setup_token_accounts(
|
||||||
|
&user_key,
|
||||||
|
&withdrawer_key,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
withdraw_amount.try_into().unwrap(),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(TokenError::OwnerMismatch.into()),
|
Err(TokenError::OwnerMismatch.into()),
|
||||||
do_process_instruction(
|
do_process_instruction(
|
||||||
|
@ -2656,7 +2695,7 @@ mod tests {
|
||||||
&accounts.token_b_key,
|
&accounts.token_b_key,
|
||||||
&token_a_key,
|
&token_a_key,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2691,7 +2730,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
let wrong_key = Pubkey::new_unique();
|
let wrong_key = Pubkey::new_unique();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2709,7 +2748,7 @@ mod tests {
|
||||||
&accounts.token_b_key,
|
&accounts.token_b_key,
|
||||||
&token_a_key,
|
&token_a_key,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2744,7 +2783,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
initial_pool,
|
initial_pool.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let old_a_key = accounts.token_a_key;
|
let old_a_key = accounts.token_a_key;
|
||||||
|
@ -2764,7 +2803,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2790,7 +2829,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2814,7 +2853,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
initial_pool,
|
initial_pool.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
let (pool_mint_key, pool_mint_account) =
|
let (pool_mint_key, pool_mint_account) =
|
||||||
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key, None);
|
create_mint(&TOKEN_PROGRAM_ID, &accounts.authority_key, None);
|
||||||
|
@ -2833,7 +2872,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2857,7 +2896,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
initial_pool,
|
initial_pool.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(SwapError::ZeroTradingTokens.into()),
|
Err(SwapError::ZeroTradingTokens.into()),
|
||||||
|
@ -2890,7 +2929,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
initial_pool,
|
initial_pool.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
// minimum A amount out too high
|
// minimum A amount out too high
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2903,7 +2942,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount * 10,
|
minimum_a_amount * 10,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2919,7 +2958,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount * 10,
|
minimum_b_amount * 10,
|
||||||
)
|
)
|
||||||
|
@ -2940,7 +2979,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
initial_pool,
|
initial_pool.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
let swap_token_a_key = accounts.token_a_key;
|
let swap_token_a_key = accounts.token_a_key;
|
||||||
let mut swap_token_a_account = accounts.get_token_account(&swap_token_a_key).clone();
|
let mut swap_token_a_account = accounts.get_token_account(&swap_token_a_key).clone();
|
||||||
|
@ -2954,7 +2993,7 @@ mod tests {
|
||||||
&mut swap_token_a_account,
|
&mut swap_token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2971,7 +3010,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&swap_token_b_key,
|
&swap_token_b_key,
|
||||||
&mut swap_token_b_account,
|
&mut swap_token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -2992,7 +3031,7 @@ mod tests {
|
||||||
&withdrawer_key,
|
&withdrawer_key,
|
||||||
initial_a,
|
initial_a,
|
||||||
initial_b,
|
initial_b,
|
||||||
initial_pool,
|
initial_pool.try_into().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
accounts
|
accounts
|
||||||
|
@ -3004,7 +3043,7 @@ mod tests {
|
||||||
&mut token_a_account,
|
&mut token_a_account,
|
||||||
&token_b_key,
|
&token_b_key,
|
||||||
&mut token_b_account,
|
&mut token_b_account,
|
||||||
withdraw_amount,
|
withdraw_amount.try_into().unwrap(),
|
||||||
minimum_a_amount,
|
minimum_a_amount,
|
||||||
minimum_b_amount,
|
minimum_b_amount,
|
||||||
)
|
)
|
||||||
|
@ -3025,30 +3064,39 @@ mod tests {
|
||||||
.calculator
|
.calculator
|
||||||
.pool_tokens_to_trading_tokens(
|
.pool_tokens_to_trading_tokens(
|
||||||
withdraw_amount - withdraw_fee,
|
withdraw_amount - withdraw_fee,
|
||||||
pool_mint.supply,
|
pool_mint.supply.try_into().unwrap(),
|
||||||
swap_token_a.amount,
|
swap_token_a.amount.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(swap_token_a.amount, token_a_amount - withdrawn_a);
|
assert_eq!(
|
||||||
|
swap_token_a.amount,
|
||||||
|
token_a_amount - to_u64(withdrawn_a).unwrap()
|
||||||
|
);
|
||||||
let withdrawn_b = accounts
|
let withdrawn_b = accounts
|
||||||
.swap_curve
|
.swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.pool_tokens_to_trading_tokens(
|
.pool_tokens_to_trading_tokens(
|
||||||
withdraw_amount - withdraw_fee,
|
withdraw_amount - withdraw_fee,
|
||||||
pool_mint.supply,
|
pool_mint.supply.try_into().unwrap(),
|
||||||
swap_token_b.amount,
|
swap_token_b.amount.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(swap_token_b.amount, token_b_amount - withdrawn_b);
|
assert_eq!(
|
||||||
|
swap_token_b.amount,
|
||||||
|
token_b_amount - to_u64(withdrawn_b).unwrap()
|
||||||
|
);
|
||||||
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
||||||
assert_eq!(token_a.amount, initial_a + withdrawn_a);
|
assert_eq!(token_a.amount, initial_a + to_u64(withdrawn_a).unwrap());
|
||||||
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
||||||
assert_eq!(token_b.amount, initial_b + withdrawn_b);
|
assert_eq!(token_b.amount, initial_b + to_u64(withdrawn_b).unwrap());
|
||||||
let pool_account = Processor::unpack_token_account(&pool_account.data).unwrap();
|
let pool_account = Processor::unpack_token_account(&pool_account.data).unwrap();
|
||||||
assert_eq!(pool_account.amount, initial_pool - withdraw_amount);
|
assert_eq!(
|
||||||
|
pool_account.amount,
|
||||||
|
to_u64(initial_pool - withdraw_amount).unwrap()
|
||||||
|
);
|
||||||
let fee_account =
|
let fee_account =
|
||||||
Processor::unpack_token_account(&accounts.pool_fee_account.data).unwrap();
|
Processor::unpack_token_account(&accounts.pool_fee_account.data).unwrap();
|
||||||
assert_eq!(fee_account.amount, withdraw_fee);
|
assert_eq!(fee_account.amount, withdraw_fee.try_into().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// correct withdrawal from fee account
|
// correct withdrawal from fee account
|
||||||
|
@ -3091,32 +3139,32 @@ mod tests {
|
||||||
.swap_curve
|
.swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.pool_tokens_to_trading_tokens(
|
.pool_tokens_to_trading_tokens(
|
||||||
pool_fee_amount,
|
pool_fee_amount.try_into().unwrap(),
|
||||||
pool_mint.supply,
|
pool_mint.supply.try_into().unwrap(),
|
||||||
swap_token_a.amount,
|
swap_token_a.amount.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
||||||
assert_eq!(token_a.amount, withdrawn_a);
|
assert_eq!(token_a.amount, withdrawn_a.try_into().unwrap());
|
||||||
let withdrawn_b = accounts
|
let withdrawn_b = accounts
|
||||||
.swap_curve
|
.swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.pool_tokens_to_trading_tokens(
|
.pool_tokens_to_trading_tokens(
|
||||||
pool_fee_amount,
|
pool_fee_amount.try_into().unwrap(),
|
||||||
pool_mint.supply,
|
pool_mint.supply.try_into().unwrap(),
|
||||||
swap_token_b.amount,
|
swap_token_b.amount.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
||||||
assert_eq!(token_b.amount, withdrawn_b);
|
assert_eq!(token_b.amount, withdrawn_b.try_into().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_valid_swap_curve(curve_type: CurveType, calculator: Box<dyn CurveCalculator>) {
|
fn check_valid_swap_curve(curve_type: CurveType, calculator: Box<dyn CurveCalculator>) {
|
||||||
let user_key = Pubkey::new_unique();
|
let user_key = Pubkey::new_unique();
|
||||||
let swapper_key = Pubkey::new_unique();
|
let swapper_key = Pubkey::new_unique();
|
||||||
let token_a_amount = 1000;
|
let token_a_amount = 10_000_000_000u64;
|
||||||
let token_b_amount = 5000;
|
let token_b_amount = 50_000_000_000u64;
|
||||||
|
|
||||||
let swap_curve = SwapCurve {
|
let swap_curve = SwapCurve {
|
||||||
curve_type,
|
curve_type,
|
||||||
|
@ -3165,32 +3213,45 @@ mod tests {
|
||||||
|
|
||||||
let results = swap_curve
|
let results = swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.swap(a_to_b_amount, token_a_amount, token_b_amount)
|
.swap(
|
||||||
|
a_to_b_amount.try_into().unwrap(),
|
||||||
|
token_a_amount.try_into().unwrap(),
|
||||||
|
token_b_amount.try_into().unwrap(),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let swap_token_a = Processor::unpack_token_account(&accounts.token_a_account.data).unwrap();
|
let swap_token_a = Processor::unpack_token_account(&accounts.token_a_account.data).unwrap();
|
||||||
let token_a_amount = swap_token_a.amount;
|
let token_a_amount = swap_token_a.amount;
|
||||||
assert_eq!(token_a_amount, results.new_source_amount);
|
assert_eq!(
|
||||||
|
token_a_amount,
|
||||||
|
results.new_source_amount.try_into().unwrap()
|
||||||
|
);
|
||||||
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
||||||
assert_eq!(token_a.amount, initial_a - a_to_b_amount);
|
assert_eq!(token_a.amount, initial_a - a_to_b_amount);
|
||||||
|
|
||||||
let swap_token_b = Processor::unpack_token_account(&accounts.token_b_account.data).unwrap();
|
let swap_token_b = Processor::unpack_token_account(&accounts.token_b_account.data).unwrap();
|
||||||
let token_b_amount = swap_token_b.amount;
|
let token_b_amount = swap_token_b.amount;
|
||||||
assert_eq!(token_b_amount, results.new_destination_amount);
|
assert_eq!(
|
||||||
|
token_b_amount,
|
||||||
|
results.new_destination_amount.try_into().unwrap()
|
||||||
|
);
|
||||||
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
||||||
assert_eq!(token_b.amount, initial_b + results.amount_swapped);
|
assert_eq!(
|
||||||
|
token_b.amount,
|
||||||
|
initial_b + to_u64(results.amount_swapped).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
let first_fee = swap_curve
|
let first_fee = swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.owner_fee_to_pool_tokens(
|
.owner_fee_to_pool_tokens(
|
||||||
results.owner_fee,
|
results.owner_fee,
|
||||||
token_a_amount,
|
token_a_amount.try_into().unwrap(),
|
||||||
initial_supply,
|
initial_supply.try_into().unwrap(),
|
||||||
TOKENS_IN_POOL,
|
TOKENS_IN_POOL.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let fee_account = Processor::unpack_token_account(&accounts.pool_fee_account.data).unwrap();
|
let fee_account = Processor::unpack_token_account(&accounts.pool_fee_account.data).unwrap();
|
||||||
assert_eq!(fee_account.amount, first_fee);
|
assert_eq!(fee_account.amount, first_fee.try_into().unwrap());
|
||||||
|
|
||||||
let first_swap_amount = results.amount_swapped;
|
let first_swap_amount = results.amount_swapped;
|
||||||
|
|
||||||
|
@ -3216,38 +3277,48 @@ mod tests {
|
||||||
|
|
||||||
let results = swap_curve
|
let results = swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.swap(b_to_a_amount, token_b_amount, token_a_amount)
|
.swap(
|
||||||
|
b_to_a_amount.try_into().unwrap(),
|
||||||
|
token_b_amount.try_into().unwrap(),
|
||||||
|
token_a_amount.try_into().unwrap(),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let swap_token_a = Processor::unpack_token_account(&accounts.token_a_account.data).unwrap();
|
let swap_token_a = Processor::unpack_token_account(&accounts.token_a_account.data).unwrap();
|
||||||
let token_a_amount = swap_token_a.amount;
|
let token_a_amount = swap_token_a.amount;
|
||||||
assert_eq!(token_a_amount, results.new_destination_amount);
|
assert_eq!(
|
||||||
|
token_a_amount,
|
||||||
|
results.new_destination_amount.try_into().unwrap()
|
||||||
|
);
|
||||||
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
let token_a = Processor::unpack_token_account(&token_a_account.data).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
token_a.amount,
|
token_a.amount,
|
||||||
initial_a - a_to_b_amount + results.amount_swapped
|
initial_a - a_to_b_amount + to_u64(results.amount_swapped).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let swap_token_b = Processor::unpack_token_account(&accounts.token_b_account.data).unwrap();
|
let swap_token_b = Processor::unpack_token_account(&accounts.token_b_account.data).unwrap();
|
||||||
let token_b_amount = swap_token_b.amount;
|
let token_b_amount = swap_token_b.amount;
|
||||||
assert_eq!(token_b_amount, results.new_source_amount);
|
assert_eq!(
|
||||||
|
token_b_amount,
|
||||||
|
results.new_source_amount.try_into().unwrap()
|
||||||
|
);
|
||||||
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
let token_b = Processor::unpack_token_account(&token_b_account.data).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
token_b.amount,
|
token_b.amount,
|
||||||
initial_b + first_swap_amount - b_to_a_amount
|
initial_b + to_u64(first_swap_amount).unwrap() - b_to_a_amount
|
||||||
);
|
);
|
||||||
|
|
||||||
let second_fee = swap_curve
|
let second_fee = swap_curve
|
||||||
.calculator
|
.calculator
|
||||||
.owner_fee_to_pool_tokens(
|
.owner_fee_to_pool_tokens(
|
||||||
results.owner_fee,
|
results.owner_fee,
|
||||||
token_b_amount,
|
token_b_amount.try_into().unwrap(),
|
||||||
initial_supply,
|
initial_supply.try_into().unwrap(),
|
||||||
TOKENS_IN_POOL,
|
TOKENS_IN_POOL.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let fee_account = Processor::unpack_token_account(&accounts.pool_fee_account.data).unwrap();
|
let fee_account = Processor::unpack_token_account(&accounts.pool_fee_account.data).unwrap();
|
||||||
assert_eq!(fee_account.amount, first_fee + second_fee);
|
assert_eq!(fee_account.amount, to_u64(first_fee + second_fee).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue