Skip to main content

defuse/contract/tokens/nep141/
deposit.rs

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