@@ -161,19 +161,18 @@ impl Processor {
161
161
return Ok ( ( ) ) ;
162
162
}
163
163
164
- let mut source_data = source_account_info. data . borrow_mut ( ) ;
165
- let mut dest_data = dest_account_info. data . borrow_mut ( ) ;
166
- Account :: unpack_mut ( & mut source_data, & mut |source_account : & mut Account | {
167
- Account :: unpack_mut ( & mut dest_data, & mut |dest_account : & mut Account | {
164
+ let mut source_account = Account :: unpack ( & source_account_info. data . borrow ( ) ) ?;
165
+ let mut dest_account = Account :: unpack ( & dest_account_info. data . borrow ( ) ) ?;
166
+
168
167
if source_account. amount < amount {
169
168
return Err ( TokenError :: InsufficientFunds . into ( ) ) ;
170
169
}
171
- if source_account. mint != dest_account. mint {
172
- return Err ( TokenError :: MintMismatch . into ( ) ) ;
173
- }
174
170
if source_account. is_frozen ( ) || dest_account. is_frozen ( ) {
175
171
return Err ( TokenError :: AccountFrozen . into ( ) ) ;
176
172
}
173
+ if source_account. mint != dest_account. mint {
174
+ return Err ( TokenError :: MintMismatch . into ( ) ) ;
175
+ }
177
176
178
177
if let Some ( ( mint_info, expected_decimals) ) = expected_mint_info {
179
178
if source_account. mint != * mint_info. key {
@@ -234,9 +233,10 @@ impl Processor {
234
233
. ok_or ( TokenError :: Overflow ) ?;
235
234
}
236
235
236
+ Account :: pack ( source_account, & mut source_account_info. data . borrow_mut ( ) ) ?;
237
+ Account :: pack ( dest_account, & mut dest_account_info. data . borrow_mut ( ) ) ?;
238
+
237
239
Ok ( ( ) )
238
- } )
239
- } )
240
240
}
241
241
242
242
/// Processes an [Approve](enum.TokenInstruction.html) instruction.
@@ -815,6 +815,13 @@ mod tests {
815
815
Processor :: process ( & instruction. program_id , & account_infos, & instruction. data )
816
816
}
817
817
818
+ fn do_process_instruction_dups (
819
+ instruction : Instruction ,
820
+ account_infos : Vec < AccountInfo > ,
821
+ ) -> ProgramResult {
822
+ Processor :: process ( & instruction. program_id , & account_infos, & instruction. data )
823
+ }
824
+
818
825
fn return_token_error_as_program_error ( ) -> ProgramError {
819
826
TokenError :: MintMismatch . into ( )
820
827
}
@@ -1089,6 +1096,318 @@ mod tests {
1089
1096
) ;
1090
1097
}
1091
1098
1099
+ #[ test]
1100
+ fn test_transfer_dups ( ) {
1101
+ let program_id = pubkey_rand ( ) ;
1102
+ let account1_key = pubkey_rand ( ) ;
1103
+ let mut account1_account = SolanaAccount :: new (
1104
+ account_minimum_balance ( ) ,
1105
+ Account :: get_packed_len ( ) ,
1106
+ & program_id,
1107
+ ) ;
1108
+ let mut account1_info: AccountInfo = ( & account1_key, true , & mut account1_account) . into ( ) ;
1109
+ let account2_key = pubkey_rand ( ) ;
1110
+ let mut account2_account = SolanaAccount :: new (
1111
+ account_minimum_balance ( ) ,
1112
+ Account :: get_packed_len ( ) ,
1113
+ & program_id,
1114
+ ) ;
1115
+ let mut account2_info: AccountInfo = ( & account2_key, false , & mut account2_account) . into ( ) ;
1116
+ let account3_key = pubkey_rand ( ) ;
1117
+ let mut account3_account = SolanaAccount :: new (
1118
+ account_minimum_balance ( ) ,
1119
+ Account :: get_packed_len ( ) ,
1120
+ & program_id,
1121
+ ) ;
1122
+ let account3_info: AccountInfo = ( & account3_key, false , & mut account3_account) . into ( ) ;
1123
+ let account4_key = pubkey_rand ( ) ;
1124
+ let mut account4_account = SolanaAccount :: new (
1125
+ account_minimum_balance ( ) ,
1126
+ Account :: get_packed_len ( ) ,
1127
+ & program_id,
1128
+ ) ;
1129
+ let account4_info: AccountInfo = ( & account4_key, true , & mut account4_account) . into ( ) ;
1130
+ let multisig_key = pubkey_rand ( ) ;
1131
+ let mut multisig_account = SolanaAccount :: new (
1132
+ multisig_minimum_balance ( ) ,
1133
+ Multisig :: get_packed_len ( ) ,
1134
+ & program_id,
1135
+ ) ;
1136
+ let multisig_info: AccountInfo = ( & multisig_key, true , & mut multisig_account) . into ( ) ;
1137
+ let owner_key = pubkey_rand ( ) ;
1138
+ let mut owner_account = SolanaAccount :: default ( ) ;
1139
+ let owner_info: AccountInfo = ( & owner_key, true , & mut owner_account) . into ( ) ;
1140
+ let mint_key = pubkey_rand ( ) ;
1141
+ let mut mint_account =
1142
+ SolanaAccount :: new ( mint_minimum_balance ( ) , Mint :: get_packed_len ( ) , & program_id) ;
1143
+ let mint_info: AccountInfo = ( & mint_key, false , & mut mint_account) . into ( ) ;
1144
+ let rent_key = rent:: id ( ) ;
1145
+ let mut rent_sysvar = rent_sysvar ( ) ;
1146
+ let rent_info: AccountInfo = ( & rent_key, false , & mut rent_sysvar) . into ( ) ;
1147
+
1148
+ // create mint
1149
+ do_process_instruction_dups (
1150
+ initialize_mint ( & program_id, & mint_key, & owner_key, None , 2 ) . unwrap ( ) ,
1151
+ vec ! [ mint_info. clone( ) , rent_info. clone( ) ] ,
1152
+ )
1153
+ . unwrap ( ) ;
1154
+
1155
+ // create account
1156
+ do_process_instruction_dups (
1157
+ initialize_account ( & program_id, & account1_key, & mint_key, & account1_key) . unwrap ( ) ,
1158
+ vec ! [
1159
+ account1_info. clone( ) ,
1160
+ mint_info. clone( ) ,
1161
+ account1_info. clone( ) ,
1162
+ rent_info. clone( ) ,
1163
+ ] ,
1164
+ )
1165
+ . unwrap ( ) ;
1166
+
1167
+ // create another account
1168
+ do_process_instruction_dups (
1169
+ initialize_account ( & program_id, & account2_key, & mint_key, & owner_key) . unwrap ( ) ,
1170
+ vec ! [
1171
+ account2_info. clone( ) ,
1172
+ mint_info. clone( ) ,
1173
+ owner_info. clone( ) ,
1174
+ rent_info. clone( ) ,
1175
+ ] ,
1176
+ )
1177
+ . unwrap ( ) ;
1178
+
1179
+ // mint to account
1180
+ do_process_instruction_dups (
1181
+ mint_to ( & program_id, & mint_key, & account1_key, & owner_key, & [ ] , 1000 ) . unwrap ( ) ,
1182
+ vec ! [ mint_info. clone( ) , account1_info. clone( ) , owner_info. clone( ) ] ,
1183
+ )
1184
+ . unwrap ( ) ;
1185
+
1186
+ // source-owner transfer
1187
+ do_process_instruction_dups (
1188
+ transfer (
1189
+ & program_id,
1190
+ & account1_key,
1191
+ & account2_key,
1192
+ & account1_key,
1193
+ & [ ] ,
1194
+ 500 ,
1195
+ )
1196
+ . unwrap ( ) ,
1197
+ vec ! [
1198
+ account1_info. clone( ) ,
1199
+ account2_info. clone( ) ,
1200
+ account1_info. clone( ) ,
1201
+ ] ,
1202
+ )
1203
+ . unwrap ( ) ;
1204
+
1205
+ // source-owner transfer2
1206
+ do_process_instruction_dups (
1207
+ transfer2 (
1208
+ & program_id,
1209
+ & account1_key,
1210
+ & mint_key,
1211
+ & account2_key,
1212
+ & account1_key,
1213
+ & [ ] ,
1214
+ 500 ,
1215
+ 2 ,
1216
+ )
1217
+ . unwrap ( ) ,
1218
+ vec ! [
1219
+ account1_info. clone( ) ,
1220
+ mint_info. clone( ) ,
1221
+ account2_info. clone( ) ,
1222
+ account1_info. clone( ) ,
1223
+ ] ,
1224
+ )
1225
+ . unwrap ( ) ;
1226
+
1227
+ // source-delegate transfer
1228
+ Account :: unpack_unchecked_mut (
1229
+ & mut account1_info. data . borrow_mut ( ) ,
1230
+ & mut |account : & mut Account | {
1231
+ account. amount = 1000 ;
1232
+ account. delegated_amount = 1000 ;
1233
+ account. delegate = COption :: Some ( account1_key) ;
1234
+ account. owner = owner_key;
1235
+ Ok ( ( ) )
1236
+ } ,
1237
+ )
1238
+ . unwrap ( ) ;
1239
+
1240
+ do_process_instruction_dups (
1241
+ transfer (
1242
+ & program_id,
1243
+ & account1_key,
1244
+ & account2_key,
1245
+ & account1_key,
1246
+ & [ ] ,
1247
+ 500 ,
1248
+ )
1249
+ . unwrap ( ) ,
1250
+ vec ! [
1251
+ account1_info. clone( ) ,
1252
+ account2_info. clone( ) ,
1253
+ account1_info. clone( ) ,
1254
+ ] ,
1255
+ )
1256
+ . unwrap ( ) ;
1257
+
1258
+ // source-delegate transfer2
1259
+ do_process_instruction_dups (
1260
+ transfer2 (
1261
+ & program_id,
1262
+ & account1_key,
1263
+ & mint_key,
1264
+ & account2_key,
1265
+ & account1_key,
1266
+ & [ ] ,
1267
+ 500 ,
1268
+ 2 ,
1269
+ )
1270
+ . unwrap ( ) ,
1271
+ vec ! [
1272
+ account1_info. clone( ) ,
1273
+ mint_info. clone( ) ,
1274
+ account2_info. clone( ) ,
1275
+ account1_info. clone( ) ,
1276
+ ] ,
1277
+ )
1278
+ . unwrap ( ) ;
1279
+
1280
+ // test destination-owner transfer
1281
+ do_process_instruction_dups (
1282
+ initialize_account ( & program_id, & account3_key, & mint_key, & account2_key) . unwrap ( ) ,
1283
+ vec ! [
1284
+ account3_info. clone( ) ,
1285
+ mint_info. clone( ) ,
1286
+ account2_info. clone( ) ,
1287
+ rent_info. clone( ) ,
1288
+ ] ,
1289
+ )
1290
+ . unwrap ( ) ;
1291
+ do_process_instruction_dups (
1292
+ mint_to ( & program_id, & mint_key, & account3_key, & owner_key, & [ ] , 1000 ) . unwrap ( ) ,
1293
+ vec ! [ mint_info. clone( ) , account3_info. clone( ) , owner_info. clone( ) ] ,
1294
+ )
1295
+ . unwrap ( ) ;
1296
+
1297
+ account1_info. is_signer = false ;
1298
+ account2_info. is_signer = true ;
1299
+ do_process_instruction_dups (
1300
+ transfer (
1301
+ & program_id,
1302
+ & account3_key,
1303
+ & account2_key,
1304
+ & account2_key,
1305
+ & [ ] ,
1306
+ 500 ,
1307
+ )
1308
+ . unwrap ( ) ,
1309
+ vec ! [
1310
+ account3_info. clone( ) ,
1311
+ account2_info. clone( ) ,
1312
+ account2_info. clone( ) ,
1313
+ ] ,
1314
+ )
1315
+ . unwrap ( ) ;
1316
+
1317
+ // destination-owner transfer2
1318
+ do_process_instruction_dups (
1319
+ transfer2 (
1320
+ & program_id,
1321
+ & account3_key,
1322
+ & mint_key,
1323
+ & account2_key,
1324
+ & account2_key,
1325
+ & [ ] ,
1326
+ 500 ,
1327
+ 2 ,
1328
+ )
1329
+ . unwrap ( ) ,
1330
+ vec ! [
1331
+ account3_info. clone( ) ,
1332
+ mint_info. clone( ) ,
1333
+ account2_info. clone( ) ,
1334
+ account2_info. clone( ) ,
1335
+ ] ,
1336
+ )
1337
+ . unwrap ( ) ;
1338
+
1339
+ // test source-multisig signer
1340
+ do_process_instruction_dups (
1341
+ initialize_multisig ( & program_id, & multisig_key, & [ & account4_key] , 1 ) . unwrap ( ) ,
1342
+ vec ! [
1343
+ multisig_info. clone( ) ,
1344
+ rent_info. clone( ) ,
1345
+ account4_info. clone( ) ,
1346
+ ] ,
1347
+ )
1348
+ . unwrap ( ) ;
1349
+
1350
+ do_process_instruction_dups (
1351
+ initialize_account ( & program_id, & account4_key, & mint_key, & multisig_key) . unwrap ( ) ,
1352
+ vec ! [
1353
+ account4_info. clone( ) ,
1354
+ mint_info. clone( ) ,
1355
+ multisig_info. clone( ) ,
1356
+ rent_info. clone( ) ,
1357
+ ] ,
1358
+ )
1359
+ . unwrap ( ) ;
1360
+
1361
+ do_process_instruction_dups (
1362
+ mint_to ( & program_id, & mint_key, & account4_key, & owner_key, & [ ] , 1000 ) . unwrap ( ) ,
1363
+ vec ! [ mint_info. clone( ) , account4_info. clone( ) , owner_info. clone( ) ] ,
1364
+ )
1365
+ . unwrap ( ) ;
1366
+
1367
+ // source-multisig-signer transfer
1368
+ do_process_instruction_dups (
1369
+ transfer (
1370
+ & program_id,
1371
+ & account4_key,
1372
+ & account2_key,
1373
+ & multisig_key,
1374
+ & [ & account4_key] ,
1375
+ 500 ,
1376
+ )
1377
+ . unwrap ( ) ,
1378
+ vec ! [
1379
+ account4_info. clone( ) ,
1380
+ account2_info. clone( ) ,
1381
+ multisig_info. clone( ) ,
1382
+ account4_info. clone( ) ,
1383
+ ] ,
1384
+ )
1385
+ . unwrap ( ) ;
1386
+
1387
+ // source-multisig-signer transfer2
1388
+ do_process_instruction_dups (
1389
+ transfer2 (
1390
+ & program_id,
1391
+ & account4_key,
1392
+ & mint_key,
1393
+ & account2_key,
1394
+ & multisig_key,
1395
+ & [ & account4_key] ,
1396
+ 500 ,
1397
+ 2 ,
1398
+ )
1399
+ . unwrap ( ) ,
1400
+ vec ! [
1401
+ account4_info. clone( ) ,
1402
+ mint_info. clone( ) ,
1403
+ account2_info. clone( ) ,
1404
+ multisig_info. clone( ) ,
1405
+ account4_info. clone( ) ,
1406
+ ] ,
1407
+ )
1408
+ . unwrap ( ) ;
1409
+ }
1410
+
1092
1411
#[ test]
1093
1412
fn test_transfer ( ) {
1094
1413
let program_id = pubkey_rand ( ) ;
0 commit comments