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::{contractclient, contractspecfn, 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#[contractspecfn(name = "TokenFnSpec", export = false)]
84#[contractclient(crate_path = "crate", name = "TokenClient")]
85pub trait TokenInterface {
86    /// Returns the allowance for `spender` to transfer from `from`.
87    ///
88    /// The amount returned is the amount that spender is allowed to transfer
89    /// out of from's balance. When the spender transfers amounts, the allowance
90    /// will be reduced by the amount transferred.
91    ///
92    /// # Arguments
93    ///
94    /// * `from` - The address holding the balance of tokens to be drawn from.
95    /// * `spender` - The address spending the tokens held by `from`.
96    fn allowance(env: Env, from: Address, spender: Address) -> i128;
97
98    /// Set the allowance by `amount` for `spender` to transfer/burn from
99    /// `from`.
100    ///
101    /// The amount set is the amount that spender is approved to transfer out of
102    /// from's balance. The spender will be allowed to transfer amounts, and
103    /// when an amount is transferred the allowance will be reduced by the
104    /// amount transferred.
105    ///
106    /// # Arguments
107    ///
108    /// * `from` - The address holding the balance of tokens to be drawn from.
109    /// * `spender` - The address being authorized to spend the tokens held by
110    ///   `from`.
111    /// * `amount` - The tokens to be made available to `spender`.
112    /// * `expiration_ledger` - The ledger number where this allowance expires. Cannot
113    ///    be less than the current ledger number unless the amount is being set to 0.
114    ///    An expired entry (where expiration_ledger < the current ledger number)
115    ///    should be treated as a 0 amount allowance.
116    ///
117    /// # Events
118    ///
119    /// Emits an event with topics `["approve", from: Address,
120    /// spender: Address], data = [amount: i128, expiration_ledger: u32]`
121    fn approve(env: Env, from: Address, spender: Address, amount: i128, expiration_ledger: u32);
122
123    /// Returns the balance of `id`.
124    ///
125    /// # Arguments
126    ///
127    /// * `id` - The address for which a balance is being queried. If the
128    ///   address has no existing balance, returns 0.
129    fn balance(env: Env, id: Address) -> i128;
130
131    /// Transfer `amount` from `from` to `to`.
132    ///
133    /// # Arguments
134    ///
135    /// * `from` - The address holding the balance of tokens which will be
136    ///   withdrawn from.
137    /// * `to` - The address which will receive the transferred tokens.
138    /// * `amount` - The amount of tokens to be transferred.
139    ///
140    /// # Events
141    ///
142    /// Emits an event with:
143    /// * topics `["transfer", from: Address, to: Address]`
144    /// * data `{ to_muxed_id: Option<u64>, amount: i128 }: Map`
145    ///
146    /// Legacy implementations may emit an event with:
147    /// * topics `["transfer", from: Address, to: Address]`
148    /// * data `amount: i128`
149    fn transfer(env: Env, from: Address, to: MuxedAddress, amount: i128);
150
151    /// Transfer `amount` from `from` to `to`, consuming the allowance that
152    /// `spender` has on `from`'s balance. Authorized by spender
153    /// (`spender.require_auth()`).
154    ///
155    /// The spender will be allowed to transfer the amount from from's balance
156    /// if the amount is less than or equal to the allowance that the spender
157    /// has on the from's balance. The spender's allowance on from's balance
158    /// will be reduced by the amount.
159    ///
160    /// # Arguments
161    ///
162    /// * `spender` - The address authorizing the transfer, and having its
163    ///   allowance consumed during the transfer.
164    /// * `from` - The address holding the balance of tokens which will be
165    ///   withdrawn from.
166    /// * `to` - The address which will receive the transferred tokens.
167    /// * `amount` - The amount of tokens to be transferred.
168    ///
169    /// # Events
170    ///
171    /// Emits an event with topics `["transfer", from: Address, to: Address],
172    /// data = amount: i128`
173    fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);
174
175    /// Burn `amount` from `from`.
176    ///
177    /// Reduces from's balance by the amount, without transferring the balance
178    /// to another holder's balance.
179    ///
180    /// # Arguments
181    ///
182    /// * `from` - The address holding the balance of tokens which will be
183    ///   burned from.
184    /// * `amount` - The amount of tokens to be burned.
185    ///
186    /// # Events
187    ///
188    /// Emits an event with topics `["burn", from: Address], data = amount:
189    /// i128`
190    fn burn(env: Env, from: Address, amount: i128);
191
192    /// Burn `amount` from `from`, consuming the allowance of `spender`.
193    ///
194    /// Reduces from's balance by the amount, without transferring the balance
195    /// to another holder's balance.
196    ///
197    /// The spender will be allowed to burn the amount from from's balance, if
198    /// the amount is less than or equal to the allowance that the spender has
199    /// on the from's balance. The spender's allowance on from's balance will be
200    /// reduced by the amount.
201    ///
202    /// # Arguments
203    ///
204    /// * `spender` - The address authorizing the burn, and having its allowance
205    ///   consumed during the burn.
206    /// * `from` - The address holding the balance of tokens which will be
207    ///   burned from.
208    /// * `amount` - The amount of tokens to be burned.
209    ///
210    /// # Events
211    ///
212    /// Emits an event with topics `["burn", from: Address], data = amount:
213    /// i128`
214    fn burn_from(env: Env, spender: Address, from: Address, amount: i128);
215
216    /// Returns the number of decimals used to represent amounts of this token.
217    ///
218    /// # Panics
219    ///
220    /// If the contract has not yet been initialized.
221    fn decimals(env: Env) -> u32;
222
223    /// Returns the name for this token.
224    ///
225    /// # Panics
226    ///
227    /// If the contract has not yet been initialized.
228    fn name(env: Env) -> String;
229
230    /// Returns the symbol for this token.
231    ///
232    /// # Panics
233    ///
234    /// If the contract has not yet been initialized.
235    fn symbol(env: Env) -> String;
236}
237
238/// Spec contains the contract spec of functions of the Token contracts.
239#[doc(hidden)]
240pub struct TokenFnSpec;
241
242/// Interface for admin capabilities for Token contracts, such as the Stellar
243/// Asset Contract.
244#[contractspecfn(name = "StellarAssetFnSpec", export = false)]
245#[contractclient(crate_path = "crate", name = "StellarAssetClient")]
246pub trait StellarAssetInterface {
247    /// Returns the allowance for `spender` to transfer from `from`.
248    ///
249    /// The amount returned is the amount that spender is allowed to transfer
250    /// out of from's balance. When the spender transfers amounts, the allowance
251    /// will be reduced by the amount transferred.
252    ///
253    /// # Arguments
254    ///
255    /// * `from` - The address holding the balance of tokens to be drawn from.
256    /// * `spender` - The address spending the tokens held by `from`.
257    fn allowance(env: Env, from: Address, spender: Address) -> i128;
258
259    /// Set the allowance by `amount` for `spender` to transfer/burn from
260    /// `from`.
261    ///
262    /// The amount set is the amount that spender is approved to transfer out of
263    /// from's balance. The spender will be allowed to transfer amounts, and
264    /// when an amount is transferred the allowance will be reduced by the
265    /// amount transferred.
266    ///
267    /// # Arguments
268    ///
269    /// * `from` - The address holding the balance of tokens to be drawn from.
270    /// * `spender` - The address being authorized to spend the tokens held by
271    ///   `from`.
272    /// * `amount` - The tokens to be made available to `spender`.
273    /// * `expiration_ledger` - The ledger number where this allowance expires. Cannot
274    ///    be less than the current ledger number unless the amount is being set to 0.
275    ///    An expired entry (where expiration_ledger < the current ledger number)
276    ///    should be treated as a 0 amount allowance.
277    ///
278    /// # Events
279    ///
280    /// Emits an event with topics `["approve", from: Address,
281    /// spender: Address], data = [amount: i128, expiration_ledger: u32]`
282    fn approve(env: Env, from: Address, spender: Address, amount: i128, expiration_ledger: u32);
283
284    /// Returns the balance of `id`.
285    ///
286    /// # Arguments
287    ///
288    /// * `id` - The address for which a balance is being queried. If the
289    ///   address has no existing balance, returns 0.
290    fn balance(env: Env, id: Address) -> i128;
291
292    /// Transfer `amount` from `from` to `to`.
293    ///
294    /// # Arguments
295    ///
296    /// * `from` - The address holding the balance of tokens which will be
297    ///   withdrawn from.
298    /// * `to` - The address which will receive the transferred tokens.
299    /// * `amount` - The amount of tokens to be transferred.
300    ///
301    /// # Events
302    ///
303    /// Emits an event with:
304    /// * topics `["transfer", from: Address, to: Address]`
305    /// * data `{ to_muxed_id: Option<u64>, amount: i128 }: Map`
306    ///
307    /// Legacy implementations may emit an event with:
308    /// * topics `["transfer", from: Address, to: Address]`
309    /// * data `amount: i128`
310    fn transfer(env: Env, from: Address, to: MuxedAddress, amount: i128);
311
312    /// Transfer `amount` from `from` to `to`, consuming the allowance that
313    /// `spender` has on `from`'s balance. Authorized by spender
314    /// (`spender.require_auth()`).
315    ///
316    /// The spender will be allowed to transfer the amount from from's balance
317    /// if the amount is less than or equal to the allowance that the spender
318    /// has on the from's balance. The spender's allowance on from's balance
319    /// will be reduced by the amount.
320    ///
321    /// # Arguments
322    ///
323    /// * `spender` - The address authorizing the transfer, and having its
324    ///   allowance consumed during the transfer.
325    /// * `from` - The address holding the balance of tokens which will be
326    ///   withdrawn from.
327    /// * `to` - The address which will receive the transferred tokens.
328    /// * `amount` - The amount of tokens to be transferred.
329    ///
330    /// # Events
331    ///
332    /// Emits an event with topics `["transfer", from: Address, to: Address],
333    /// data = amount: i128`
334    fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);
335
336    /// Burn `amount` from `from`.
337    ///
338    /// Reduces from's balance by the amount, without transferring the balance
339    /// to another holder's balance.
340    ///
341    /// # Arguments
342    ///
343    /// * `from` - The address holding the balance of tokens which will be
344    ///   burned from.
345    /// * `amount` - The amount of tokens to be burned.
346    ///
347    /// # Events
348    ///
349    /// Emits an event with topics `["burn", from: Address], data = amount:
350    /// i128`
351    fn burn(env: Env, from: Address, amount: i128);
352
353    /// Burn `amount` from `from`, consuming the allowance of `spender`.
354    ///
355    /// Reduces from's balance by the amount, without transferring the balance
356    /// to another holder's balance.
357    ///
358    /// The spender will be allowed to burn the amount from from's balance, if
359    /// the amount is less than or equal to the allowance that the spender has
360    /// on the from's balance. The spender's allowance on from's balance will be
361    /// reduced by the amount.
362    ///
363    /// # Arguments
364    ///
365    /// * `spender` - The address authorizing the burn, and having its allowance
366    ///   consumed during the burn.
367    /// * `from` - The address holding the balance of tokens which will be
368    ///   burned from.
369    /// * `amount` - The amount of tokens to be burned.
370    ///
371    /// # Events
372    ///
373    /// Emits an event with topics `["burn", from: Address], data = amount:
374    /// i128`
375    fn burn_from(env: Env, spender: Address, from: Address, amount: i128);
376
377    /// Returns the number of decimals used to represent amounts of this token.
378    ///
379    /// # Panics
380    ///
381    /// If the contract has not yet been initialized.
382    fn decimals(env: Env) -> u32;
383
384    /// Returns the name for this token.
385    ///
386    /// # Panics
387    ///
388    /// If the contract has not yet been initialized.
389    fn name(env: Env) -> String;
390
391    /// Returns the symbol for this token.
392    ///
393    /// # Panics
394    ///
395    /// If the contract has not yet been initialized.
396    fn symbol(env: Env) -> String;
397
398    /// Sets the administrator to the specified address `new_admin`.
399    ///
400    /// # Arguments
401    ///
402    /// * `new_admin` - The address which will henceforth be the administrator
403    ///   of this token contract.
404    ///
405    /// # Events
406    ///
407    /// Emits an event with topics `["set_admin", admin: Address], data =
408    /// [new_admin: Address]`
409    fn set_admin(env: Env, new_admin: Address);
410
411    /// Returns the admin of the contract.
412    ///
413    /// # Panics
414    ///
415    /// If the admin is not set.
416    fn admin(env: Env) -> Address;
417
418    /// Sets whether the account is authorized to use its balance. If
419    /// `authorized` is true, `id` should be able to use its balance.
420    ///
421    /// # Arguments
422    ///
423    /// * `id` - The address being (de-)authorized.
424    /// * `authorize` - Whether or not `id` can use its balance.
425    ///
426    /// # Events
427    ///
428    /// Emits an event with topics `["set_authorized", id: Address], data =
429    /// [authorize: bool]`
430    fn set_authorized(env: Env, id: Address, authorize: bool);
431
432    /// Returns true if `id` is authorized to use its balance.
433    ///
434    /// # Arguments
435    ///
436    /// * `id` - The address for which token authorization is being checked.
437    fn authorized(env: Env, id: Address) -> bool;
438
439    /// Mints `amount` to `to`.
440    ///
441    /// # Arguments
442    ///
443    /// * `to` - The address which will receive the minted tokens.
444    /// * `amount` - The amount of tokens to be minted.
445    ///
446    /// # Events
447    ///
448    /// Emits an event with topics `["mint", to: Address], data
449    /// = amount: i128`
450    fn mint(env: Env, to: Address, amount: i128);
451
452    /// Clawback `amount` from `from` account. `amount` is burned in the
453    /// clawback process.
454    ///
455    /// # Arguments
456    ///
457    /// * `from` - The address holding the balance from which the clawback will
458    ///   take tokens.
459    /// * `amount` - The amount of tokens to be clawed back.
460    ///
461    /// # Events
462    ///
463    /// Emits an event with topics `["clawback", admin: Address, to: Address],
464    /// data = amount: i128`
465    fn clawback(env: Env, from: Address, amount: i128);
466}
467
468/// Contains the contract spec of the functions of the Stellar Asset Contract.
469///
470/// The Stellar Asset Contract is a superset of the Token Contract.
471#[doc(hidden)]
472pub struct StellarAssetFnSpec;