@@ -52,6 +52,12 @@ pub struct Transfer<'info> {
52
52
#[ account( mut ) ]
53
53
pub outbox_rate_limit : Account < ' info , OutboxRateLimit > ,
54
54
55
+ #[ account(
56
+ mut ,
57
+ address = config. custody
58
+ ) ]
59
+ pub custody : InterfaceAccount < ' info , token_interface:: TokenAccount > ,
60
+
55
61
pub system_program : Program < ' info , System > ,
56
62
}
57
63
@@ -85,6 +91,9 @@ impl TransferArgs {
85
91
#[ derive( Accounts ) ]
86
92
#[ instruction( args: TransferArgs ) ]
87
93
pub struct TransferBurn < ' info > {
94
+ #[ account(
95
+ constraint = common. config. mode == Mode :: Burning @ NTTError :: InvalidMode ,
96
+ ) ]
88
97
pub common : Transfer < ' info > ,
89
98
90
99
#[ account(
@@ -111,15 +120,18 @@ pub struct TransferBurn<'info> {
111
120
bump,
112
121
) ]
113
122
pub session_authority : AccountInfo < ' info > ,
114
- }
115
123
116
- pub fn transfer_burn ( ctx : Context < TransferBurn > , args : TransferArgs ) -> Result < ( ) > {
117
- require_eq ! (
118
- ctx . accounts . common . config . mode ,
119
- Mode :: Burning ,
120
- NTTError :: InvalidMode
121
- ) ;
124
+ # [ account (
125
+ seeds = [ crate :: TOKEN_AUTHORITY_SEED ] ,
126
+ bump ,
127
+ ) ]
128
+ pub token_authority : AccountInfo < ' info > ,
129
+ }
122
130
131
+ pub fn transfer_burn < ' info > (
132
+ ctx : Context < ' _ , ' _ , ' _ , ' info , TransferBurn < ' info > > ,
133
+ args : TransferArgs ,
134
+ ) -> Result < ( ) > {
123
135
let accs = ctx. accounts ;
124
136
let TransferArgs {
125
137
mut amount,
@@ -136,30 +148,50 @@ pub fn transfer_burn(ctx: Context<TransferBurn>, args: TransferArgs) -> Result<(
136
148
)
137
149
. map_err ( NTTError :: from) ?;
138
150
139
- let before = accs. common . from . amount ;
151
+ let before = accs. common . custody . amount ;
152
+
153
+ onchain:: invoke_transfer_checked (
154
+ & accs. common . token_program . key ( ) ,
155
+ accs. common . from . to_account_info ( ) ,
156
+ accs. common . mint . to_account_info ( ) ,
157
+ accs. common . custody . to_account_info ( ) ,
158
+ accs. session_authority . to_account_info ( ) ,
159
+ ctx. remaining_accounts ,
160
+ amount,
161
+ accs. common . mint . decimals ,
162
+ & [ & [
163
+ crate :: SESSION_AUTHORITY_SEED ,
164
+ accs. common . from . owner . as_ref ( ) ,
165
+ args. keccak256 ( ) . as_ref ( ) ,
166
+ & [ ctx. bumps . session_authority ] ,
167
+ ] ] ,
168
+ ) ?;
140
169
141
170
token_interface:: burn (
142
171
CpiContext :: new_with_signer (
143
172
accs. common . token_program . to_account_info ( ) ,
144
173
token_interface:: Burn {
145
174
mint : accs. common . mint . to_account_info ( ) ,
146
- from : accs. common . from . to_account_info ( ) ,
147
- authority : accs. session_authority . to_account_info ( ) ,
175
+ from : accs. common . custody . to_account_info ( ) ,
176
+ authority : accs. token_authority . to_account_info ( ) ,
148
177
} ,
149
- & [ & [
150
- crate :: SESSION_AUTHORITY_SEED ,
151
- accs. common . from . owner . as_ref ( ) ,
152
- args. keccak256 ( ) . as_ref ( ) ,
153
- & [ ctx. bumps . session_authority ] ,
154
- ] ] ,
178
+ & [ & [ crate :: TOKEN_AUTHORITY_SEED , & [ ctx. bumps . token_authority ] ] ] ,
155
179
) ,
156
180
amount,
157
181
) ?;
158
182
159
- accs. common . from . reload ( ) ?;
160
- let after = accs. common . from . amount ;
183
+ accs. common . custody . reload ( ) ?;
184
+ let after = accs. common . custody . amount ;
161
185
162
- if after != before - amount {
186
+ // NOTE: we currently do not support tokens with fees. Support could be
187
+ // added, but it would require the client to calculate the amount _before_
188
+ // paying fees that results in an amount that can safely be trimmed.
189
+ // Otherwise, if the amount after paying fees has dust, then that amount
190
+ // would be lost.
191
+ // To support fee tokens, we would first transfer the amount, _then_ assert
192
+ // that the resulting amount has no dust (instead of removing dust before
193
+ // the transfer like we do now).
194
+ if after != before {
163
195
return Err ( NTTError :: BadAmountAfterBurn . into ( ) ) ;
164
196
}
165
197
@@ -174,14 +206,19 @@ pub fn transfer_burn(ctx: Context<TransferBurn>, args: TransferArgs) -> Result<(
174
206
recipient_ntt_manager,
175
207
recipient_address,
176
208
should_queue,
177
- )
209
+ ) ?;
210
+
211
+ Ok ( ( ) )
178
212
}
179
213
180
214
// Lock/unlock
181
215
182
216
#[ derive( Accounts ) ]
183
217
#[ instruction( args: TransferArgs ) ]
184
218
pub struct TransferLock < ' info > {
219
+ #[ account(
220
+ constraint = common. config. mode == Mode :: Locking @ NTTError :: InvalidMode ,
221
+ ) ]
185
222
pub common : Transfer < ' info > ,
186
223
187
224
#[ account(
@@ -208,24 +245,12 @@ pub struct TransferLock<'info> {
208
245
bump,
209
246
) ]
210
247
pub session_authority : AccountInfo < ' info > ,
211
-
212
- #[ account(
213
- mut ,
214
- address = common. config. custody
215
- ) ]
216
- pub custody : InterfaceAccount < ' info , token_interface:: TokenAccount > ,
217
248
}
218
249
219
250
pub fn transfer_lock < ' info > (
220
251
ctx : Context < ' _ , ' _ , ' _ , ' info , TransferLock < ' info > > ,
221
252
args : TransferArgs ,
222
253
) -> Result < ( ) > {
223
- require_eq ! (
224
- ctx. accounts. common. config. mode,
225
- Mode :: Locking ,
226
- NTTError :: InvalidMode
227
- ) ;
228
-
229
254
let accs = ctx. accounts ;
230
255
let TransferArgs {
231
256
mut amount,
@@ -242,13 +267,13 @@ pub fn transfer_lock<'info>(
242
267
)
243
268
. map_err ( NTTError :: from) ?;
244
269
245
- let before = accs. custody . amount ;
270
+ let before = accs. common . custody . amount ;
246
271
247
272
onchain:: invoke_transfer_checked (
248
273
& accs. common . token_program . key ( ) ,
249
274
accs. common . from . to_account_info ( ) ,
250
275
accs. common . mint . to_account_info ( ) ,
251
- accs. custody . to_account_info ( ) ,
276
+ accs. common . custody . to_account_info ( ) ,
252
277
accs. session_authority . to_account_info ( ) ,
253
278
ctx. remaining_accounts ,
254
279
amount,
@@ -261,8 +286,8 @@ pub fn transfer_lock<'info>(
261
286
] ] ,
262
287
) ?;
263
288
264
- accs. custody . reload ( ) ?;
265
- let after = accs. custody . amount ;
289
+ accs. common . custody . reload ( ) ?;
290
+ let after = accs. common . custody . amount ;
266
291
267
292
// NOTE: we currently do not support tokens with fees. Support could be
268
293
// added, but it would require the client to calculate the amount _before_
0 commit comments