soroban_sdk/token.rs
1//! Token contains types for calling and accessing token contracts, including
2//! the Stellar Asset Contract.
3//!
4//! See [`TokenInterface`] for the interface of token contracts such as the
5//! Stellar Asset Contract.
6//!
7//! Use [`TokenClient`] for calling token contracts such as the Stellar Asset
8//! Contract.
9
10use crate::{contracttrait, Address, Env, MuxedAddress, String};
11
12// The interface below was copied from
13// https://github.com/stellar/rs-soroban-env/blob/main/soroban-env-host/src/native_contract/token/contract.rs
14// at commit b3c188f48dec51a956c1380fb6fe92201a3f716b.
15//
16// Differences between this interface and the built-in contract
17// 1. The return values here don't return Results.
18// 2. The implementations have been replaced with a panic.
19// 3. &Host type usage are replaced with Env
20
21#[doc(hidden)]
22#[deprecated(note = "use TokenInterface")]
23pub use TokenInterface as Interface;
24
25#[doc(hidden)]
26#[deprecated(note = "use TokenClient")]
27pub use TokenClient as Client;
28
29/// Interface for Token contracts, such as the Stellar Asset Contract.
30///
31/// Defined by [SEP-41].
32///
33/// [SEP-41]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0041.md
34///
35/// The token interface provides the following functionality.
36///
37/// If a contract implementing the interface does not support some of the
38/// functionality, it should return an error.
39///
40/// The interface does not define any set of standard errors. Errors can be
41/// defined by the implementing contract.
42///
43/// ## Meta
44///
45/// Tokens implementing the interface expose meta functions about the token:
46/// - [`decimals`][Self::decimals]
47/// - [`name`][Self::name]
48/// - [`symbol`][Self::symbol]
49///
50/// ## Balances
51///
52/// Tokens track a balance for each address that holds the token. Tokens implementing the interface expose
53/// a single function for getting the balance that an address holds:
54/// - [`balance`][Self::balance]
55///
56/// ## Transfers
57///
58/// Tokens allow holders of the token to transfer tokens to other addresses.
59/// Tokens implementing the interface expose a single function for doing so:
60/// - [`transfer`][Self::transfer]
61///
62/// ## Burning
63///
64/// Tokens allow holders of the token to burn, i.e. dispose of, tokens without
65/// transferring them to another holder. Tokens implementing the interface
66/// expose a single function for doing so:
67/// - [`burn`][Self::burn]
68///
69/// ## Allowances
70///
71/// Tokens can allow holders to permit others to transfer amounts from their
72/// balance using the following functions.
73/// - [`allowance`][Self::allowance]
74/// - [`approve`][Self::approve]
75/// - [`transfer_from`][Self::transfer_from]
76/// - [`burn_from`][Self::burn_from]
77///
78/// ## Minting
79///
80/// There are no functions in the token interface for minting tokens. Minting is
81/// an administrative function that can differ significantly from one token to
82/// the next.
83#[contracttrait(
84 crate_path = "crate",
85 spec_name = "TokenFnSpec",
86 spec_export = false,
87 args_name = "TokenArgs",
88 client_name = "TokenClient"
89)]
90pub trait TokenInterface {
91 /// Returns the allowance for `spender` to transfer from `from`.
92 ///
93 /// The amount returned is the amount that spender is allowed to transfer
94 /// out of from's balance. When the spender transfers amounts, the allowance
95 /// will be reduced by the amount transferred.
96 ///
97 /// # Arguments
98 ///
99 /// * `from` - The address holding the balance of tokens to be drawn from.
100 /// * `spender` - The address spending the tokens held by `from`.
101 fn allowance(env: Env, from: Address, spender: Address) -> i128;
102
103 /// Set the allowance by `amount` for `spender` to transfer/burn from
104 /// `from`.
105 ///
106 /// The amount set is the amount that spender is approved to transfer out of
107 /// from's balance. The spender will be allowed to transfer amounts, and
108 /// when an amount is transferred the allowance will be reduced by the
109 /// amount transferred.
110 ///
111 /// # Arguments
112 ///
113 /// * `from` - The address holding the balance of tokens to be drawn from.
114 /// * `spender` - The address being authorized to spend the tokens held by
115 /// `from`.
116 /// * `amount` - The tokens to be made available to `spender`.
117 /// * `expiration_ledger` - The ledger number where this allowance expires. Cannot
118 /// be less than the current ledger number unless the amount is being set to 0.
119 /// An expired entry (where expiration_ledger < the current ledger number)
120 /// should be treated as a 0 amount allowance.
121 ///
122 /// # Events
123 ///
124 /// Emits an event with topics `["approve", from: Address,
125 /// spender: Address], data = [amount: i128, expiration_ledger: u32]`
126 fn approve(env: Env, from: Address, spender: Address, amount: i128, expiration_ledger: u32);
127
128 /// Returns the balance of `id`.
129 ///
130 /// # Arguments
131 ///
132 /// * `id` - The address for which a balance is being queried. If the
133 /// address has no existing balance, returns 0.
134 fn balance(env: Env, id: Address) -> i128;
135
136 /// Transfer `amount` from `from` to `to`.
137 ///
138 /// # Arguments
139 ///
140 /// * `from` - The address holding the balance of tokens which will be
141 /// withdrawn from.
142 /// * `to` - The address which will receive the transferred tokens.
143 /// * `amount` - The amount of tokens to be transferred.
144 ///
145 /// # Events
146 ///
147 /// Emits an event with:
148 /// * topics `["transfer", from: Address, to: Address]`
149 /// * data `{ to_muxed_id: Option<u64>, amount: i128 }: Map`
150 ///
151 /// Legacy implementations may emit an event with:
152 /// * topics `["transfer", from: Address, to: Address]`
153 /// * data `amount: i128`
154 fn transfer(env: Env, from: Address, to: MuxedAddress, amount: i128);
155
156 /// Transfer `amount` from `from` to `to`, consuming the allowance that
157 /// `spender` has on `from`'s balance. Authorized by spender
158 /// (`spender.require_auth()`).
159 ///
160 /// The spender will be allowed to transfer the amount from from's balance
161 /// if the amount is less than or equal to the allowance that the spender
162 /// has on the from's balance. The spender's allowance on from's balance
163 /// will be reduced by the amount.
164 ///
165 /// # Arguments
166 ///
167 /// * `spender` - The address authorizing the transfer, and having its
168 /// allowance consumed during the transfer.
169 /// * `from` - The address holding the balance of tokens which will be
170 /// withdrawn from.
171 /// * `to` - The address which will receive the transferred tokens.
172 /// * `amount` - The amount of tokens to be transferred.
173 ///
174 /// # Events
175 ///
176 /// Emits an event with topics `["transfer", from: Address, to: Address],
177 /// data = amount: i128`
178 fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);
179
180 /// Burn `amount` from `from`.
181 ///
182 /// Reduces from's balance by the amount, without transferring the balance
183 /// to another holder's balance.
184 ///
185 /// # Arguments
186 ///
187 /// * `from` - The address holding the balance of tokens which will be
188 /// burned from.
189 /// * `amount` - The amount of tokens to be burned.
190 ///
191 /// # Events
192 ///
193 /// Emits an event with topics `["burn", from: Address], data = amount:
194 /// i128`
195 fn burn(env: Env, from: Address, amount: i128);
196
197 /// Burn `amount` from `from`, consuming the allowance of `spender`.
198 ///
199 /// Reduces from's balance by the amount, without transferring the balance
200 /// to another holder's balance.
201 ///
202 /// The spender will be allowed to burn the amount from from's balance, if
203 /// the amount is less than or equal to the allowance that the spender has
204 /// on the from's balance. The spender's allowance on from's balance will be
205 /// reduced by the amount.
206 ///
207 /// # Arguments
208 ///
209 /// * `spender` - The address authorizing the burn, and having its allowance
210 /// consumed during the burn.
211 /// * `from` - The address holding the balance of tokens which will be
212 /// burned from.
213 /// * `amount` - The amount of tokens to be burned.
214 ///
215 /// # Events
216 ///
217 /// Emits an event with topics `["burn", from: Address], data = amount:
218 /// i128`
219 fn burn_from(env: Env, spender: Address, from: Address, amount: i128);
220
221 /// Returns the number of decimals used to represent amounts of this token.
222 ///
223 /// # Panics
224 ///
225 /// If the contract has not yet been initialized.
226 fn decimals(env: Env) -> u32;
227
228 /// Returns the name for this token.
229 ///
230 /// # Panics
231 ///
232 /// If the contract has not yet been initialized.
233 fn name(env: Env) -> String;
234
235 /// Returns the symbol for this token.
236 ///
237 /// # Panics
238 ///
239 /// If the contract has not yet been initialized.
240 fn symbol(env: Env) -> String;
241}
242
243/// Interface for admin capabilities for Token contracts, such as the Stellar
244/// Asset Contract.
245#[contracttrait(
246 crate_path = "crate",
247 spec_name = "StellarAssetFnSpec",
248 spec_export = false,
249 args_name = "StellarAssetArgs",
250 client_name = "StellarAssetClient"
251)]
252pub trait StellarAssetInterface {
253 /// Returns the allowance for `spender` to transfer from `from`.
254 ///
255 /// The amount returned is the amount that spender is allowed to transfer
256 /// out of from's balance. When the spender transfers amounts, the allowance
257 /// will be reduced by the amount transferred.
258 ///
259 /// # Arguments
260 ///
261 /// * `from` - The address holding the balance of tokens to be drawn from.
262 /// * `spender` - The address spending the tokens held by `from`.
263 fn allowance(env: Env, from: Address, spender: Address) -> i128;
264
265 /// Set the allowance by `amount` for `spender` to transfer/burn from
266 /// `from`.
267 ///
268 /// The amount set is the amount that spender is approved to transfer out of
269 /// from's balance. The spender will be allowed to transfer amounts, and
270 /// when an amount is transferred the allowance will be reduced by the
271 /// amount transferred.
272 ///
273 /// # Arguments
274 ///
275 /// * `from` - The address holding the balance of tokens to be drawn from.
276 /// * `spender` - The address being authorized to spend the tokens held by
277 /// `from`.
278 /// * `amount` - The tokens to be made available to `spender`.
279 /// * `expiration_ledger` - The ledger number where this allowance expires. Cannot
280 /// be less than the current ledger number unless the amount is being set to 0.
281 /// An expired entry (where expiration_ledger < the current ledger number)
282 /// should be treated as a 0 amount allowance.
283 ///
284 /// # Events
285 ///
286 /// Emits an event with topics `["approve", from: Address,
287 /// spender: Address], data = [amount: i128, expiration_ledger: u32]`
288 fn approve(env: Env, from: Address, spender: Address, amount: i128, expiration_ledger: u32);
289
290 /// Returns the balance of `id`.
291 ///
292 /// # Arguments
293 ///
294 /// * `id` - The address for which a balance is being queried. If the
295 /// address has no existing balance, returns 0.
296 fn balance(env: Env, id: Address) -> i128;
297
298 /// Transfer `amount` from `from` to `to`.
299 ///
300 /// # Arguments
301 ///
302 /// * `from` - The address holding the balance of tokens which will be
303 /// withdrawn from.
304 /// * `to` - The address which will receive the transferred tokens.
305 /// * `amount` - The amount of tokens to be transferred.
306 ///
307 /// # Events
308 ///
309 /// Emits an event with:
310 /// * topics `["transfer", from: Address, to: Address]`
311 /// * data `{ to_muxed_id: Option<u64>, amount: i128 }: Map`
312 ///
313 /// Legacy implementations may emit an event with:
314 /// * topics `["transfer", from: Address, to: Address]`
315 /// * data `amount: i128`
316 fn transfer(env: Env, from: Address, to: MuxedAddress, amount: i128);
317
318 /// Transfer `amount` from `from` to `to`, consuming the allowance that
319 /// `spender` has on `from`'s balance. Authorized by spender
320 /// (`spender.require_auth()`).
321 ///
322 /// The spender will be allowed to transfer the amount from from's balance
323 /// if the amount is less than or equal to the allowance that the spender
324 /// has on the from's balance. The spender's allowance on from's balance
325 /// will be reduced by the amount.
326 ///
327 /// # Arguments
328 ///
329 /// * `spender` - The address authorizing the transfer, and having its
330 /// allowance consumed during the transfer.
331 /// * `from` - The address holding the balance of tokens which will be
332 /// withdrawn from.
333 /// * `to` - The address which will receive the transferred tokens.
334 /// * `amount` - The amount of tokens to be transferred.
335 ///
336 /// # Events
337 ///
338 /// Emits an event with topics `["transfer", from: Address, to: Address],
339 /// data = amount: i128`
340 fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);
341
342 /// Burn `amount` from `from`.
343 ///
344 /// Reduces from's balance by the amount, without transferring the balance
345 /// to another holder's balance.
346 ///
347 /// # Arguments
348 ///
349 /// * `from` - The address holding the balance of tokens which will be
350 /// burned from.
351 /// * `amount` - The amount of tokens to be burned.
352 ///
353 /// # Events
354 ///
355 /// Emits an event with topics `["burn", from: Address], data = amount:
356 /// i128`
357 fn burn(env: Env, from: Address, amount: i128);
358
359 /// Burn `amount` from `from`, consuming the allowance of `spender`.
360 ///
361 /// Reduces from's balance by the amount, without transferring the balance
362 /// to another holder's balance.
363 ///
364 /// The spender will be allowed to burn the amount from from's balance, if
365 /// the amount is less than or equal to the allowance that the spender has
366 /// on the from's balance. The spender's allowance on from's balance will be
367 /// reduced by the amount.
368 ///
369 /// # Arguments
370 ///
371 /// * `spender` - The address authorizing the burn, and having its allowance
372 /// consumed during the burn.
373 /// * `from` - The address holding the balance of tokens which will be
374 /// burned from.
375 /// * `amount` - The amount of tokens to be burned.
376 ///
377 /// # Events
378 ///
379 /// Emits an event with topics `["burn", from: Address], data = amount:
380 /// i128`
381 fn burn_from(env: Env, spender: Address, from: Address, amount: i128);
382
383 /// Returns the number of decimals used to represent amounts of this token.
384 ///
385 /// # Panics
386 ///
387 /// If the contract has not yet been initialized.
388 fn decimals(env: Env) -> u32;
389
390 /// Returns the name for this token.
391 ///
392 /// # Panics
393 ///
394 /// If the contract has not yet been initialized.
395 fn name(env: Env) -> String;
396
397 /// Returns the symbol for this token.
398 ///
399 /// # Panics
400 ///
401 /// If the contract has not yet been initialized.
402 fn symbol(env: Env) -> String;
403
404 /// Sets the administrator to the specified address `new_admin`.
405 ///
406 /// # Arguments
407 ///
408 /// * `new_admin` - The address which will henceforth be the administrator
409 /// of this token contract.
410 ///
411 /// # Events
412 ///
413 /// Emits an event with topics `["set_admin", admin: Address], data =
414 /// [new_admin: Address]`
415 fn set_admin(env: Env, new_admin: Address);
416
417 /// Returns the admin of the contract.
418 ///
419 /// # Panics
420 ///
421 /// If the admin is not set.
422 fn admin(env: Env) -> Address;
423
424 /// Sets whether the account is authorized to use its balance. If
425 /// `authorized` is true, `id` should be able to use its balance.
426 ///
427 /// # Arguments
428 ///
429 /// * `id` - The address being (de-)authorized.
430 /// * `authorize` - Whether or not `id` can use its balance.
431 ///
432 /// # Events
433 ///
434 /// Emits an event with topics `["set_authorized", id: Address], data =
435 /// [authorize: bool]`
436 fn set_authorized(env: Env, id: Address, authorize: bool);
437
438 /// Returns true if `id` is authorized to use its balance.
439 ///
440 /// # Arguments
441 ///
442 /// * `id` - The address for which token authorization is being checked.
443 fn authorized(env: Env, id: Address) -> bool;
444
445 /// Mints `amount` to `to`.
446 ///
447 /// # Arguments
448 ///
449 /// * `to` - The address which will receive the minted tokens.
450 /// * `amount` - The amount of tokens to be minted.
451 ///
452 /// # Events
453 ///
454 /// Emits an event with topics `["mint", to: Address], data
455 /// = amount: i128`
456 fn mint(env: Env, to: Address, amount: i128);
457
458 /// Clawback `amount` from `from` account. `amount` is burned in the
459 /// clawback process.
460 ///
461 /// # Arguments
462 ///
463 /// * `from` - The address holding the balance from which the clawback will
464 /// take tokens.
465 /// * `amount` - The amount of tokens to be clawed back.
466 ///
467 /// # Events
468 ///
469 /// Emits an event with topics `["clawback", admin: Address, to: Address],
470 /// data = amount: i128`
471 fn clawback(env: Env, from: Address, amount: i128);
472}