templar_common/vault/
wad.rs

1use core::ops::Div;
2use std::collections::BTreeMap;
3use std::ops::{Add, Sub};
4
5use near_sdk::borsh::schema::{add_definition, Declaration, Definition};
6use near_sdk::borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
7use near_sdk::serde::{Deserialize, Serialize};
8use primitive_types::{U256, U512};
9use schemars::JsonSchema;
10
11use crate::schemars::r#gen::SchemaGenerator;
12use crate::schemars::schema::Schema;
13
14pub type WIDE = U512;
15
16#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
17pub struct Number(pub U256);
18
19impl Serialize for Number {
20    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21    where
22        S: near_sdk::serde::Serializer,
23    {
24        serializer.serialize_str(&self.0.to_string())
25    }
26}
27
28impl<'de> Deserialize<'de> for Number {
29    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30    where
31        D: near_sdk::serde::Deserializer<'de>,
32    {
33        let s = <String as near_sdk::serde::Deserialize>::deserialize(deserializer)?;
34        U256::from_dec_str(&s)
35            .map(Number)
36            .map_err(|_| near_sdk::serde::de::Error::custom("invalid decimal string for U256"))
37    }
38}
39
40impl Number {
41    pub const ZERO: Self = Number(U256([0, 0, 0, 0]));
42
43    #[inline]
44    #[must_use]
45    pub fn zero() -> Self {
46        Self::ZERO
47    }
48
49    #[inline]
50    #[must_use]
51    pub fn one() -> Self {
52        Number(U256::one())
53    }
54
55    #[inline]
56    #[must_use]
57    pub fn is_zero(&self) -> bool {
58        self.0.is_zero()
59    }
60
61    #[inline]
62    #[must_use]
63    pub fn as_u128_trunc(self) -> u128 {
64        let mut b32 = [0u8; 32];
65        self.0.write_as_little_endian(&mut b32);
66        let mut b16 = [0u8; 16];
67        b16.copy_from_slice(&b32[..16]);
68        u128::from_le_bytes(b16)
69    }
70
71    #[inline]
72    #[must_use]
73    pub fn saturating_add(self, other: Number) -> Number {
74        Number(self.0.saturating_add(other.0))
75    }
76
77    #[inline]
78    #[must_use]
79    pub fn saturating_sub(self, other: Number) -> Number {
80        Number(self.0.saturating_sub(other.0))
81    }
82
83    #[inline]
84    fn as_u256_trunc(q: U512) -> U256 {
85        let mut b64 = [0u8; 64];
86        q.write_as_little_endian(&mut b64);
87        U256::from_little_endian(&b64[..32])
88    }
89
90    #[inline]
91    #[must_use]
92    pub fn mul_div_floor(multiplicand: Number, multiplier: Number, denominator: Number) -> Number {
93        if denominator.is_zero() {
94            return Number::zero();
95        }
96        let product = multiplicand.0.full_mul(multiplier.0);
97        let quotient = product / U512::from(denominator.0);
98        Number(Self::as_u256_trunc(quotient))
99    }
100
101    #[inline]
102    #[must_use]
103    pub fn mul_div_ceil(multiplicand: Number, multiplier: Number, denominator: Number) -> Number {
104        if denominator.is_zero() {
105            return Number::zero();
106        }
107        let product = multiplicand.0.full_mul(multiplier.0);
108        let wide_denominator = U512::from(denominator.0);
109        let quotient = product / wide_denominator;
110        let remainder = product % wide_denominator;
111        let base = Number(Self::as_u256_trunc(quotient));
112        if remainder.is_zero() {
113            base
114        } else {
115            base.saturating_add(Number::one())
116        }
117    }
118}
119
120impl From<u128> for Number {
121    fn from(v: u128) -> Self {
122        Number(U256::from(v))
123    }
124}
125
126impl From<Number> for u128 {
127    fn from(n: Number) -> u128 {
128        n.as_u128_trunc()
129    }
130}
131
132impl From<U256> for Number {
133    fn from(v: U256) -> Self {
134        Number(v)
135    }
136}
137
138impl From<Number> for U256 {
139    fn from(n: Number) -> U256 {
140        n.0
141    }
142}
143
144impl Div<u128> for Number {
145    type Output = Number;
146
147    fn div(self, rhs: u128) -> Number {
148        Number(self.0 / U256::from(rhs))
149    }
150}
151
152impl Div<Number> for Number {
153    type Output = Number;
154
155    fn div(self, rhs: Number) -> Number {
156        Number(self.0 / rhs.0)
157    }
158}
159
160impl Add<Number> for Number {
161    type Output = Number;
162
163    fn add(self, rhs: Number) -> Number {
164        Number(self.0 + rhs.0)
165    }
166}
167
168impl Sub<Number> for Number {
169    type Output = Number;
170
171    fn sub(self, rhs: Number) -> Number {
172        Number(self.0 - rhs.0)
173    }
174}
175
176impl BorshSerialize for Number {
177    fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
178        let mut b32 = [0u8; 32];
179        self.0.write_as_little_endian(&mut b32);
180        writer.write_all(&b32)
181    }
182}
183
184impl BorshDeserialize for Number {
185    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
186        let mut b32 = [0u8; 32];
187        reader.read_exact(&mut b32)?;
188        Ok(Number(U256::from_little_endian(&b32)))
189    }
190}
191
192impl BorshSchema for Number {
193    fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
194        add_definition(Self::declaration(), Definition::Primitive(32), definitions);
195    }
196
197    fn declaration() -> Declaration {
198        "Number".into()
199    }
200}
201
202impl JsonSchema for Number {
203    fn schema_name() -> String {
204        "Number".to_string()
205    }
206
207    fn json_schema(generator: &mut SchemaGenerator) -> Schema {
208        let mut g = generator.subschema_for::<String>().into_object();
209        g.metadata().description = Some("256-bit Unsigned Integer".to_string());
210        g.string().pattern = Some("^(0|[1-9][0-9]{0,77})$".to_string());
211        g.into()
212    }
213}
214
215pub const MAX_MANAGEMENT_FEE_WAD: u128 = Wad::SCALE / 100 * 5;
216pub const MAX_PERFORMANCE_FEE_WAD: u128 = Wad::SCALE / 100 * 50;
217pub const MAX_FEE_WAD: u128 = MAX_PERFORMANCE_FEE_WAD;
218pub const YEAR_NS: u64 = 365 * 24 * 60 * 60 * 1_000_000_000;
219
220#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
221pub struct Wad(pub Number);
222
223impl Serialize for Wad {
224    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
225    where
226        S: near_sdk::serde::Serializer,
227    {
228        Serialize::serialize(&self.0, serializer)
229    }
230}
231
232impl<'de> Deserialize<'de> for Wad {
233    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
234    where
235        D: near_sdk::serde::Deserializer<'de>,
236    {
237        <Number as Deserialize>::deserialize(deserializer).map(Wad)
238    }
239}
240
241impl Wad {
242    const SCALE_LOW_LIMB: u64 = 1_000_000_000_000_000_000u64;
243    pub const SCALE: u128 = 1_000_000_000_000_000_000u128;
244    pub const ZERO: Self = Wad(Number::ZERO);
245    pub const ONE: Self = Wad(Number(U256([Self::SCALE_LOW_LIMB, 0, 0, 0])));
246
247    #[inline]
248    #[must_use]
249    pub fn zero() -> Self {
250        Self::ZERO
251    }
252
253    #[inline]
254    #[must_use]
255    pub fn one() -> Self {
256        Self::ONE
257    }
258
259    #[inline]
260    #[must_use]
261    pub fn is_zero(&self) -> bool {
262        self.0.is_zero()
263    }
264
265    #[inline]
266    #[must_use]
267    pub fn is_one(&self) -> bool {
268        self.0 .0 == U256::from(Self::SCALE)
269    }
270
271    #[inline]
272    #[must_use]
273    pub fn as_u128_trunc(self) -> u128 {
274        self.0.as_u128_trunc()
275    }
276
277    #[inline]
278    #[must_use]
279    pub fn apply_floored(self, amount: Number) -> Number {
280        mul_wad_floor(amount, self)
281    }
282}
283
284impl From<u128> for Wad {
285    fn from(v: u128) -> Self {
286        Wad(Number::from(v))
287    }
288}
289
290impl From<Wad> for u128 {
291    fn from(v: Wad) -> Self {
292        v.0.as_u128_trunc()
293    }
294}
295
296impl Div<u128> for Wad {
297    type Output = Wad;
298
299    fn div(self, rhs: u128) -> Wad {
300        Wad(self.0 / rhs)
301    }
302}
303
304impl Div<Number> for Wad {
305    type Output = Wad;
306
307    fn div(self, rhs: Number) -> Wad {
308        Wad(self.0 / rhs)
309    }
310}
311
312impl BorshSerialize for Wad {
313    fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
314        BorshSerialize::serialize(&self.0, writer)
315    }
316}
317
318impl BorshDeserialize for Wad {
319    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
320        Number::deserialize_reader(reader).map(Wad)
321    }
322}
323
324impl BorshSchema for Wad {
325    fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
326        add_definition(Self::declaration(), Definition::Primitive(32), definitions);
327    }
328
329    fn declaration() -> Declaration {
330        "Wad".into()
331    }
332}
333
334impl JsonSchema for Wad {
335    fn schema_name() -> String {
336        "Wad".to_string()
337    }
338
339    fn json_schema(generator: &mut SchemaGenerator) -> Schema {
340        let mut g = generator.subschema_for::<String>().into_object();
341        g.metadata().description = Some("WAD-scaled U256 (1e18 = 100%)".to_string());
342        g.string().pattern = Some("^(0|[1-9][0-9]{0,77})$".to_string());
343        g.into()
344    }
345}
346
347#[inline]
348#[must_use]
349pub fn mul_wad_floor(x: Number, y: Wad) -> Number {
350    Number::mul_div_floor(x, y.0, Number::from(Wad::SCALE))
351}
352
353#[inline]
354#[must_use]
355pub fn mul_div_floor(x: Number, y: Number, denom: Number) -> Number {
356    Number::mul_div_floor(x, y, denom)
357}
358
359#[inline]
360#[must_use]
361pub fn mul_div_ceil(x: Number, y: Number, denom: Number) -> Number {
362    Number::mul_div_ceil(x, y, denom)
363}
364
365#[must_use]
366pub fn compute_fee_shares(
367    cur_total_assets: Number,
368    last_total_assets: Number,
369    fee_wad: Wad,
370    total_supply: Number,
371) -> Number {
372    if cur_total_assets <= last_total_assets || fee_wad.is_zero() || total_supply.is_zero() {
373        return Number::zero();
374    }
375
376    let profit = cur_total_assets.saturating_sub(last_total_assets);
377    let fee_assets = fee_wad.apply_floored(profit);
378    compute_fee_shares_from_assets(fee_assets, cur_total_assets, total_supply)
379}
380
381#[must_use]
382pub fn compute_fee_shares_from_assets(
383    fee_assets: Number,
384    cur_total_assets: Number,
385    total_supply: Number,
386) -> Number {
387    if fee_assets.is_zero() || cur_total_assets.is_zero() || total_supply.is_zero() {
388        return Number::zero();
389    }
390
391    let denom = Number(cur_total_assets.0 - fee_assets.0);
392    Number::mul_div_floor(fee_assets, total_supply, denom)
393}