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;