1use soroban_token_sdk::metadata::TokenMetadata;
2use stellar_axelar_gas_service::AxelarGasServiceClient;
3use stellar_axelar_gateway::executable::{AxelarExecutableInterface, CustomAxelarExecutable};
4use stellar_axelar_gateway::AxelarGatewayMessagingClient;
5use stellar_axelar_std::address::AddressExt;
6use stellar_axelar_std::events::Event;
7use stellar_axelar_std::token::StellarAssetClient;
8use stellar_axelar_std::types::Token;
9use stellar_axelar_std::xdr::ToXdr;
10use stellar_axelar_std::{
11 contract, contractimpl, ensure, interfaces, only_operator, only_owner, soroban_sdk, vec,
12 when_not_paused, Address, AxelarExecutable, Bytes, BytesN, Env, IntoVal, Operatable, Ownable,
13 Pausable, String, Symbol, Upgradable, Val,
14};
15use stellar_token_manager::TokenManagerClient;
16use token_id::UnregisteredTokenId;
17
18use crate::error::ContractError;
19use crate::event::{
20 InterchainTokenDeploymentStartedEvent, InterchainTransferReceivedEvent,
21 InterchainTransferSentEvent, LinkTokenReceivedEvent, LinkTokenStartedEvent,
22 TokenMetadataRegisteredEvent, TrustedChainRemovedEvent, TrustedChainSetEvent,
23};
24use crate::flow_limit::FlowDirection;
25use crate::interface::InterchainTokenServiceInterface;
26use crate::storage::{self, TokenIdConfigValue};
27use crate::token_manager::TokenManagerClientExt;
28use crate::token_metadata::TokenMetadataExt;
29use crate::types::{
30 DeployInterchainToken, HubMessage, InterchainTransfer, LinkToken, Message,
31 RegisterTokenMetadata, TokenManagerType,
32};
33use crate::{deployer, flow_limit, token_handler, token_id, token_metadata};
34
35const ITS_HUB_CHAIN_NAME: &str = "axelar";
36const EXECUTE_WITH_INTERCHAIN_TOKEN: &str = "execute_with_interchain_token";
37
38#[contract]
39#[derive(Operatable, Ownable, Pausable, Upgradable, AxelarExecutable)]
40pub struct InterchainTokenService;
41
42#[contractimpl]
43impl InterchainTokenService {
44 pub fn __constructor(
45 env: Env,
46 owner: Address,
47 operator: Address,
48 gateway: Address,
49 gas_service: Address,
50 its_hub_address: String,
51 chain_name: String,
52 native_token_address: Address,
53 interchain_token_wasm_hash: BytesN<32>,
54 token_manager_wasm_hash: BytesN<32>,
55 ) {
56 interfaces::set_owner(&env, &owner);
57 interfaces::set_operator(&env, &operator);
58 storage::set_gateway(&env, &gateway);
59 storage::set_gas_service(&env, &gas_service);
60 storage::set_its_hub_address(&env, &its_hub_address);
61 storage::set_chain_name(&env, &chain_name);
62 storage::set_native_token_address(&env, &native_token_address);
63 storage::set_interchain_token_wasm_hash(&env, &interchain_token_wasm_hash);
64 storage::set_token_manager_wasm_hash(&env, &token_manager_wasm_hash);
65 }
66}
67
68#[contractimpl]
69impl InterchainTokenServiceInterface for InterchainTokenService {
70 fn gas_service(env: &Env) -> Address {
71 storage::gas_service(env)
72 }
73
74 fn chain_name(env: &Env) -> String {
75 storage::chain_name(env)
76 }
77
78 fn its_hub_chain_name(env: &Env) -> String {
79 String::from_str(env, ITS_HUB_CHAIN_NAME)
80 }
81
82 fn its_hub_address(env: &Env) -> String {
83 storage::its_hub_address(env)
84 }
85
86 fn native_token_address(env: &Env) -> Address {
87 storage::native_token_address(env)
88 }
89
90 fn interchain_token_wasm_hash(env: &Env) -> BytesN<32> {
91 storage::interchain_token_wasm_hash(env)
92 }
93
94 fn token_manager_wasm_hash(env: &Env) -> BytesN<32> {
95 storage::token_manager_wasm_hash(env)
96 }
97
98 fn is_trusted_chain(env: &Env, chain: String) -> bool {
99 storage::is_trusted_chain(env, chain)
100 }
101
102 #[only_operator]
103 fn set_trusted_chain(env: &Env, chain: String) -> Result<(), ContractError> {
104 ensure!(
105 !storage::is_trusted_chain(env, chain.clone()),
106 ContractError::TrustedChainAlreadySet
107 );
108
109 storage::set_trusted_chain_status(env, chain.clone());
110
111 TrustedChainSetEvent { chain }.emit(env);
112
113 Ok(())
114 }
115
116 #[only_operator]
117 fn remove_trusted_chain(env: &Env, chain: String) -> Result<(), ContractError> {
118 ensure!(
119 storage::is_trusted_chain(env, chain.clone()),
120 ContractError::TrustedChainNotSet
121 );
122
123 storage::remove_trusted_chain_status(env, chain.clone());
124
125 TrustedChainRemovedEvent { chain }.emit(env);
126
127 Ok(())
128 }
129
130 fn interchain_token_id(env: &Env, deployer: Address, salt: BytesN<32>) -> BytesN<32> {
131 token_id::interchain_token_id(env, Self::chain_name_hash(env), deployer, salt)
132 }
133
134 fn canonical_interchain_token_id(env: &Env, token_address: Address) -> BytesN<32> {
135 token_id::canonical_interchain_token_id(env, Self::chain_name_hash(env), token_address)
136 }
137
138 fn linked_token_id(env: &Env, deployer: Address, salt: BytesN<32>) -> BytesN<32> {
139 token_id::linked_token_id(env, Self::chain_name_hash(env), deployer, salt)
140 }
141
142 fn interchain_token_address(env: &Env, token_id: BytesN<32>) -> Address {
143 deployer::interchain_token_address(env, token_id)
144 }
145
146 fn token_manager_address(env: &Env, token_id: BytesN<32>) -> Address {
147 deployer::token_manager_address(env, token_id)
148 }
149
150 fn registered_token_address(env: &Env, token_id: BytesN<32>) -> Address {
151 storage::token_id_config(env, token_id).token_address
152 }
153
154 fn deployed_token_manager(env: &Env, token_id: BytesN<32>) -> Address {
155 storage::token_id_config(env, token_id).token_manager
156 }
157
158 fn token_manager_type(env: &Env, token_id: BytesN<32>) -> TokenManagerType {
159 storage::token_id_config(env, token_id).token_manager_type
160 }
161
162 fn flow_limit(env: &Env, token_id: BytesN<32>) -> Option<i128> {
163 flow_limit::flow_limit(env, token_id)
164 }
165
166 fn flow_out_amount(env: &Env, token_id: BytesN<32>) -> i128 {
167 flow_limit::flow_out_amount(env, token_id)
168 }
169
170 fn flow_in_amount(env: &Env, token_id: BytesN<32>) -> i128 {
171 flow_limit::flow_in_amount(env, token_id)
172 }
173
174 #[only_operator]
175 fn set_flow_limit(
176 env: &Env,
177 token_id: BytesN<32>,
178 flow_limit: Option<i128>,
179 ) -> Result<(), ContractError> {
180 flow_limit::set_flow_limit(env, token_id, flow_limit)
181 }
182
183 #[when_not_paused]
184 fn deploy_interchain_token(
185 env: &Env,
186 caller: Address,
187 salt: BytesN<32>,
188 token_metadata: TokenMetadata,
189 initial_supply: i128,
190 minter: Option<Address>,
191 ) -> Result<BytesN<32>, ContractError> {
192 caller.require_auth();
193
194 ensure!(initial_supply >= 0, ContractError::InvalidInitialSupply);
195 ensure!(
196 initial_supply > 0 || minter.is_some(),
197 ContractError::InvalidTokenConfig
198 );
199
200 let token_id = Self::interchain_token_id(env, caller.clone(), salt);
201
202 token_metadata.validate()?;
203
204 let unregistered_token_id = token_id::ensure_token_not_registered(env, token_id.clone())?;
205
206 let token_address = Self::deploy_token(env, unregistered_token_id, token_metadata, minter)?;
207
208 if initial_supply > 0 {
209 StellarAssetClient::new(env, &token_address).mint(&caller, &initial_supply);
210 }
211
212 Ok(token_id)
213 }
214
215 #[when_not_paused]
216 fn deploy_remote_interchain_token(
217 env: &Env,
218 caller: Address,
219 salt: BytesN<32>,
220 destination_chain: String,
221 gas_token: Option<Token>,
222 ) -> Result<BytesN<32>, ContractError> {
223 caller.require_auth();
224
225 let token_id = Self::interchain_token_id(env, caller.clone(), salt);
226
227 Self::deploy_remote_token(env, caller, token_id.clone(), destination_chain, gas_token)?;
228
229 Ok(token_id)
230 }
231
232 #[when_not_paused]
233 fn register_canonical_token(
234 env: &Env,
235 token_address: Address,
236 ) -> Result<BytesN<32>, ContractError> {
237 let _ =
239 token_metadata::token_metadata(env, &token_address, &Self::native_token_address(env))?;
240
241 let token_id = Self::canonical_interchain_token_id(env, token_address.clone());
242
243 let unregistered_token_id = token_id::ensure_token_not_registered(env, token_id.clone())?;
244
245 let _: Address = Self::deploy_token_manager(
246 env,
247 unregistered_token_id,
248 token_address,
249 TokenManagerType::LockUnlock,
250 );
251
252 Ok(token_id)
253 }
254
255 #[when_not_paused]
256 fn deploy_remote_canonical_token(
257 env: &Env,
258 token_address: Address,
259 destination_chain: String,
260 spender: Address,
261 gas_token: Option<Token>,
262 ) -> Result<BytesN<32>, ContractError> {
263 spender.require_auth();
264
265 let token_id = Self::canonical_interchain_token_id(env, token_address);
266
267 Self::deploy_remote_token(env, spender, token_id.clone(), destination_chain, gas_token)?;
268
269 Ok(token_id)
270 }
271
272 #[when_not_paused]
273 fn register_token_metadata(
274 env: &Env,
275 token_address: Address,
276 spender: Address,
277 gas_token: Option<Token>,
278 ) -> Result<(), ContractError> {
279 spender.require_auth();
280
281 let token_metadata =
282 token_metadata::token_metadata(env, &token_address, &Self::native_token_address(env))?;
283
284 let hub_message = HubMessage::RegisterTokenMetadata(RegisterTokenMetadata {
287 decimals: u8::try_from(token_metadata.decimal).unwrap(),
288 token_address: token_address.to_string_bytes(),
289 });
290
291 Self::send_to_hub(env, spender, hub_message, gas_token)?;
292
293 TokenMetadataRegisteredEvent {
294 token_address,
295 decimals: token_metadata.decimal,
296 }
297 .emit(env);
298
299 Ok(())
300 }
301
302 #[when_not_paused]
303 fn register_custom_token(
304 env: &Env,
305 deployer: Address,
306 salt: BytesN<32>,
307 token_address: Address,
308 token_manager_type: TokenManagerType,
309 ) -> Result<BytesN<32>, ContractError> {
310 deployer.require_auth();
311
312 ensure!(
314 token_manager_type != TokenManagerType::NativeInterchainToken,
315 ContractError::InvalidTokenManagerType
316 );
317
318 let _ =
320 token_metadata::token_metadata(env, &token_address, &Self::native_token_address(env))?;
321
322 let token_id = Self::linked_token_id(env, deployer, salt);
323
324 let unregistered_token_id = token_id::ensure_token_not_registered(env, token_id.clone())?;
325
326 let _: Address = Self::deploy_token_manager(
327 env,
328 unregistered_token_id,
329 token_address,
330 token_manager_type,
331 );
332
333 Ok(token_id)
334 }
335
336 #[when_not_paused]
337 fn link_token(
338 env: &Env,
339 deployer: Address,
340 salt: BytesN<32>,
341 destination_chain: String,
342 destination_token_address: Bytes,
343 token_manager_type: TokenManagerType,
344 link_params: Option<Bytes>,
345 gas_token: Option<Token>,
346 ) -> Result<BytesN<32>, ContractError> {
347 deployer.require_auth();
348
349 ensure!(
350 !destination_token_address.is_empty(),
351 ContractError::InvalidDestinationTokenAddress
352 );
353
354 ensure!(
356 token_manager_type != TokenManagerType::NativeInterchainToken,
357 ContractError::InvalidTokenManagerType
358 );
359
360 let token_id = Self::linked_token_id(env, deployer.clone(), salt);
361 let token_address = Self::token_id_config(env, token_id.clone())?.token_address;
362
363 let message = Message::LinkToken(LinkToken {
364 token_id: token_id.clone(),
365 token_manager_type,
366 source_token_address: token_address.to_string_bytes(),
367 destination_token_address: destination_token_address.clone(),
368 params: link_params.clone(),
369 });
370
371 LinkTokenStartedEvent {
372 token_id: token_id.clone(),
373 destination_chain: destination_chain.clone(),
374 source_token_address: token_address.to_string_bytes(),
375 destination_token_address,
376 token_manager_type,
377 params: link_params,
378 }
379 .emit(env);
380
381 Self::pay_gas_and_call_contract(env, deployer, destination_chain, message, gas_token)?;
382
383 Ok(token_id)
384 }
385
386 #[when_not_paused]
387 fn interchain_transfer(
388 env: &Env,
389 caller: Address,
390 token_id: BytesN<32>,
391 destination_chain: String,
392 destination_address: Bytes,
393 amount: i128,
394 data: Option<Bytes>,
395 gas_token: Option<Token>,
396 ) -> Result<(), ContractError> {
397 ensure!(amount > 0, ContractError::InvalidAmount);
398
399 ensure!(
400 !destination_address.is_empty(),
401 ContractError::InvalidDestinationAddress
402 );
403
404 if let Some(ref data) = data {
405 ensure!(!data.is_empty(), ContractError::InvalidData);
406 }
407
408 caller.require_auth();
409
410 token_handler::take_token(
411 env,
412 &caller,
413 Self::token_id_config(env, token_id.clone())?,
414 amount,
415 )?;
416
417 FlowDirection::Out.add_flow(env, token_id.clone(), amount)?;
418
419 InterchainTransferSentEvent {
420 token_id: token_id.clone(),
421 source_address: caller.clone(),
422 destination_chain: destination_chain.clone(),
423 destination_address: destination_address.clone(),
424 amount,
425 data_hash: data
426 .as_ref()
427 .map(|data| env.crypto().keccak256(data).into()),
428 }
429 .emit(env);
430
431 let message = Message::InterchainTransfer(InterchainTransfer {
432 token_id,
433 source_address: caller.to_string_bytes(),
434 destination_address,
435 amount,
436 data,
437 });
438
439 Self::pay_gas_and_call_contract(env, caller, destination_chain, message, gas_token)?;
440
441 Ok(())
442 }
443
444 #[only_owner]
445 fn transfer_token_admin(
446 env: &Env,
447 token_id: BytesN<32>,
448 new_admin: Address,
449 ) -> Result<(), ContractError> {
450 let TokenIdConfigValue {
451 token_address,
452 token_manager_type,
453 token_manager,
454 } = Self::token_id_config(env, token_id)?;
455
456 ensure!(
457 token_manager_type == TokenManagerType::MintBurn,
458 ContractError::InvalidTokenManagerType
459 );
460
461 TokenManagerClient::new(env, &token_manager).set_admin(env, &token_address, &new_admin);
462
463 Ok(())
464 }
465}
466
467impl InterchainTokenService {
468 fn send_to_hub(
469 env: &Env,
470 spender: Address,
471 hub_message: HubMessage,
472 gas_token: Option<Token>,
473 ) -> Result<(), ContractError> {
474 let gateway = AxelarGatewayMessagingClient::new(env, &Self::gateway(env));
475 let gas_service = AxelarGasServiceClient::new(env, &Self::gas_service(env));
476
477 let hub_chain = Self::its_hub_chain_name(env);
478 let hub_address = Self::its_hub_address(env);
479
480 let payload = hub_message.abi_encode(env)?;
481
482 if let Some(gas_token) = gas_token {
483 gas_service.pay_gas(
484 &env.current_contract_address(),
485 &hub_chain,
486 &hub_address,
487 &payload,
488 &spender,
489 &gas_token,
490 &Bytes::new(env),
491 );
492 }
493
494 gateway.call_contract(
495 &env.current_contract_address(),
496 &hub_chain,
497 &hub_address,
498 &payload,
499 );
500
501 Ok(())
502 }
503
504 fn pay_gas_and_call_contract(
505 env: &Env,
506 caller: Address,
507 destination_chain: String,
508 message: Message,
509 gas_token: Option<Token>,
510 ) -> Result<(), ContractError> {
511 if !matches!(message, Message::InterchainTransfer(_)) {
515 ensure!(
516 destination_chain != Self::chain_name(env),
517 ContractError::InvalidDestinationChain
518 );
519 }
520
521 ensure!(
522 Self::is_trusted_chain(env, destination_chain.clone()),
523 ContractError::UntrustedChain
524 );
525
526 let hub_message = HubMessage::SendToHub {
527 destination_chain,
528 message,
529 };
530
531 Self::send_to_hub(env, caller, hub_message, gas_token)?;
532
533 Ok(())
534 }
535
536 fn get_execute_params(
538 env: &Env,
539 source_chain: String,
540 source_address: String,
541 payload: Bytes,
542 ) -> Result<(String, Message), ContractError> {
543 ensure!(
544 source_chain == Self::its_hub_chain_name(env),
545 ContractError::NotHubChain
546 );
547 ensure!(
548 source_address == Self::its_hub_address(env),
549 ContractError::NotHubAddress
550 );
551
552 let HubMessage::ReceiveFromHub {
553 source_chain: original_source_chain,
554 message,
555 } = HubMessage::abi_decode(env, &payload)?
556 else {
557 return Err(ContractError::InvalidMessageType);
558 };
559 ensure!(
560 storage::is_trusted_chain(env, original_source_chain.clone()),
561 ContractError::UntrustedChain
562 );
563
564 Ok((original_source_chain, message))
565 }
566
567 fn set_token_id_config(env: &Env, token_id: BytesN<32>, token_data: TokenIdConfigValue) {
568 storage::set_token_id_config(env, token_id, &token_data);
569 }
570
571 fn token_id_config(
582 env: &Env,
583 token_id: BytesN<32>,
584 ) -> Result<TokenIdConfigValue, ContractError> {
585 storage::try_token_id_config(env, token_id).ok_or(ContractError::InvalidTokenId)
586 }
587
588 fn chain_name_hash(env: &Env) -> BytesN<32> {
589 let chain_name = Self::chain_name(env);
590 env.crypto().keccak256(&chain_name.to_xdr(env)).into()
591 }
592
593 fn deploy_remote_token(
614 env: &Env,
615 caller: Address,
616 token_id: BytesN<32>,
617 destination_chain: String,
618 gas_token: Option<Token>,
619 ) -> Result<(), ContractError> {
620 let token_address = Self::token_id_config(env, token_id.clone())?.token_address;
621 let TokenMetadata {
622 name,
623 symbol,
624 decimal,
625 } = token_metadata::token_metadata(env, &token_address, &Self::native_token_address(env))?;
626
627 let message = Message::DeployInterchainToken(DeployInterchainToken {
628 token_id: token_id.clone(),
629 name: name.clone(),
630 symbol: symbol.clone(),
631 decimals: decimal as u8,
632 minter: None,
633 });
634
635 InterchainTokenDeploymentStartedEvent {
636 token_id,
637 token_address,
638 destination_chain: destination_chain.clone(),
639 name,
640 symbol,
641 decimals: decimal,
642 minter: None,
643 }
644 .emit(env);
645
646 Self::pay_gas_and_call_contract(env, caller, destination_chain, message, gas_token)?;
647
648 Ok(())
649 }
650
651 fn execute_transfer_message(
652 env: &Env,
653 source_chain: &String,
654 message_id: String,
655 InterchainTransfer {
656 token_id,
657 source_address,
658 destination_address,
659 amount,
660 data,
661 }: InterchainTransfer,
662 ) -> Result<(), ContractError> {
663 ensure!(amount > 0, ContractError::InvalidAmount);
664
665 let destination_address = Address::from_string_bytes(&destination_address);
666
667 let token_config_value = Self::token_id_config(env, token_id.clone())?;
668 let token_address = token_config_value.token_address.clone();
669
670 FlowDirection::In.add_flow(env, token_id.clone(), amount)?;
671
672 token_handler::give_token(env, &destination_address, token_config_value, amount)?;
673
674 InterchainTransferReceivedEvent {
675 source_chain: source_chain.clone(),
676 token_id: token_id.clone(),
677 source_address: source_address.clone(),
678 destination_address: destination_address.clone(),
679 amount,
680 data_hash: data
681 .as_ref()
682 .map(|data| env.crypto().keccak256(data).into()),
683 }
684 .emit(env);
685
686 if let Some(payload) = data {
687 Self::execute_contract_with_token(
688 env,
689 destination_address,
690 source_chain,
691 message_id,
692 source_address,
693 payload,
694 token_id,
695 token_address,
696 amount,
697 );
698 }
699
700 Ok(())
701 }
702
703 fn execute_contract_with_token(
704 env: &Env,
705 destination_address: Address,
706 source_chain: &String,
707 message_id: String,
708 source_address: Bytes,
709 payload: Bytes,
710 token_id: BytesN<32>,
711 token_address: Address,
712 amount: i128,
713 ) {
714 env.invoke_contract::<Val>(
717 &destination_address,
718 &Symbol::new(env, EXECUTE_WITH_INTERCHAIN_TOKEN),
719 vec![
720 env,
721 source_chain.to_val(),
722 message_id.to_val(),
723 source_address.to_val(),
724 payload.to_val(),
725 token_id.to_val(),
726 token_address.to_val(),
727 amount.into_val(env),
728 ],
729 );
730 }
731
732 fn execute_deploy_message(
733 env: &Env,
734 DeployInterchainToken {
735 token_id,
736 name,
737 symbol,
738 decimals,
739 minter,
740 }: DeployInterchainToken,
741 ) -> Result<(), ContractError> {
742 let token_metadata = TokenMetadata::new(name, symbol, decimals as u32)?;
743
744 let minter = minter.map(|m| Address::from_string_bytes(&m));
746
747 let unregistered_token_id = token_id::ensure_token_not_registered(env, token_id)?;
748 let _: Address = Self::deploy_token(env, unregistered_token_id, token_metadata, minter)?;
749
750 Ok(())
751 }
752
753 fn execute_link_token_message(
754 env: &Env,
755 source_chain: String,
756 LinkToken {
757 token_id,
758 token_manager_type,
759 source_token_address,
760 destination_token_address,
761 params,
762 }: LinkToken,
763 ) -> Result<(), ContractError> {
764 let token_address = Address::from_string_bytes(&destination_token_address);
765
766 let _ =
768 token_metadata::token_metadata(env, &token_address, &Self::native_token_address(env))?;
769
770 let unregistered_token_id = token_id::ensure_token_not_registered(env, token_id)?;
771
772 let _: Address = Self::deploy_token_manager(
773 env,
774 unregistered_token_id.clone(),
775 token_address,
776 token_manager_type,
777 );
778
779 LinkTokenReceivedEvent {
780 source_chain,
781 token_id: unregistered_token_id.into(),
782 source_token_address,
783 destination_token_address,
784 token_manager_type,
785 params,
786 }
787 .emit(env);
788
789 Ok(())
790 }
791
792 fn deploy_token_manager(
793 env: &Env,
794 unregistered_token_id: UnregisteredTokenId,
795 token_address: Address,
796 token_manager_type: TokenManagerType,
797 ) -> Address {
798 let token_id: BytesN<32> = unregistered_token_id.into();
799 let token_manager = deployer::deploy_token_manager(
800 env,
801 Self::token_manager_wasm_hash(env),
802 token_id.clone(),
803 token_address.clone(),
804 token_manager_type,
805 );
806
807 Self::set_token_id_config(
808 env,
809 token_id,
810 TokenIdConfigValue {
811 token_address: token_address.clone(),
812 token_manager: token_manager.clone(),
813 token_manager_type,
814 },
815 );
816
817 token_handler::post_token_manager_deploy(
818 env,
819 token_manager_type,
820 token_manager.clone(),
821 token_address,
822 );
823
824 token_manager
825 }
826
827 fn deploy_token(
834 env: &Env,
835 unregistered_token_id: UnregisteredTokenId,
836 token_metadata: TokenMetadata,
837 minter: Option<Address>,
838 ) -> Result<Address, ContractError> {
839 let token_address = deployer::deploy_interchain_token(
840 env,
841 Self::interchain_token_wasm_hash(env),
842 minter,
843 unregistered_token_id.clone(),
844 token_metadata,
845 );
846
847 Self::deploy_token_manager(
848 env,
849 unregistered_token_id,
850 token_address.clone(),
851 TokenManagerType::NativeInterchainToken,
852 );
853
854 Ok(token_address)
855 }
856}
857
858impl CustomAxelarExecutable for InterchainTokenService {
859 type Error = ContractError;
860
861 fn __gateway(env: &Env) -> Address {
862 storage::gateway(env)
863 }
864
865 #[when_not_paused]
866 fn __execute(
867 env: &Env,
868 source_chain: String,
869 message_id: String,
870 source_address: String,
871 payload: Bytes,
872 ) -> Result<(), Self::Error> {
873 let (source_chain, message) =
874 Self::get_execute_params(env, source_chain, source_address, payload)?;
875
876 match message {
877 Message::InterchainTransfer(message) => {
878 Self::execute_transfer_message(env, &source_chain, message_id, message)
879 }
880 Message::DeployInterchainToken(message) => Self::execute_deploy_message(env, message),
881 Message::LinkToken(message) => {
882 Self::execute_link_token_message(env, source_chain, message)
883 }
884 }?;
885
886 Ok(())
887 }
888}