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}