Skip to main content

defuse/contract/tokens/nep245/
deposit.rs

1use defuse_core::{DefuseError, token_id::nep245::Nep245TokenId, tokens::MAX_TOKEN_ID_LEN};
2use defuse_nep245::receiver::MultiTokenReceiver;
3use near_plugins::{Pausable, pause};
4use near_sdk::{AccountId, FunctionError, PromiseOrValue, env, json_types::U128, near, require};
5
6use crate::{
7    contract::{Contract, ContractExt},
8    intents::{Intents, ext_intents},
9    tokens::{DepositAction, DepositMessage},
10};
11
12#[near]
13impl MultiTokenReceiver for Contract {
14    /// Deposit multi-tokens.
15    ///
16    /// `msg` contains [`AccountId`] of the internal recipient.
17    /// Empty `msg` means deposit to `sender_id`
18    #[pause]
19    fn mt_on_transfer(
20        &mut self,
21        sender_id: AccountId,
22        previous_owner_ids: Vec<AccountId>,
23        token_ids: Vec<defuse_nep245::TokenId>,
24        amounts: Vec<U128>,
25        msg: String,
26    ) -> PromiseOrValue<Vec<U128>> {
27        let token = env::predecessor_account_id();
28
29        require!(!amounts.is_empty(), "invalid args");
30
31        require!(
32            token_ids.len() == amounts.len(),
33            "NEP-245: Contract MUST panic if `token_ids` length does not equals `amounts` length"
34        );
35
36        require!(
37            previous_owner_ids.len() == token_ids.len(),
38            "NEP-245: Contract MUST panic if `previous_owner_ids` length does not equals `token_ids` length"
39        );
40
41        require!(
42            token != env::current_account_id(),
43            "self-wrapping is not allowed"
44        );
45
46        let core_token_ids = token_ids
47            .iter()
48            .inspect(|token_id| {
49                if token_id.len() > MAX_TOKEN_ID_LEN {
50                    DefuseError::TokenIdTooLarge(token_id.len()).panic();
51                }
52            })
53            .cloned()
54            .map(|token_id| Nep245TokenId::new(token.clone(), token_id))
55            .map(Into::into);
56
57        let DepositMessage {
58            receiver_id,
59            action,
60        } = if msg.is_empty() {
61            DepositMessage::new(sender_id)
62        } else {
63            msg.parse().unwrap_or_else(|e| panic!("{e}"))
64        };
65
66        self.deposit(
67            receiver_id,
68            core_token_ids
69                .clone()
70                .zip(amounts.iter().map(|amount| amount.0)),
71            Some("deposit"),
72        )
73        .unwrap_or_else(|err| err.panic());
74
75        let Some(action) = action else {
76            return PromiseOrValue::Value(vec![U128(0); token_ids.len()]);
77        };
78
79        match action {
80            // DepositAction::Notify(notify) => Self::notify_on_transfer(
81            //     sender_id,
82            //     previous_owner_ids,
83            //     receiver_id.clone(),
84            //     core_token_ids.map(|t| t.to_string()).collect(),
85            //     amounts.clone(),
86            //     notify,
87            // )
88            // .unwrap_or_else(|err| err.panic())
89            // .then(
90            //     Self::ext(env::current_account_id())
91            //         .with_static_gas(Self::mt_resolve_deposit_gas(amounts.len()))
92            //         .with_unused_gas_weight(0)
93            //         .mt_resolve_deposit(receiver_id, token.clone(), token_ids, amounts),
94            // )
95            // .into(),
96            DepositAction::Execute(execute) => {
97                if !execute.execute_intents.is_empty() {
98                    if execute.refund_if_fails {
99                        self.execute_intents(execute.execute_intents);
100                    } else {
101                        ext_intents::ext(env::current_account_id())
102                            .execute_intents(execute.execute_intents)
103                            .detach();
104                    }
105                }
106                PromiseOrValue::Value(vec![U128(0); token_ids.len()])
107            }
108        }
109    }
110}
111
112#[near]
113impl Contract {
114    #[private]
115    #[allow(clippy::needless_pass_by_value)]
116    pub fn mt_resolve_deposit(
117        &mut self,
118        receiver_id: AccountId,
119        contract_id: AccountId,
120        tokens: Vec<defuse_nep245::TokenId>,
121        #[allow(unused_mut)] mut amounts: Vec<U128>,
122    ) -> PromiseOrValue<Vec<U128>> {
123        self.resolve_deposit_internal(
124            &receiver_id,
125            tokens
126                .into_iter()
127                .map(|token_id| Nep245TokenId::new(contract_id.clone(), token_id))
128                .map(Into::into)
129                .zip(amounts.iter_mut().map(|amount| &mut amount.0)),
130        );
131
132        PromiseOrValue::Value(amounts)
133    }
134}