defuse/contract/tokens/nep245/
deposit.rs1use 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 #[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.clone())
62 } else {
63 msg.parse().unwrap_or_else(|e| panic!("{e}"))
64 };
65
66 self.deposit(
67 receiver_id.clone(),
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 .then(
89 Self::ext(env::current_account_id())
90 .with_static_gas(Self::mt_resolve_deposit_gas(amounts.len()))
91 .with_unused_gas_weight(0)
92 .mt_resolve_deposit(receiver_id, token.clone(), token_ids, amounts),
93 )
94 .into(),
95 DepositAction::Execute(execute) => {
96 if !execute.execute_intents.is_empty() {
97 if execute.refund_if_fails {
98 self.execute_intents(execute.execute_intents);
99 } else {
100 ext_intents::ext(env::current_account_id())
101 .execute_intents(execute.execute_intents)
102 .detach();
103 }
104 }
105 PromiseOrValue::Value(vec![U128(0); token_ids.len()])
106 }
107 }
108 }
109}
110
111#[near]
112impl Contract {
113 #[private]
114 #[allow(clippy::needless_pass_by_value)]
115 pub fn mt_resolve_deposit(
116 &mut self,
117 receiver_id: AccountId,
118 contract_id: AccountId,
119 tokens: Vec<defuse_nep245::TokenId>,
120 #[allow(unused_mut)] mut amounts: Vec<U128>,
121 ) -> PromiseOrValue<Vec<U128>> {
122 self.resolve_deposit_internal(
123 &receiver_id,
124 tokens
125 .into_iter()
126 .map(|token_id| Nep245TokenId::new(contract_id.clone(), token_id))
127 .map(Into::into)
128 .zip(amounts.iter_mut().map(|amount| &mut amount.0)),
129 );
130
131 PromiseOrValue::Value(amounts)
132 }
133}