Skip to main content

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    /// * `live_until_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 live_until_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, live_until_ledger: u32]`
126    fn approve(env: Env, from: Address, spender: Address, amount: i128, live_until_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 `{ amount: i128, to_muxed_id: Option<u64> }: 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    /// * `live_until_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 live_until_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, sep0011_asset: String], data = [amount: i128,
288    /// live_until_ledger: u32]`
289    fn approve(env: Env, from: Address, spender: Address, amount: i128, live_until_ledger: u32);
290
291    /// Returns the balance of `id`.
292    ///
293    /// # Arguments
294    ///
295    /// * `id` - The address for which a balance is being queried. If the
296    ///   address has no existing balance, returns 0.
297    fn balance(env: Env, id: Address) -> i128;
298
299    /// Transfer `amount` from `from` to `to`.
300    ///
301    /// # Arguments
302    ///
303    /// * `from` - The address holding the balance of tokens which will be
304    ///   withdrawn from.
305    /// * `to` - The address which will receive the transferred tokens.
306    /// * `amount` - The amount of tokens to be transferred.
307    ///
308    /// # Events
309    ///
310    /// When `to` is a muxed address, emits an event with:
311    /// * topics `["transfer", from: Address, to: Address, sep0011_asset: String]`
312    /// * data `{ amount: i128, to_muxed_id: Option<u64> }: Map`
313    ///
314    /// Otherwise, emits an event with:
315    /// * topics `["transfer", from: Address, to: Address, sep0011_asset: String]`
316    /// * data `amount: i128`
317    ///
318    /// When `from != to` and `from` is the asset issuer, a `mint` event is emitted instead.
319    /// When `from != to` and `to` is the asset issuer, a `burn` event is emitted instead.
320    fn transfer(env: Env, from: Address, to: MuxedAddress, amount: i128);
321
322    /// Transfer `amount` from `from` to `to`, consuming the allowance that
323    /// `spender` has on `from`'s balance. Authorized by spender
324    /// (`spender.require_auth()`).
325    ///
326    /// The spender will be allowed to transfer the amount from from's balance
327    /// if the amount is less than or equal to the allowance that the spender
328    /// has on the from's balance. The spender's allowance on from's balance
329    /// will be reduced by the amount.
330    ///
331    /// # Arguments
332    ///
333    /// * `spender` - The address authorizing the transfer, and having its
334    ///   allowance consumed during the transfer.
335    /// * `from` - The address holding the balance of tokens which will be
336    ///   withdrawn from.
337    /// * `to` - The address which will receive the transferred tokens.
338    /// * `amount` - The amount of tokens to be transferred.
339    ///
340    /// # Events
341    ///
342    /// Emits an event with topics `["transfer", from: Address, to: Address,
343    /// sep0011_asset: String], data = amount: i128`
344    fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);
345
346    /// Burn `amount` from `from`.
347    ///
348    /// Reduces from's balance by the amount, without transferring the balance
349    /// to another holder's balance.
350    ///
351    /// # Arguments
352    ///
353    /// * `from` - The address holding the balance of tokens which will be
354    ///   burned from.
355    /// * `amount` - The amount of tokens to be burned.
356    ///
357    /// # Events
358    ///
359    /// Emits an event with topics `["burn", from: Address,
360    /// sep0011_asset: String], data = amount: i128`
361    fn burn(env: Env, from: Address, amount: i128);
362
363    /// Burn `amount` from `from`, consuming the allowance of `spender`.
364    ///
365    /// Reduces from's balance by the amount, without transferring the balance
366    /// to another holder's balance.
367    ///
368    /// The spender will be allowed to burn the amount from from's balance, if
369    /// the amount is less than or equal to the allowance that the spender has
370    /// on the from's balance. The spender's allowance on from's balance will be
371    /// reduced by the amount.
372    ///
373    /// # Arguments
374    ///
375    /// * `spender` - The address authorizing the burn, and having its allowance
376    ///   consumed during the burn.
377    /// * `from` - The address holding the balance of tokens which will be
378    ///   burned from.
379    /// * `amount` - The amount of tokens to be burned.
380    ///
381    /// # Events
382    ///
383    /// Emits an event with topics `["burn", from: Address,
384    /// sep0011_asset: String], data = amount: i128`
385    fn burn_from(env: Env, spender: Address, from: Address, amount: i128);
386
387    /// Returns the number of decimals used to represent amounts of this token.
388    ///
389    /// # Panics
390    ///
391    /// If the contract has not yet been initialized.
392    fn decimals(env: Env) -> u32;
393
394    /// Returns the name for this token.
395    ///
396    /// # Panics
397    ///
398    /// If the contract has not yet been initialized.
399    fn name(env: Env) -> String;
400
401    /// Returns the symbol for this token.
402    ///
403    /// # Panics
404    ///
405    /// If the contract has not yet been initialized.
406    fn symbol(env: Env) -> String;
407
408    /// Sets the administrator to the specified address `new_admin`.
409    ///
410    /// # Arguments
411    ///
412    /// * `new_admin` - The address which will henceforth be the administrator
413    ///   of this token contract.
414    ///
415    /// # Events
416    ///
417    /// Emits an event with topics `["set_admin", admin: Address,
418    /// sep0011_asset: String], data = new_admin: Address`
419    fn set_admin(env: Env, new_admin: Address);
420
421    /// Returns the admin of the contract.
422    ///
423    /// # Panics
424    ///
425    /// If the admin is not set.
426    fn admin(env: Env) -> Address;
427
428    /// Sets whether the account is authorized to use its balance. If
429    /// `authorized` is true, `id` should be able to use its balance.
430    ///
431    /// # Arguments
432    ///
433    /// * `id` - The address being (de-)authorized.
434    /// * `authorize` - Whether or not `id` can use its balance.
435    ///
436    /// # Events
437    ///
438    /// Emits an event with topics `["set_authorized", id: Address,
439    /// sep0011_asset: String], data = authorize: bool`
440    fn set_authorized(env: Env, id: Address, authorize: bool);
441
442    /// Returns true if `id` is authorized to use its balance.
443    ///
444    /// # Arguments
445    ///
446    /// * `id` - The address for which token authorization is being checked.
447    fn authorized(env: Env, id: Address) -> bool;
448
449    /// Mints `amount` to `to`.
450    ///
451    /// # Arguments
452    ///
453    /// * `to` - The address which will receive the minted tokens.
454    /// * `amount` - The amount of tokens to be minted.
455    ///
456    /// # Events
457    ///
458    /// Emits an event with topics `["mint", to: Address,
459    /// sep0011_asset: String], data = amount: i128`
460    fn mint(env: Env, to: Address, amount: i128);
461
462    /// Clawback `amount` from `from` account. `amount` is burned in the
463    /// clawback process.
464    ///
465    /// # Arguments
466    ///
467    /// * `from` - The address holding the balance from which the clawback will
468    ///   take tokens.
469    /// * `amount` - The amount of tokens to be clawed back.
470    ///
471    /// # Events
472    ///
473    /// Emits an event with topics `["clawback", from: Address,
474    /// sep0011_asset: String], data = amount: i128`
475    fn clawback(env: Env, from: Address, amount: i128);
476
477    /// Creates this contract asset's unlimited trustline for the provided
478    /// address.
479    ///
480    /// This is a no-op if the input address is a C-address, or if the
481    /// provided G-address already has the respective trustline.
482    ///
483    /// If the trustline is actually created, this will require authorization
484    /// from `addr` (i.e. `addr.require_auth` will be called).
485    ///
486    /// # Arguments
487    ///
488    /// * `addr` - The address for which a trustline will be created.
489    ///
490    /// # Panics
491    ///
492    /// Panics during trustline creation if the asset issuer does not exist,
493    /// or when a new trustline cannot be created.
494    fn trust(env: Env, addr: Address);
495}