defuse/contract/tokens/nep141/
deposit.rs

1use defuse_core::token_id::{TokenId, nep141::Nep141TokenId};
2use defuse_near_utils::{UnwrapOrPanic, UnwrapOrPanicError};
3use near_contract_standards::fungible_token::receiver::FungibleTokenReceiver;
4use near_plugins::{Pausable, pause};
5use near_sdk::{AccountId, PromiseOrValue, env, json_types::U128, near, require};
6
7use crate::{
8    contract::{Contract, ContractExt},
9    intents::{Intents, ext_intents},
10    tokens::{DepositAction, DepositMessage},
11};
12
13#[near]
14impl FungibleTokenReceiver for Contract {
15    /// Deposit fungible tokens.
16    ///
17    /// `msg` contains [`AccountId`] of the internal recipient.
18    /// Empty `msg` means deposit to `sender_id`
19    #[pause]
20    fn ft_on_transfer(
21        &mut self,
22        sender_id: AccountId,
23        amount: U128,
24        msg: String,
25    ) -> PromiseOrValue<U128> {
26        require!(amount.0 > 0, "zero amount");
27
28        let token_id = TokenId::Nep141(Nep141TokenId::new(env::predecessor_account_id()));
29
30        let DepositMessage {
31            receiver_id,
32            action,
33        } = if msg.is_empty() {
34            DepositMessage::new(sender_id.clone())
35        } else {
36            msg.parse().unwrap_or_panic_display()
37        };
38
39        self.deposit(
40            receiver_id.clone(),
41            [(token_id.clone(), amount.0)],
42            Some("deposit"),
43        )
44        .unwrap_or_panic();
45
46        let Some(action) = action else {
47            return PromiseOrValue::Value(0.into());
48        };
49
50        match action {
51            DepositAction::Notify(notify) => Self::notify_on_transfer(
52                sender_id.clone(),
53                vec![sender_id],
54                receiver_id.clone(),
55                vec![token_id.to_string()],
56                vec![amount],
57                notify,
58            )
59            .then(
60                Self::ext(env::current_account_id())
61                    .with_static_gas(Self::mt_resolve_deposit_gas(1))
62                    .with_unused_gas_weight(0)
63                    .ft_resolve_deposit(receiver_id, env::predecessor_account_id(), amount),
64            )
65            .into(),
66            DepositAction::Execute(execute) => {
67                if !execute.execute_intents.is_empty() {
68                    if execute.refund_if_fails {
69                        self.execute_intents(execute.execute_intents);
70                    } else {
71                        ext_intents::ext(env::current_account_id())
72                            .execute_intents(execute.execute_intents)
73                            .detach();
74                    }
75                }
76                PromiseOrValue::Value(0.into())
77            }
78        }
79    }
80}
81
82#[near]
83impl Contract {
84    #[private]
85    #[allow(clippy::needless_pass_by_value)]
86    pub fn ft_resolve_deposit(
87        &mut self,
88        receiver_id: AccountId,
89        contract_id: AccountId,
90        #[allow(unused_mut)] mut amount: U128,
91    ) -> PromiseOrValue<U128> {
92        self.resolve_deposit_internal(
93            &receiver_id,
94            [(Nep141TokenId::new(contract_id).into(), &mut amount.0)],
95        );
96        PromiseOrValue::Value(amount)
97    }
98}