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)
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::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}