forked from BibliothecaDAO/realms-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibrary.cairo
117 lines (100 loc) · 4.05 KB
/
library.cairo
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
# AMM LIBRARY
# The purpose of the library is to hold any abstracted logic from the AMM. This allows cleaner test suites.
# MIT LICENCE
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.cairo.common.math import assert_not_equal
from starkware.cairo.common.uint256 import (
Uint256,
uint256_add,
uint256_sub,
uint256_mul,
uint256_unsigned_div_rem,
uint256_le,
uint256_eq,
)
namespace AMM:
# input arguments are:
# 1) exact amount of token to sell
# 2) currency reserve amount
# 3) token reserve amount
func get_sell_price{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
token_amount : Uint256,
currency_reserves : Uint256,
token_reserves : Uint256,
lp_fee_thousands_ : Uint256,
) -> (price : Uint256):
alloc_locals
# LP fee is used to withold currency as reward to LP providers
let (lp_fee) = uint256_sub(Uint256(1000, 0), lp_fee_thousands_)
# Apply LP fee to token amount
let (token_amount_w_fee, mul_overflow) = uint256_mul(token_amount, lp_fee)
with_attr error_message("LP fee overflow"):
assert mul_overflow = Uint256(0, 0)
end
# Calculate price
let (numerator, mul_overflow) = uint256_mul(token_amount_w_fee, currency_reserves)
with_attr error_message("Price numerator overflow"):
assert mul_overflow = Uint256(0, 0)
end
let (denominator, mul_overflow) = uint256_mul(token_reserves, Uint256(1000, 0))
with_attr error_message("LP fee buffer denominator overflow"):
assert mul_overflow = Uint256(0, 0)
end
let (denominator_fee, is_overflow) = uint256_add(denominator, token_amount_w_fee)
with_attr error_message("Price denominator overflow"):
assert is_overflow = 0
end
let (price, _) = uint256_unsigned_div_rem(numerator, denominator_fee)
# Sanity fallback check to see if price is 0
with_attr error_message("Price cannot be 0"):
let (is_zero) = uint256_le(price, Uint256(0, 0))
assert_not_equal(is_zero, 1)
end
# Rounding errors favour the contract
return (price)
end
# input arguments are:
# 1) exact amount of token to buy
# 2) currency reserve amount
# 3) token reserve amount
func get_buy_price{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
token_amount : Uint256,
currency_reserves : Uint256,
token_reserves : Uint256,
lp_fee_thousands_ : Uint256,
) -> (price : Uint256):
alloc_locals
# LP fee is used to withold currency as reward to LP providers
let (lp_fee) = uint256_sub(Uint256(1000, 0), lp_fee_thousands_)
# Calculate price
let (numerator, mul_overflow) = uint256_mul(currency_reserves, token_amount)
with_attr error_message("Values too large"):
assert mul_overflow = Uint256(0, 0)
end
let (denominator) = uint256_sub(token_reserves, token_amount)
with_attr error_message("Can't buy 100% of the AMM"):
let (is_z) = uint256_eq(denominator, Uint256(0, 0))
assert is_z = 0
end
# Add LP fee
let (numerator, mul_overflow) = uint256_mul(numerator, Uint256(1000, 0))
with_attr error_message("Numerator overflow"):
assert mul_overflow = Uint256(0, 0)
end
let (denominator, mul_overflow) = uint256_mul(denominator, lp_fee)
with_attr error_message("Denominator overflow"):
assert mul_overflow = Uint256(0, 0)
end
# Calculate price
let (price, remainder) = uint256_unsigned_div_rem(numerator, denominator)
# Return value if no remainder
let (is_z) = uint256_eq(remainder, Uint256(0, 0))
if is_z == (1):
return (price)
end
# Round up when there is a remainder, to favour LP providers
let (price, _) = uint256_add(price, Uint256(1, 0))
return (price)
end
end