sep_41_token/lib.rs
1//! Interface for SEP-41 Token Standard
2//! https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0041.md
3
4#![no_std]
5
6#[cfg(any(test, feature = "testutils"))]
7pub mod testutils;
8
9use soroban_sdk::{contractclient, symbol_short, Address, Env, String};
10
11/// SEP-0041 Token Standard Trait
12#[contractclient(name = "TokenClient")]
13pub trait Token {
14 /// Returns the allowance for `spender` to transfer from `from`.
15 ///
16 /// # Arguments
17 ///
18 /// - `from` - The address holding the balance of tokens to be drawn from.
19 /// - `spender` - The address spending the tokens held by `from`.
20 fn allowance(env: Env, from: Address, spender: Address) -> i128;
21
22 /// Set the allowance by `amount` for `spender` to transfer/burn from
23 /// `from`. Overrides any existing allowance set between `spender` and `from`.
24 ///
25 /// # Arguments
26 ///
27 /// - `from` - The address holding the balance of tokens to be drawn from.
28 /// - `spender` - The address being authorized to spend the tokens held by
29 /// `from`.
30 /// - `amount` - The tokens to be made available to `spender`.
31 /// - `live_until_ledger` - The ledger number where this allowance expires.
32 /// Cannot be less than the current ledger number unless the amount is being
33 /// set to 0. An expired entry (where live_until_ledger < the current
34 /// ledger number) should be treated as a 0 amount allowance.
35 ///
36 /// # Events
37 ///
38 /// Emits an event with topics `["approve", from: Address,
39 /// spender: Address], data = [amount: i128, live_until_ledger: u32]`
40 ///
41 /// Emits an event with:
42 /// - topics - `["approve", from: Address, spender: Address]`
43 /// - data - `[amount: i128, live_until_ledger: u32]`
44 fn approve(env: Env, from: Address, spender: Address, amount: i128, live_until_ledger: u32);
45
46 /// Returns the balance of `id`.
47 ///
48 /// # Arguments
49 ///
50 /// - `id` - The address for which a balance is being queried. If the
51 /// address has no existing balance, returns 0.
52 fn balance(env: Env, id: Address) -> i128;
53
54 /// Transfer `amount` from `from` to `to`.
55 ///
56 /// # Arguments
57 ///
58 /// - `from` - The address holding the balance of tokens which will be
59 /// withdrawn from.
60 /// - `to` - The address which will receive the transferred tokens.
61 /// - `amount` - The amount of tokens to be transferred.
62 ///
63 /// # Events
64 ///
65 /// Emits an event with:
66 /// - topics - `["transfer", from: Address, to: Address]`
67 /// - data - `[amount: i128]`
68 fn transfer(env: Env, from: Address, to: Address, amount: i128);
69
70 /// Transfer `amount` from `from` to `to`, consuming the allowance of
71 /// `spender`. Authorized by spender (`spender.require_auth()`).
72 ///
73 /// # Arguments
74 ///
75 /// - `spender` - The address authorizing the transfer, and having its
76 /// allowance consumed during the transfer.
77 /// - `from` - The address holding the balance of tokens which will be
78 /// withdrawn from.
79 /// - `to` - The address which will receive the transferred tokens.
80 /// - `amount` - The amount of tokens to be transferred.
81 ///
82 /// # Events
83 ///
84 /// Emits an event with:
85 /// - topics - `["transfer", from: Address, to: Address]`
86 /// - data - `[amount: i128]`
87 fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);
88
89 /// Burn `amount` from `from`.
90 ///
91 /// # Arguments
92 ///
93 /// - `from` - The address holding the balance of tokens which will be
94 /// burned from.
95 /// - `amount` - The amount of tokens to be burned.
96 ///
97 /// # Events
98 ///
99 /// Emits an event with:
100 /// - topics - `["burn", from: Address]`
101 /// - data - `[amount: i128]`
102 fn burn(env: Env, from: Address, amount: i128);
103
104 /// Burn `amount` from `from`, consuming the allowance of `spender`.
105 ///
106 /// # Arguments
107 ///
108 /// - `spender` - The address authorizing the burn, and having its allowance
109 /// consumed during the burn.
110 /// - `from` - The address holding the balance of tokens which will be
111 /// burned from.
112 /// - `amount` - The amount of tokens to be burned.
113 ///
114 /// # Events
115 ///
116 /// Emits an event with:
117 /// - topics - `["burn", from: Address]`
118 /// - data - `[amount: i128]`
119 fn burn_from(env: Env, spender: Address, from: Address, amount: i128);
120
121 /// Returns the number of decimals used to represent amounts of this token.
122 fn decimals(env: Env) -> u32;
123
124 /// Returns the name for this token.
125 fn name(env: Env) -> String;
126
127 /// Returns the symbol for this token.
128 fn symbol(env: Env) -> String;
129}
130
131/// Extension for functions implemented by the SEP-0041 compliant native Stellar Asset
132/// Contract: https://github.com/stellar/rs-soroban-env/blob/main/soroban-env-host/src/native_contract/token/contract.rs
133#[contractclient(name = "StellarAssetClient")]
134pub trait StellarAssetExtension {
135 /// Create `amount` of tokens and assigns them to `to`.
136 ///
137 /// Requires authorization by the admin.
138 ///
139 /// # Arguments
140 ///
141 /// - `to` - The address which will receive the created tokens.
142 /// - `amount` - The amount of tokens to be created.
143 fn mint(env: Env, to: Address, amount: i128);
144
145 /// Set the authorization status of an address to `authorize`.
146 ///
147 /// Requires authorization by the admin.
148 ///
149 /// # Arguments
150 ///
151 /// - `addr` - The address which will have their authorization modified.
152 /// - `authorize` - The authorization status to be set.
153 fn set_authorized(env: Env, addr: Address, authorize: bool);
154
155 /// Get the authorization status of an address.
156 ///
157 /// # Arguments
158 ///
159 /// - `addr` - The address which will have their authorization status queried.
160 fn authorized(env: Env, addr: Address) -> bool;
161
162 /// Clawback `amount` of tokens from `from`.
163 ///
164 /// Requires authorization by the admin.
165 ///
166 /// # Arguments
167 ///
168 /// - `from` - The address which will have their tokens clawed back.
169 /// - `amount` - The amount of tokens to be clawed back.
170 fn clawback(env: Env, from: Address, amount: i128);
171
172 /// Set the admin address to `new_admin`.
173 ///
174 /// Requires authorization by the admin.
175 ///
176 /// # Arguments
177 ///
178 /// - `new_admin` - The address which will be set as the new admin.
179 fn set_admin(env: Env, new_admin: Address);
180
181 /// Get the admin address.
182 fn admin(env: Env);
183}
184
185pub struct TokenEvents {}
186
187impl TokenEvents {
188 /// Emitted when an allowance is set
189 ///
190 /// - topics - `["approve", from: Address, spender: Address]`
191 /// - data - `[amount: i128, live_until_ledger: u32]`
192 pub fn approve(
193 env: &Env,
194 from: Address,
195 spender: Address,
196 amount: i128,
197 live_until_ledger: u32,
198 ) {
199 let topics = (symbol_short!("approve"), from, spender);
200 env.events().publish(topics, (amount, live_until_ledger));
201 }
202
203 /// Emitted when an amount is transferred from one address to another
204 ///
205 /// - topics - `["transfer", from: Address, to: Address]`
206 /// - data - `[amount: i128]`
207 pub fn transfer(env: &Env, from: Address, to: Address, amount: i128) {
208 let topics = (symbol_short!("transfer"), from, to);
209 env.events().publish(topics, amount);
210 }
211
212 /// Emitted when an amount of tokens is burnt from one address
213 ///
214 /// - topics - `["burn", from: Address]`
215 /// - data - `[amount: i128]`
216 pub fn burn(env: &Env, from: Address, amount: i128) {
217 let topics = (symbol_short!("burn"), from);
218 env.events().publish(topics, amount);
219 }
220
221 /// Emitted when an amount of tokens is created and assigned to an address
222 ///
223 /// - topics - `["mint", admin: Address, to: Address]`
224 /// - data - `[amount: i128]`
225 pub fn mint(env: &Env, admin: Address, to: Address, amount: i128) {
226 let topics = (symbol_short!("mint"), admin, to);
227 env.events().publish(topics, amount);
228 }
229}