-
Notifications
You must be signed in to change notification settings - Fork 0
/
swap_math.rs
120 lines (103 loc) · 4.19 KB
/
swap_math.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use anchor_lang::prelude::*;
use crate::{constants::*, errors::ErrorCode, instructions::*, state::*, util::*};
pub fn calc_quote_amount_sell_base(
base_amount: u128,
woopool: &Account<'_, WooPool>,
decimals: &Decimals,
state: &GetStateResult,
) -> Result<(u128, u128)> {
require!(state.feasible_out, ErrorCode::WooOracleNotFeasible);
require!(state.price_out > 0, ErrorCode::WooOraclePriceNotValid);
//let notionalSwap : u128 = (base_amount * state.price_out * decimals.quote_dec) / decimals.base_dec / decimals.price_dec;
let notion_calc_a: u128 =
checked_mul_div(base_amount, state.price_out, decimals.price_dec as u128)?;
let notional_swap: u128 = checked_mul_div(
notion_calc_a,
decimals.quote_dec as u128,
decimals.base_dec as u128,
)?;
require!(
notional_swap <= woopool.max_notional_swap,
ErrorCode::WooPoolExceedMaxNotionalValue
);
// gamma = k * price * base_amount; and decimal 18
let gamma_calc_a: u128 =
checked_mul_div(base_amount, state.price_out, decimals.price_dec as u128)?;
let gamma: u128 =
checked_mul_div(gamma_calc_a, state.coeff as u128, decimals.base_dec as u128)?;
require!(gamma <= woopool.max_gamma, ErrorCode::WooPoolExceedMaxGamma);
// Formula: quoteAmount = baseAmount * oracle.price * (1 - oracle.k * baseAmount * oracle.price - oracle.spread)
// quoteAmount =
// (((baseAmount * state.price * decs.quoteDec) / decs.priceDec) *
// (uint256(1e18) - gamma - state.spread)) /
// 1e18 /
// decs.baseDec;
// ====>
// quoteAmount =
// (((baseAmount * state.price / decs.priceDec) * decs.quoteDec) * (uint256(1e18) - gamma - state.spread)) /
// 1e18 /
// decs.baseDec;
// ====>
// a = (baseAmount * state.price / decs.priceDec)
// b = (uint256(1e18) - gamma - state.spread)
// quoteAmount = ((a * decs.quoteDec) * b) / 1e18 / decs.baseDec;
// = ((a * b) / 1e18) * decs.quoteDec / decs.baseDec
let calc_a: u128 = checked_mul_div(base_amount, state.price_out, decimals.price_dec as u128)?;
let calc_b: u128 = ONE_E18_U128
.checked_sub(gamma)
.unwrap()
.checked_sub(state.spread as u128)
.unwrap();
let calc_c = checked_mul_div(calc_a, calc_b, ONE_E18_U128)?;
let quote_amount = checked_mul_div(
calc_c,
decimals.quote_dec as u128,
decimals.base_dec as u128,
)?;
// newPrice = oracle.price * (1 - k * oracle.price * baseAmount)
let new_price: u128 = checked_mul_div(
ONE_E18_U128.checked_sub(gamma).unwrap(),
state.price_out,
ONE_E18_U128,
)?;
Ok((quote_amount, new_price))
}
pub fn calc_base_amount_sell_quote(
quote_amount: u128,
woopool: &Account<'_, WooPool>,
decimals: &Decimals,
state: &GetStateResult,
) -> Result<(u128, u128)> {
require!(state.feasible_out, ErrorCode::WooOracleNotFeasible);
require!(state.price_out > 0, ErrorCode::WooOraclePriceNotValid);
require!(
quote_amount <= woopool.max_notional_swap,
ErrorCode::WooPoolExceedMaxNotionalValue
);
// gamma = k * quote_amount; and decimal 18
let gamma: u128 = checked_mul_div(
quote_amount,
state.coeff as u128,
decimals.quote_dec as u128,
)?;
require!(gamma <= woopool.max_gamma, ErrorCode::WooPoolExceedMaxGamma);
// Formula: baseAmount = quoteAmount / oracle.price * (1 - oracle.k * quoteAmount - oracle.spread)
let calc_a: u128 = quote_amount
.checked_mul(decimals.base_dec as u128)
.ok_or(ErrorCode::MathOverflow)?;
let calc_b: u128 = checked_mul_div(calc_a, decimals.price_dec as u128, state.price_out)?;
let calc_c: u128 = ONE_E18_U128
.checked_sub(gamma)
.unwrap()
.checked_sub(state.spread as u128)
.unwrap();
let calc_d: u128 = checked_mul_div(calc_b, calc_c, ONE_E18_U128)?;
let base_amount = calc_d.checked_div(decimals.quote_dec as u128).unwrap();
// new_price = oracle.price / (1 - k * quoteAmount)
let new_price: u128 = checked_mul_div(
ONE_E18_U128,
state.price_out,
ONE_E18_U128.checked_sub(gamma).unwrap(),
)?;
Ok((base_amount, new_price))
}