Skip to content

Commit d14c98b

Browse files
[program] Account for the confidential transfer fee extension when re-allocating during configure account (#172)
* account for confidential transfer fee extension when re-allocating * add tests for configuring accouts with registry when there are fees * add check that `TransferFeeAmount` and `ConfidentialTransferFeeAmount` extensions are present * remove unnecessary logic
1 parent 3fac5c5 commit d14c98b

File tree

3 files changed

+132
-12
lines changed

3 files changed

+132
-12
lines changed

clients/rust-legacy/tests/confidential_transfer.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3203,14 +3203,6 @@ async fn confidential_transfer_configure_token_account_with_registry() {
32033203

32043204
let TokenContext { token, alice, .. } = context.token_context.unwrap();
32053205
let alice_account_keypair = Keypair::new();
3206-
token
3207-
.create_auxiliary_token_account_with_extension_space(
3208-
&alice_account_keypair,
3209-
&alice.pubkey(),
3210-
vec![ExtensionType::ConfidentialTransferAccount],
3211-
)
3212-
.await
3213-
.unwrap();
32143206
let elgamal_keypair = ElGamalKeypair::new_rand();
32153207

32163208
// create ElGamal registry
@@ -3273,7 +3265,6 @@ async fn confidential_transfer_configure_token_account_with_registry() {
32733265
drop(ctx);
32743266

32753267
// configure account using ElGamal registry
3276-
let alice_account_keypair = Keypair::new();
32773268
let alice_token_account = alice_account_keypair.pubkey();
32783269
token
32793270
.create_auxiliary_token_account_with_extension_space(

clients/rust-legacy/tests/confidential_transfer_fee.rs

Lines changed: 129 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,23 @@ use {
88
pubkey::Pubkey,
99
signature::Signer,
1010
signer::{keypair::Keypair, signers::Signers},
11-
transaction::TransactionError,
11+
system_instruction,
12+
transaction::{Transaction, TransactionError},
1213
transport::TransportError,
1314
},
15+
spl_elgamal_registry::state::ELGAMAL_REGISTRY_ACCOUNT_LEN,
1416
spl_record::state::RecordData,
1517
spl_token_2022::{
1618
error::TokenError,
1719
extension::{
1820
confidential_transfer::{
19-
ConfidentialTransferAccount, ConfidentialTransferMint, DecryptableBalance,
21+
self, ConfidentialTransferAccount, ConfidentialTransferMint, DecryptableBalance,
2022
},
2123
confidential_transfer_fee::{
2224
account_info::WithheldTokensInfo, ConfidentialTransferFeeAmount,
2325
ConfidentialTransferFeeConfig,
2426
},
25-
transfer_fee::TransferFee,
27+
transfer_fee::{TransferFee, TransferFeeAmount},
2628
BaseStateWithExtensions, ExtensionType,
2729
},
2830
instruction,
@@ -37,6 +39,7 @@ use {
3739
TokenResult,
3840
},
3941
},
42+
spl_token_confidential_transfer_proof_extraction::instruction::{ProofData, ProofLocation},
4043
std::convert::TryInto,
4144
};
4245

@@ -1207,3 +1210,126 @@ async fn confidential_transfer_harvest_withheld_tokens_to_mint() {
12071210

12081211
check_withheld_amount_in_mint(&token, &withdraw_withheld_authority_elgamal_keypair, fee).await;
12091212
}
1213+
1214+
#[tokio::test]
1215+
async fn confidential_transfer_configure_token_account_with_fee_with_registry() {
1216+
let transfer_fee_authority = Keypair::new();
1217+
let withdraw_withheld_authority = Keypair::new();
1218+
1219+
let confidential_transfer_authority = Keypair::new();
1220+
let auto_approve_new_accounts = true;
1221+
let auditor_elgamal_keypair = ElGamalKeypair::new_rand();
1222+
let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into();
1223+
1224+
let confidential_transfer_fee_authority = Keypair::new();
1225+
let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand();
1226+
let withdraw_withheld_authority_elgamal_pubkey =
1227+
(*withdraw_withheld_authority_elgamal_keypair.pubkey()).into();
1228+
1229+
let mut context = TestContext::new().await;
1230+
context
1231+
.init_token_with_mint(vec![
1232+
ExtensionInitializationParams::TransferFeeConfig {
1233+
transfer_fee_config_authority: Some(transfer_fee_authority.pubkey()),
1234+
withdraw_withheld_authority: Some(withdraw_withheld_authority.pubkey()),
1235+
transfer_fee_basis_points: TEST_FEE_BASIS_POINTS,
1236+
maximum_fee: TEST_MAXIMUM_FEE,
1237+
},
1238+
ExtensionInitializationParams::ConfidentialTransferMint {
1239+
authority: Some(confidential_transfer_authority.pubkey()),
1240+
auto_approve_new_accounts,
1241+
auditor_elgamal_pubkey: Some(auditor_elgamal_pubkey),
1242+
},
1243+
ExtensionInitializationParams::ConfidentialTransferFeeConfig {
1244+
authority: Some(confidential_transfer_fee_authority.pubkey()),
1245+
withdraw_withheld_authority_elgamal_pubkey,
1246+
},
1247+
])
1248+
.await
1249+
.unwrap();
1250+
1251+
let TokenContext { token, alice, .. } = context.token_context.unwrap();
1252+
let elgamal_keypair = ElGamalKeypair::new_rand();
1253+
1254+
// create ElGamal registry
1255+
let ctx = context.context.lock().await;
1256+
let proof_data =
1257+
confidential_transfer::instruction::PubkeyValidityProofData::new(&elgamal_keypair).unwrap();
1258+
let proof_location = ProofLocation::InstructionOffset(
1259+
1.try_into().unwrap(),
1260+
ProofData::InstructionData(&proof_data),
1261+
);
1262+
1263+
let elgamal_registry_address = spl_elgamal_registry::get_elgamal_registry_address(
1264+
&alice.pubkey(),
1265+
&spl_elgamal_registry::id(),
1266+
);
1267+
1268+
let rent = ctx.banks_client.get_rent().await.unwrap();
1269+
let space = ELGAMAL_REGISTRY_ACCOUNT_LEN;
1270+
let system_instruction = system_instruction::transfer(
1271+
&ctx.payer.pubkey(),
1272+
&elgamal_registry_address,
1273+
rent.minimum_balance(space),
1274+
);
1275+
let create_registry_instructions =
1276+
spl_elgamal_registry::instruction::create_registry(&alice.pubkey(), proof_location)
1277+
.unwrap();
1278+
1279+
let instructions = [&[system_instruction], &create_registry_instructions[..]].concat();
1280+
let tx = Transaction::new_signed_with_payer(
1281+
&instructions,
1282+
Some(&ctx.payer.pubkey()),
1283+
&[&ctx.payer, &alice],
1284+
ctx.last_blockhash,
1285+
);
1286+
ctx.banks_client.process_transaction(tx).await.unwrap();
1287+
1288+
let payer_pubkey = ctx.payer.pubkey();
1289+
drop(ctx);
1290+
1291+
// configure account using ElGamal registry
1292+
let alice_account_keypair = Keypair::new();
1293+
let alice_token_account = alice_account_keypair.pubkey();
1294+
token
1295+
.create_auxiliary_token_account_with_extension_space(
1296+
&alice_account_keypair,
1297+
&alice.pubkey(),
1298+
vec![], // do not allocate space for confidential transfer fees
1299+
)
1300+
.await
1301+
.unwrap();
1302+
1303+
token
1304+
.confidential_transfer_configure_token_account_with_registry(
1305+
&alice_account_keypair.pubkey(),
1306+
&elgamal_registry_address,
1307+
Some(&payer_pubkey), // test account allocation
1308+
)
1309+
.await
1310+
.unwrap();
1311+
1312+
let state = token.get_account_info(&alice_token_account).await.unwrap();
1313+
let confidential_transfer_account = state
1314+
.get_extension::<ConfidentialTransferAccount>()
1315+
.unwrap();
1316+
assert!(bool::from(&confidential_transfer_account.approved));
1317+
assert!(bool::from(
1318+
&confidential_transfer_account.allow_confidential_credits
1319+
));
1320+
assert_eq!(
1321+
confidential_transfer_account.elgamal_pubkey,
1322+
(*elgamal_keypair.pubkey()).into()
1323+
);
1324+
1325+
let transfer_fee = state.get_extension::<TransferFeeAmount>().unwrap();
1326+
assert_eq!(transfer_fee.withheld_amount, 0.into());
1327+
1328+
let confidential_transfer_fee = state
1329+
.get_extension::<ConfidentialTransferFeeAmount>()
1330+
.unwrap();
1331+
assert_eq!(
1332+
confidential_transfer_fee.withheld_amount,
1333+
PodElGamalCiphertext::default(),
1334+
);
1335+
}

program/src/extension/confidential_transfer/processor.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ fn reallocate_for_configure_account_with_registry<'a>(
157157
// `try_calculate_account_len` dedupes extension types, so always push
158158
// the `ConfidentialTransferAccount` type
159159
current_extension_types.push(ExtensionType::ConfidentialTransferAccount);
160+
if current_extension_types.contains(&ExtensionType::TransferFeeAmount) {
161+
current_extension_types.push(ExtensionType::ConfidentialTransferFeeAmount);
162+
}
160163
let needed_account_len =
161164
ExtensionType::try_calculate_account_len::<Account>(&current_extension_types)?;
162165

0 commit comments

Comments
 (0)