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}