templar_market_contract/
lib.rs

1#![allow(clippy::needless_pass_by_value)]
2
3use std::ops::{Deref, DerefMut};
4
5use near_sdk::{env, near, AccountId, BorshStorageKey, PanicOnDefault};
6use near_sdk_contract_tools::standard::nep145::{
7    Nep145Controller, Nep145ForceUnregister, StorageBalanceBounds,
8};
9use templar_common::market::{Market, MarketConfiguration};
10
11#[derive(BorshStorageKey)]
12#[near(serializers = [borsh])]
13enum StorageKey {
14    Market,
15}
16
17#[derive(PanicOnDefault, near_sdk_contract_tools::Nep145)]
18#[nep145(force_unregister_hook = "Self")]
19#[near(contract_state)]
20pub struct Contract {
21    pub market: Market,
22    storage_usage_snapshot: u64,
23    storage_usage_supply_position: u64,
24    storage_usage_borrow_position: u64,
25}
26
27#[near]
28impl Contract {
29    #[allow(clippy::unwrap_used, reason = "Infallible")]
30    #[init]
31    pub fn new(configuration: MarketConfiguration) -> Self {
32        let mut market = Market::new(StorageKey::Market, configuration);
33        let snapshot = market.snapshot();
34        let storage_usage_1 = env::storage_usage();
35        market.finalized_snapshots.flush();
36        let storage_usage_2 = env::storage_usage();
37        let storage_usage_snapshot = storage_usage_2.saturating_sub(storage_usage_1);
38
39        // These values shoud be approximately:
40        // 161 (fixed cost) +
41        // borsh serialization length of position record +
42        // 128 (max account length in bytes)
43        let zero_account: AccountId = "0".repeat(64).parse().unwrap();
44
45        drop(market.get_or_create_supply_position_guard(snapshot, zero_account.clone()));
46        let storage_usage_3 = env::storage_usage();
47        let storage_usage_supply_position = storage_usage_3.saturating_sub(storage_usage_2);
48
49        drop(market.get_or_create_borrow_position_guard(snapshot, zero_account.clone()));
50        let storage_usage_4 = env::storage_usage();
51        let storage_usage_borrow_position = storage_usage_4.saturating_sub(storage_usage_3);
52
53        env::log_str(&format!("Storage usage: {{ \"snapshot\": {storage_usage_snapshot}, \"supply_position\":{storage_usage_supply_position}, \"borrow_position\": {storage_usage_borrow_position} }}"));
54
55        market.cleanup_supply_position(&zero_account);
56        market.cleanup_borrow_position(&zero_account);
57
58        let mut self_ = Self {
59            market,
60            storage_usage_snapshot,
61            storage_usage_supply_position,
62            storage_usage_borrow_position,
63        };
64
65        self_.set_storage_balance_bounds(&StorageBalanceBounds {
66            min: env::storage_byte_cost().saturating_mul(u128::from(
67                storage_usage_supply_position.max(storage_usage_borrow_position)
68                    + 2 * storage_usage_snapshot,
69            )),
70            max: None,
71        });
72
73        self_
74    }
75
76    fn charge_for_storage(&mut self, account_id: &AccountId, storage_consumption: u64) {
77        self.lock_storage(
78            account_id,
79            env::storage_byte_cost().saturating_mul(u128::from(storage_consumption)),
80        )
81        .unwrap_or_else(|e| templar_common::panic_with_message(&format!("Storage error: {e}")));
82    }
83
84    fn refund_for_storage(&mut self, account_id: &AccountId, storage_consumption: u64) {
85        self.unlock_storage(
86            account_id,
87            env::storage_byte_cost().saturating_mul(u128::from(storage_consumption)),
88        )
89        .unwrap_or_else(|e| templar_common::panic_with_message(&format!("Storage error: {e}")));
90    }
91}
92
93impl near_sdk_contract_tools::hook::Hook<Self, Nep145ForceUnregister<'_>> for Contract {
94    fn hook<R>(_: &mut Self, _: &Nep145ForceUnregister, _: impl FnOnce(&mut Self) -> R) -> R {
95        templar_common::panic_with_message("force unregistration is not supported")
96    }
97}
98
99impl Deref for Contract {
100    type Target = Market;
101
102    fn deref(&self) -> &Self::Target {
103        &self.market
104    }
105}
106
107impl DerefMut for Contract {
108    fn deref_mut(&mut self) -> &mut Self::Target {
109        &mut self.market
110    }
111}
112
113mod impl_helper;
114mod impl_market_external;
115mod impl_token_receiver;
116
117#[cfg(test)]
118mod tests;
119
120#[cfg(target_arch = "wasm32")]
121mod custom_getrandom {
122    #![allow(clippy::no_mangle_with_rust_abi)]
123
124    use getrandom::{register_custom_getrandom, Error};
125    use near_sdk::env;
126
127    register_custom_getrandom!(custom_getrandom);
128
129    #[allow(clippy::unnecessary_wraps)]
130    pub fn custom_getrandom(buf: &mut [u8]) -> Result<(), Error> {
131        buf.copy_from_slice(&env::random_seed_array());
132        Ok(())
133    }
134}