@@ -18,7 +18,10 @@ pub struct PrepareMarketOrder<'info> {
18
18
custodian : CheckedCustodian < ' info > ,
19
19
20
20
/// The auction participant needs to set approval to this PDA if the sender (signer) is not
21
- /// provided.
21
+ /// provided. The delegated amount must equal the amount in or this instruction will revert.
22
+ ///
23
+ /// NOTE: If this account is provided, the sender token's owner will be encoded as the order
24
+ /// sender.
22
25
///
23
26
/// CHECK: Seeds must be \["transfer-authority", prepared_order.key(), args.hash()\].
24
27
#[ account(
@@ -28,11 +31,22 @@ pub struct PrepareMarketOrder<'info> {
28
31
& args. hash( ) . 0 ,
29
32
] ,
30
33
bump,
34
+ constraint = {
35
+ require_eq!(
36
+ sender_token. delegated_amount,
37
+ args. amount_in,
38
+ TokenRouterError :: DelegatedAmountMismatch ,
39
+ ) ;
40
+
41
+ true
42
+ }
31
43
) ]
32
44
program_transfer_authority : Option < UncheckedAccount < ' info > > ,
33
45
34
46
/// Sender, who has the authority to transfer assets from the sender token account. If this
35
47
/// account is not provided, the program transfer authority account must be some account.
48
+ ///
49
+ /// NOTE: If this account is provided, this pubkey will be encoded as the order sender.
36
50
sender : Option < Signer < ' info > > ,
37
51
38
52
#[ account(
@@ -161,10 +175,57 @@ pub fn prepare_market_order(
161
175
redeemer_message,
162
176
} = args;
163
177
178
+ // Finally transfer amount to custody token account. We perform exclusive or because we do not
179
+ // want to allow specifying more than one authority.
180
+ let order_sender = match (
181
+ ctx. accounts . sender . as_ref ( ) ,
182
+ ctx. accounts . program_transfer_authority . as_ref ( ) ,
183
+ ) {
184
+ ( Some ( sender) , None ) => {
185
+ token:: transfer (
186
+ CpiContext :: new (
187
+ ctx. accounts . token_program . to_account_info ( ) ,
188
+ token:: Transfer {
189
+ from : ctx. accounts . sender_token . to_account_info ( ) ,
190
+ to : ctx. accounts . prepared_custody_token . to_account_info ( ) ,
191
+ authority : sender. to_account_info ( ) ,
192
+ } ,
193
+ ) ,
194
+ amount_in,
195
+ ) ?;
196
+
197
+ sender. key ( )
198
+ }
199
+ ( None , Some ( program_transfer_authority) ) => {
200
+ let sender_token = & ctx. accounts . sender_token ;
201
+
202
+ token:: transfer (
203
+ CpiContext :: new_with_signer (
204
+ ctx. accounts . token_program . to_account_info ( ) ,
205
+ token:: Transfer {
206
+ from : sender_token. to_account_info ( ) ,
207
+ to : ctx. accounts . prepared_custody_token . to_account_info ( ) ,
208
+ authority : program_transfer_authority. to_account_info ( ) ,
209
+ } ,
210
+ & [ & [
211
+ TRANSFER_AUTHORITY_SEED_PREFIX ,
212
+ ctx. accounts . prepared_order . key ( ) . as_ref ( ) ,
213
+ & hashed_args. 0 ,
214
+ & [ ctx. bumps . program_transfer_authority . unwrap ( ) ] ,
215
+ ] ] ,
216
+ ) ,
217
+ amount_in,
218
+ ) ?;
219
+
220
+ sender_token. owner
221
+ }
222
+ _ => return err ! ( TokenRouterError :: EitherSenderOrProgramTransferAuthority ) ,
223
+ } ;
224
+
164
225
// Set the values in prepared order account.
165
226
ctx. accounts . prepared_order . set_inner ( PreparedOrder {
166
227
info : PreparedOrderInfo {
167
- order_sender : ctx . accounts . sender_token . owner ,
228
+ order_sender,
168
229
prepared_by : ctx. accounts . payer . key ( ) ,
169
230
order_type : OrderType :: Market { min_amount_out } ,
170
231
src_token : ctx. accounts . sender_token . key ( ) ,
@@ -176,41 +237,6 @@ pub fn prepare_market_order(
176
237
redeemer_message,
177
238
} ) ;
178
239
179
- // Finally transfer amount to custody token account. We perform exclusive or because we do not
180
- // want to allow specifying more than one authority.
181
- match (
182
- ctx. accounts . sender . as_ref ( ) ,
183
- ctx. accounts . program_transfer_authority . as_ref ( ) ,
184
- ) {
185
- ( Some ( sender) , None ) => token:: transfer (
186
- CpiContext :: new (
187
- ctx. accounts . token_program . to_account_info ( ) ,
188
- token:: Transfer {
189
- from : ctx. accounts . sender_token . to_account_info ( ) ,
190
- to : ctx. accounts . prepared_custody_token . to_account_info ( ) ,
191
- authority : sender. to_account_info ( ) ,
192
- } ,
193
- ) ,
194
- amount_in,
195
- ) ,
196
- ( None , Some ( program_transfer_authority) ) => token:: transfer (
197
- CpiContext :: new_with_signer (
198
- ctx. accounts . token_program . to_account_info ( ) ,
199
- token:: Transfer {
200
- from : ctx. accounts . sender_token . to_account_info ( ) ,
201
- to : ctx. accounts . prepared_custody_token . to_account_info ( ) ,
202
- authority : program_transfer_authority. to_account_info ( ) ,
203
- } ,
204
- & [ & [
205
- TRANSFER_AUTHORITY_SEED_PREFIX ,
206
- ctx. accounts . prepared_order . key ( ) . as_ref ( ) ,
207
- & hashed_args. 0 ,
208
- & [ ctx. bumps . program_transfer_authority . unwrap ( ) ] ,
209
- ] ] ,
210
- ) ,
211
- amount_in,
212
- ) ,
213
- ( None , None ) => err ! ( TokenRouterError :: MissingAuthority ) ,
214
- ( Some ( _) , Some ( _) ) => err ! ( TokenRouterError :: TooManyAuthorities ) ,
215
- }
240
+ // Done.
241
+ Ok ( ( ) )
216
242
}
0 commit comments