Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 449d74b

Browse files
committed
backport #433 to v2
1 parent 08fe830 commit 449d74b

File tree

1 file changed

+328
-9
lines changed

1 file changed

+328
-9
lines changed

token/program/src/processor.rs

Lines changed: 328 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,19 +161,18 @@ impl Processor {
161161
return Ok(());
162162
}
163163

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+
168167
if source_account.amount < amount {
169168
return Err(TokenError::InsufficientFunds.into());
170169
}
171-
if source_account.mint != dest_account.mint {
172-
return Err(TokenError::MintMismatch.into());
173-
}
174170
if source_account.is_frozen() || dest_account.is_frozen() {
175171
return Err(TokenError::AccountFrozen.into());
176172
}
173+
if source_account.mint != dest_account.mint {
174+
return Err(TokenError::MintMismatch.into());
175+
}
177176

178177
if let Some((mint_info, expected_decimals)) = expected_mint_info {
179178
if source_account.mint != *mint_info.key {
@@ -234,9 +233,10 @@ impl Processor {
234233
.ok_or(TokenError::Overflow)?;
235234
}
236235

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+
237239
Ok(())
238-
})
239-
})
240240
}
241241

242242
/// Processes an [Approve](enum.TokenInstruction.html) instruction.
@@ -815,6 +815,13 @@ mod tests {
815815
Processor::process(&instruction.program_id, &account_infos, &instruction.data)
816816
}
817817

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+
818825
fn return_token_error_as_program_error() -> ProgramError {
819826
TokenError::MintMismatch.into()
820827
}
@@ -1089,6 +1096,318 @@ mod tests {
10891096
);
10901097
}
10911098

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+
10921411
#[test]
10931412
fn test_transfer() {
10941413
let program_id = pubkey_rand();

0 commit comments

Comments
 (0)