1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
use soroban_sdk::{contractclient, Address, Bytes, BytesN, Env, String};
use soroban_token_sdk::metadata::TokenMetadata;
use stellar_axelar_gateway::executable::AxelarExecutableInterface;
use stellar_axelar_std::types::Token;
use crate::error::ContractError;
use crate::types::TokenManagerType;
#[allow(dead_code)]
#[contractclient(name = "InterchainTokenServiceClient")]
pub trait InterchainTokenServiceInterface: AxelarExecutableInterface {
/// Returns the address of the Gas Service contract.
fn gas_service(env: &Env) -> Address;
/// Returns the name of the current chain.
fn chain_name(env: &Env) -> String;
/// Returns the name of the chain on which the ITS Hub is deployed.
fn its_hub_chain_name(env: &Env) -> String;
/// Returns the address of the ITS Hub.
fn its_hub_address(env: &Env) -> String;
/// Returns the address of the native token on the current chain.
fn native_token_address(env: &Env) -> Address;
/// Returns the WASM hash of the token contract used for deploying interchain tokens.
fn interchain_token_wasm_hash(env: &Env) -> BytesN<32>;
/// Returns whether the specified chain is trusted for cross-chain messaging.
fn is_trusted_chain(env: &Env, chain: String) -> bool;
/// Sets the specified chain as trusted for cross-chain messaging.
/// # Authorization
/// - Must be called by [`Self::owner`].
fn set_trusted_chain(env: &Env, chain: String) -> Result<(), ContractError>;
/// Removes the specified chain from trusted chains.
/// # Authorization
/// - Must be called by the [`Self::owner`].
fn remove_trusted_chain(env: &Env, chain: String) -> Result<(), ContractError>;
/// Computes a 32-byte deployment salt for a new interchain token.
///
/// The deployment salt is derived uniquely for the given chain, deployer, and salt combination.
///
/// # Parameters
/// - `deployer`: The address of the token deployer.
/// - `salt`: A unique value provided by the deployer.
///
/// # Returns
/// - A `BytesN<32>` value representing the computed deployment salt.
fn interchain_token_deploy_salt(env: &Env, deployer: Address, salt: BytesN<32>) -> BytesN<32>;
/// Computes the unique identifier for an interchain token.
///
/// The token ID is derived uniquely from the sender's address and the provided salt.
///
/// # Parameters
/// - `sender`: The address of the token deployer. In the case of tokens deployed by this contract, it will be Stellar's "dead" address.
/// - `salt`: A unique value used to generate the token ID.
///
/// # Returns
/// - A `BytesN<32>` value representing the token's unique ID.
fn interchain_token_id(env: &Env, sender: Address, salt: BytesN<32>) -> BytesN<32>;
/// Computes a 32-byte deployment salt for a canonical token.
///
/// The salt is derived uniquely from the chain name hash and token address.
///
/// # Parameters
/// - `token_address`: The address of the token for which the deployment salt is being generated.
///
/// # Returns
/// - A `BytesN<32>` value representing the computed deployment salt.
fn canonical_token_deploy_salt(env: &Env, token_address: Address) -> BytesN<32>;
/// Returns the address of the token associated with the specified token ID.
fn token_address(env: &Env, token_id: BytesN<32>) -> Address;
/// Returns the type of the token manager associated with the specified token ID.
fn token_manager_type(env: &Env, token_id: BytesN<32>) -> TokenManagerType;
/// Returns whether the contract is paused.
fn is_paused(env: &Env) -> bool;
/// Returns the flow limit for the token associated with the specified token ID.
/// Returns `None` if no limit is set.
fn flow_limit(env: &Env, token_id: BytesN<32>) -> Option<i128>;
/// Returns the amount that has flowed out of the chain to other chains during the current epoch
/// for the token associated with the specified token ID.
fn flow_out_amount(env: &Env, token_id: BytesN<32>) -> i128;
/// Retrieves the amount that has flowed into the chain from other chains during the current epoch
/// for the token associated with the specified token ID.
fn flow_in_amount(env: &Env, token_id: BytesN<32>) -> i128;
/// Sets or updates the flow limit for a token.
///
/// Flow limit controls how many tokens can flow in/out during a single epoch.
/// Setting the limit to `None` disables flow limit checks for the token.
/// Setting the limit to 0 effectively freezes the token by preventing any flow.
///
/// # Arguments
/// - `token_id`: Unique identifier of the token.
/// - `flow_limit`: The new flow limit value. Must be positive if Some.
///
/// # Errors
/// - `ContractError::InvalidFlowLimit`: If the provided flow limit is not positive.
///
/// # Authorization
/// - Must be called by [`Self::operator`].
fn set_flow_limit(
env: &Env,
token_id: BytesN<32>,
flow_limit: Option<i128>,
) -> Result<(), ContractError>;
/// Sets the pause status of the contract.
/// # Authorization
/// - Must be called by [`Self::owner`].
fn set_pause_status(env: &Env, paused: bool) -> Result<(), ContractError>;
/// Deploys a new interchain token on the current chain with specified metadata and optional
/// initial supply. If initial supply is provided, it is minted to the caller. The
/// caller can also specify an optional minter address for the interchain token.
///
/// # Arguments
/// - `caller`: Address of the caller initiating the deployment.
/// - `salt`: A 32-byte unique salt used for token deployment.
/// - `token_metadata`: Metadata for the new token (name, symbol, decimals).
/// - `initial_supply`: Initial amount to mint to caller, if greater than 0.
/// - `minter`: Optional address that will have a minter role for the deployed interchain token.
///
/// # Returns
/// - `Ok(BytesN<32>)`: Returns the token ID.
///
/// # Errors
/// - `ContractError::InvalidMinter`: If the minter address is invalid.
///
/// # Authorization
/// - The `deployer` must authenticate.
fn deploy_interchain_token(
env: &Env,
deployer: Address,
salt: BytesN<32>,
token_metadata: TokenMetadata,
initial_supply: i128,
minter: Option<Address>,
) -> Result<BytesN<32>, ContractError>;
/// Initiates the deployment of an interchain token to a specified destination chain.
///
/// # Arguments
/// - `caller`: Address of the caller initiating the deployment.
/// - `salt`: A 32-byte unique salt used for token deployment.
/// - `destination_chain`: The name of the destination chain where the token will be deployed.
/// - `gas_token`: The token used to pay for the gas cost of the cross-chain call.
///
/// # Returns
/// - `Ok(BytesN<32>)`: Returns the token ID.
///
/// # Errors
/// - `ContractError::InvalidTokenId`: If the token ID does not exist in the persistent storage.
/// - Any error propagated from `pay_gas_and_call_contract`.
///
/// # Authorization
/// - The `caller` must authenticate.
fn deploy_remote_interchain_token(
env: &Env,
caller: Address,
salt: BytesN<32>,
destination_chain: String,
gas_token: Token,
) -> Result<BytesN<32>, ContractError>;
/// Registers a canonical token as an interchain token.
///
/// # Arguments
/// - `token_address` - The address of the canonical token.
///
/// # Returns
/// - `Ok(BytesN<32>)`: Returns the token ID.
///
/// # Errors
/// - `ContractError::TokenAlreadyRegistered`: If the token ID is already registered.
fn register_canonical_token(
env: &Env,
token_address: Address,
) -> Result<BytesN<32>, ContractError>;
/// Deploys a remote canonical token on a specified destination chain.
///
/// Anyone can call this to deploy a trustless canonical representation of the token to any trusted destination chain.
/// If the token name is longer than 32 characters, the symbol will be used as the name.
/// Specifically, natively issued Stellar assets will be deployed with the symbol as the name.
///
/// # Arguments
/// * `token_address` - The address of the token to be deployed.
/// * `destination_chain` - The name of the destination chain where the token will be deployed.
/// * `spender` - The spender of the cross-chain gas.
/// * `gas_token` - The token used to pay for gas during the deployment.
///
/// # Returns
/// - `Ok(BytesN<32>)`: Returns the token ID.
///
/// # Errors
/// - `ContractError::InvalidTokenId`: If the token ID does not exist in the persistent storage.
/// - Any error propagated from `pay_gas_and_call_contract`.
///
/// # Authorization
/// - `spender` needs to authorize `pay_gas` call to the gas service.
fn deploy_remote_canonical_token(
env: &Env,
token_address: Address,
destination_chain: String,
spender: Address,
gas_token: Token,
) -> Result<BytesN<32>, ContractError>;
/// Initiates a cross-chain token transfer.
///
/// Takes tokens from the caller on the source chain and initiates a transfer
/// to the specified destination chain. The tokens will be transferred to the destination address
/// when the message is executed on the destination chain.
///
/// If `data` is provided, the `destination_address` will also be executed as a contract with the
/// `data` to allow arbitrary processing of the transferred tokens.
///
/// # Arguments
/// - `caller`: The address initiating the transfer.
/// - `token_id`: The unique identifier of the token being transferred.
/// - `destination_chain`: The chain to which tokens will be transferred.
/// - `destination_address`: The recipient address on the destination chain.
/// - `amount`: The amount of tokens to transfer. Must be greater than 0.
/// - `data`: Optional data to be handled by the destination address if it's a contract.
/// - `gas_token`: The token used to pay for cross-chain message execution.
///
/// # Returns
/// - `Ok(())`
///
/// # Errors
/// - `ContractError::InvalidAmount`: If amount is not greater than 0.
/// - `ContractError::FlowLimitExceeded`: If transfer would exceed flow limits.
/// - Any error propagated from `pay_gas_and_call_contract`.
///
/// # Authorization
/// - The `caller` must authenticate.
fn interchain_transfer(
env: &Env,
caller: Address,
token_id: BytesN<32>,
destination_chain: String,
destination_address: Bytes,
amount: i128,
metadata: Option<Bytes>,
gas_token: Token,
) -> Result<(), ContractError>;
}