Spell out destination (#2977)
This commit is contained in:
parent
00767dbd28
commit
e17706c7be
|
@ -480,7 +480,7 @@ where
|
|||
/// Mint new tokens
|
||||
pub async fn mint_to<S2: Signer>(
|
||||
&self,
|
||||
dest: &Pubkey,
|
||||
destination: &Pubkey,
|
||||
authority: &S2,
|
||||
amount: u64,
|
||||
) -> TokenResult<()> {
|
||||
|
@ -488,7 +488,7 @@ where
|
|||
&[instruction::mint_to(
|
||||
&self.program_id,
|
||||
&self.pubkey,
|
||||
dest,
|
||||
destination,
|
||||
&authority.pubkey(),
|
||||
&[],
|
||||
amount,
|
||||
|
|
|
@ -254,7 +254,7 @@ fn process_deposit(
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let token_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_token_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_token_account_info = next_account_info(account_info_iter)?;
|
||||
let mint_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
let authority_info_data_len = authority_info.data_len();
|
||||
|
@ -307,33 +307,35 @@ fn process_deposit(
|
|||
|
||||
// Process destination account
|
||||
{
|
||||
check_program_account(dest_token_account_info.owner)?;
|
||||
let dest_token_account_data = &mut dest_token_account_info.data.borrow_mut();
|
||||
let mut dest_token_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(dest_token_account_data)?;
|
||||
check_program_account(destination_token_account_info.owner)?;
|
||||
let destination_token_account_data = &mut destination_token_account_info.data.borrow_mut();
|
||||
let mut destination_token_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(destination_token_account_data)?;
|
||||
|
||||
if dest_token_account.base.is_frozen() {
|
||||
if destination_token_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
|
||||
if dest_token_account.base.mint != *mint_info.key {
|
||||
if destination_token_account.base.mint != *mint_info.key {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
let mut dest_confidential_transfer_account =
|
||||
dest_token_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
dest_confidential_transfer_account.approved()?;
|
||||
let mut destination_confidential_transfer_account =
|
||||
destination_token_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
destination_confidential_transfer_account.approved()?;
|
||||
|
||||
if !bool::from(&dest_confidential_transfer_account.allow_balance_credits) {
|
||||
if !bool::from(&destination_confidential_transfer_account.allow_balance_credits) {
|
||||
return Err(TokenError::ConfidentialTransferDepositsAndTransfersDisabled.into());
|
||||
}
|
||||
|
||||
dest_confidential_transfer_account.pending_balance =
|
||||
ops::add_to(&dest_confidential_transfer_account.pending_balance, amount)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
destination_confidential_transfer_account.pending_balance = ops::add_to(
|
||||
&destination_confidential_transfer_account.pending_balance,
|
||||
amount,
|
||||
)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
dest_confidential_transfer_account.pending_balance_credit_counter =
|
||||
(u64::from(dest_confidential_transfer_account.pending_balance_credit_counter)
|
||||
destination_confidential_transfer_account.pending_balance_credit_counter =
|
||||
(u64::from(destination_confidential_transfer_account.pending_balance_credit_counter)
|
||||
.checked_add(1)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?)
|
||||
.into();
|
||||
|
@ -353,7 +355,7 @@ fn process_withdraw(
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let token_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_token_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_token_account_info = next_account_info(account_info_iter)?;
|
||||
let mint_info = next_account_info(account_info_iter)?;
|
||||
let instructions_sysvar_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
|
@ -419,28 +421,28 @@ fn process_withdraw(
|
|||
|
||||
// Process destination account
|
||||
{
|
||||
check_program_account(dest_token_account_info.owner)?;
|
||||
let dest_token_account_data = &mut dest_token_account_info.data.borrow_mut();
|
||||
let mut dest_token_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(dest_token_account_data)?;
|
||||
check_program_account(destination_token_account_info.owner)?;
|
||||
let destination_token_account_data = &mut destination_token_account_info.data.borrow_mut();
|
||||
let mut destination_token_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(destination_token_account_data)?;
|
||||
|
||||
if dest_token_account.base.is_frozen() {
|
||||
if destination_token_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
|
||||
if dest_token_account.base.mint != *mint_info.key {
|
||||
if destination_token_account.base.mint != *mint_info.key {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
// Wrapped SOL withdrawals are not supported because lamports cannot be apparated.
|
||||
assert!(!dest_token_account.base.is_native());
|
||||
dest_token_account.base.amount = dest_token_account
|
||||
assert!(!destination_token_account.base.is_native());
|
||||
destination_token_account.base.amount = destination_token_account
|
||||
.base
|
||||
.amount
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
dest_token_account.pack_base();
|
||||
destination_token_account.pack_base();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -455,7 +457,7 @@ fn process_transfer(
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let token_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_token_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_token_account_info = next_account_info(account_info_iter)?;
|
||||
let mint_info = next_account_info(account_info_iter)?;
|
||||
let instructions_sysvar_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
|
@ -540,8 +542,8 @@ fn process_transfer(
|
|||
&ciphertext_hi,
|
||||
new_source_decryptable_available_balance,
|
||||
)?;
|
||||
process_dest_for_transfer(
|
||||
dest_token_account_info,
|
||||
process_destination_for_transfer(
|
||||
destination_token_account_info,
|
||||
mint_info,
|
||||
&proof_data.transfer_with_fee_pubkeys.pubkey_dest,
|
||||
&ciphertext_lo,
|
||||
|
@ -579,8 +581,8 @@ fn process_transfer(
|
|||
new_source_decryptable_available_balance,
|
||||
)?;
|
||||
|
||||
process_dest_for_transfer(
|
||||
dest_token_account_info,
|
||||
process_destination_for_transfer(
|
||||
destination_token_account_info,
|
||||
mint_info,
|
||||
&proof_data.transfer_pubkeys.pubkey_dest,
|
||||
&ciphertext_lo,
|
||||
|
@ -648,56 +650,57 @@ fn process_source_for_transfer(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn process_dest_for_transfer(
|
||||
dest_token_account_info: &AccountInfo,
|
||||
fn process_destination_for_transfer(
|
||||
destination_token_account_info: &AccountInfo,
|
||||
mint_info: &AccountInfo,
|
||||
elgamal_pubkey_dest: &EncryptionPubkey,
|
||||
ciphertext_lo_dest: &EncryptedBalance,
|
||||
ciphertext_hi_dest: &EncryptedBalance,
|
||||
ciphertext_lo_destination: &EncryptedBalance,
|
||||
ciphertext_hi_destination: &EncryptedBalance,
|
||||
encrypted_fee: Option<EncryptedFee>,
|
||||
) -> ProgramResult {
|
||||
check_program_account(dest_token_account_info.owner)?;
|
||||
let dest_token_account_data = &mut dest_token_account_info.data.borrow_mut();
|
||||
let mut dest_token_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(dest_token_account_data)?;
|
||||
check_program_account(destination_token_account_info.owner)?;
|
||||
let destination_token_account_data = &mut destination_token_account_info.data.borrow_mut();
|
||||
let mut destination_token_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(destination_token_account_data)?;
|
||||
|
||||
if dest_token_account.base.is_frozen() {
|
||||
if destination_token_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
|
||||
if dest_token_account.base.mint != *mint_info.key {
|
||||
if destination_token_account.base.mint != *mint_info.key {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
let mut dest_confidential_transfer_account =
|
||||
dest_token_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
dest_confidential_transfer_account.approved()?;
|
||||
let mut destination_confidential_transfer_account =
|
||||
destination_token_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
destination_confidential_transfer_account.approved()?;
|
||||
|
||||
if !bool::from(&dest_confidential_transfer_account.allow_balance_credits) {
|
||||
if !bool::from(&destination_confidential_transfer_account.allow_balance_credits) {
|
||||
return Err(TokenError::ConfidentialTransferDepositsAndTransfersDisabled.into());
|
||||
}
|
||||
|
||||
if *elgamal_pubkey_dest != dest_confidential_transfer_account.pubkey_elgamal {
|
||||
if *elgamal_pubkey_dest != destination_confidential_transfer_account.pubkey_elgamal {
|
||||
return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into());
|
||||
}
|
||||
|
||||
let new_dest_pending_balance = ops::add_with_lo_hi(
|
||||
&dest_confidential_transfer_account.pending_balance,
|
||||
ciphertext_lo_dest,
|
||||
ciphertext_hi_dest,
|
||||
let new_destination_pending_balance = ops::add_with_lo_hi(
|
||||
&destination_confidential_transfer_account.pending_balance,
|
||||
ciphertext_lo_destination,
|
||||
ciphertext_hi_destination,
|
||||
)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
let new_dest_pending_balance_credit_counter =
|
||||
(u64::from(dest_confidential_transfer_account.pending_balance_credit_counter) + 1).into();
|
||||
let new_destination_pending_balance_credit_counter =
|
||||
(u64::from(destination_confidential_transfer_account.pending_balance_credit_counter) + 1)
|
||||
.into();
|
||||
|
||||
dest_confidential_transfer_account.pending_balance = new_dest_pending_balance;
|
||||
dest_confidential_transfer_account.pending_balance_credit_counter =
|
||||
new_dest_pending_balance_credit_counter;
|
||||
destination_confidential_transfer_account.pending_balance = new_destination_pending_balance;
|
||||
destination_confidential_transfer_account.pending_balance_credit_counter =
|
||||
new_destination_pending_balance_credit_counter;
|
||||
|
||||
// update destination account withheld fees
|
||||
if let Some(ciphertext_fee) = encrypted_fee {
|
||||
let ciphertext_fee_dest: EncryptedWithheldAmount =
|
||||
let ciphertext_fee_destination: EncryptedWithheldAmount =
|
||||
(ciphertext_fee.commitment, ciphertext_fee.handle_dest).into();
|
||||
let ciphertext_fee_withheld_authority: EncryptedWithheldAmount = (
|
||||
ciphertext_fee.commitment,
|
||||
|
@ -706,21 +709,21 @@ fn process_dest_for_transfer(
|
|||
.into();
|
||||
|
||||
// subtract fee from destination pending balance
|
||||
let new_dest_pending_balance = ops::subtract(
|
||||
&dest_confidential_transfer_account.pending_balance,
|
||||
&ciphertext_fee_dest,
|
||||
let new_destination_pending_balance = ops::subtract(
|
||||
&destination_confidential_transfer_account.pending_balance,
|
||||
&ciphertext_fee_destination,
|
||||
)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
// add encrypted fee to current withheld fee
|
||||
let new_withheld_amount = ops::add(
|
||||
&dest_confidential_transfer_account.withheld_amount,
|
||||
&destination_confidential_transfer_account.withheld_amount,
|
||||
&ciphertext_fee_withheld_authority,
|
||||
)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
dest_confidential_transfer_account.pending_balance = new_dest_pending_balance;
|
||||
dest_confidential_transfer_account.withheld_amount = new_withheld_amount;
|
||||
destination_confidential_transfer_account.pending_balance = new_destination_pending_balance;
|
||||
destination_confidential_transfer_account.withheld_amount = new_withheld_amount;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -810,7 +813,7 @@ fn process_withdraw_withheld_tokens_from_mint(
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let mint_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let instructions_sysvar_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
let authority_info_data_len = authority_info.data_len();
|
||||
|
@ -836,17 +839,18 @@ fn process_withdraw_withheld_tokens_from_mint(
|
|||
let confidential_transfer_mint = mint.get_extension_mut::<ConfidentialTransferMint>()?;
|
||||
|
||||
// basic checks for the destination account - must be extended for confidential transfers
|
||||
let mut dest_account_data = dest_account_info.data.borrow_mut();
|
||||
let mut dest_account = StateWithExtensionsMut::<Account>::unpack(&mut dest_account_data)?;
|
||||
if dest_account.base.mint != *mint_account_info.key {
|
||||
let mut destination_account_data = destination_account_info.data.borrow_mut();
|
||||
let mut destination_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(&mut destination_account_data)?;
|
||||
if destination_account.base.mint != *mint_account_info.key {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
if dest_account.base.is_frozen() {
|
||||
if destination_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
let mut dest_confidential_transfer_account =
|
||||
dest_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
dest_confidential_transfer_account.approved()?;
|
||||
let mut destination_confidential_transfer_account =
|
||||
destination_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
destination_confidential_transfer_account.approved()?;
|
||||
// verify consistency of proof data
|
||||
let previous_instruction =
|
||||
get_instruction_relative(proof_instruction_offset, instructions_sysvar_info)?;
|
||||
|
@ -863,7 +867,7 @@ fn process_withdraw_withheld_tokens_from_mint(
|
|||
}
|
||||
|
||||
// destination ElGamal pubkey should match in the proof data and destination account
|
||||
if proof_data.pubkey_dest != dest_confidential_transfer_account.pubkey_elgamal {
|
||||
if proof_data.pubkey_dest != destination_confidential_transfer_account.pubkey_elgamal {
|
||||
return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -876,13 +880,13 @@ fn process_withdraw_withheld_tokens_from_mint(
|
|||
|
||||
// The proof data contains the mint withheld amount encrypted under the destination ElGamal pubkey.
|
||||
// This amount should be added to the destination pending balance.
|
||||
let new_dest_pending_balance = ops::add(
|
||||
&dest_confidential_transfer_account.pending_balance,
|
||||
let new_destination_pending_balance = ops::add(
|
||||
&destination_confidential_transfer_account.pending_balance,
|
||||
&proof_data.ciphertext_dest,
|
||||
)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
dest_confidential_transfer_account.pending_balance = new_dest_pending_balance;
|
||||
destination_confidential_transfer_account.pending_balance = new_destination_pending_balance;
|
||||
|
||||
// fee is now withdrawn, so zero out mint withheld amount
|
||||
confidential_transfer_mint.withheld_amount = EncryptedWithheldAmount::zeroed();
|
||||
|
@ -898,7 +902,7 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let mint_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let instructions_sysvar_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
let authority_info_data_len = authority_info.data_len();
|
||||
|
@ -923,12 +927,13 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
&account_infos[..num_signers],
|
||||
)?;
|
||||
|
||||
let mut dest_account_data = dest_account_info.data.borrow_mut();
|
||||
let mut dest_account = StateWithExtensionsMut::<Account>::unpack(&mut dest_account_data)?;
|
||||
if dest_account.base.mint != *mint_account_info.key {
|
||||
let mut destination_account_data = destination_account_info.data.borrow_mut();
|
||||
let mut destination_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(&mut destination_account_data)?;
|
||||
if destination_account.base.mint != *mint_account_info.key {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
if dest_account.base.is_frozen() {
|
||||
if destination_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
|
||||
|
@ -936,18 +941,19 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
let mut aggregate_withheld_amount = EncryptedWithheldAmount::zeroed();
|
||||
for account_info in &account_infos[num_signers..] {
|
||||
// self-harvest, can't double-borrow the underlying data
|
||||
if account_info.key == dest_account_info.key {
|
||||
let confidential_transfer_dest_account = dest_account
|
||||
if account_info.key == destination_account_info.key {
|
||||
let confidential_transfer_destination_account = destination_account
|
||||
.get_extension_mut::<ConfidentialTransferAccount>()
|
||||
.map_err(|_| TokenError::InvalidState)?;
|
||||
|
||||
aggregate_withheld_amount = ops::add(
|
||||
&aggregate_withheld_amount,
|
||||
&confidential_transfer_dest_account.withheld_amount,
|
||||
&confidential_transfer_destination_account.withheld_amount,
|
||||
)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
confidential_transfer_dest_account.withheld_amount = EncryptedWithheldAmount::zeroed();
|
||||
confidential_transfer_destination_account.withheld_amount =
|
||||
EncryptedWithheldAmount::zeroed();
|
||||
} else {
|
||||
match harvest_from_account(mint_account_info.key, account_info) {
|
||||
Ok(encrypted_withheld_amount) => {
|
||||
|
@ -962,9 +968,9 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
}
|
||||
}
|
||||
|
||||
let mut dest_confidential_transfer_account =
|
||||
dest_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
dest_confidential_transfer_account.approved()?;
|
||||
let mut destination_confidential_transfer_account =
|
||||
destination_account.get_extension_mut::<ConfidentialTransferAccount>()?;
|
||||
destination_confidential_transfer_account.approved()?;
|
||||
// verify consistency of proof data
|
||||
let previous_instruction =
|
||||
get_instruction_relative(proof_instruction_offset, instructions_sysvar_info)?;
|
||||
|
@ -982,7 +988,7 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
}
|
||||
|
||||
// destination ElGamal pubkey should match in the proof data and destination account
|
||||
if proof_data.pubkey_dest != dest_confidential_transfer_account.pubkey_elgamal {
|
||||
if proof_data.pubkey_dest != destination_confidential_transfer_account.pubkey_elgamal {
|
||||
return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -992,13 +998,13 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
}
|
||||
|
||||
// add the sum of the withheld fees to destination pending balance
|
||||
let new_dest_pending_balance = ops::add(
|
||||
&dest_confidential_transfer_account.pending_balance,
|
||||
let new_destination_pending_balance = ops::add(
|
||||
&destination_confidential_transfer_account.pending_balance,
|
||||
&aggregate_withheld_amount,
|
||||
)
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
dest_confidential_transfer_account.pending_balance = new_dest_pending_balance;
|
||||
destination_confidential_transfer_account.pending_balance = new_destination_pending_balance;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ fn process_withdraw_withheld_tokens_from_mint(
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let mint_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
let authority_info_data_len = authority_info.data_len();
|
||||
|
||||
|
@ -132,22 +132,23 @@ fn process_withdraw_withheld_tokens_from_mint(
|
|||
account_info_iter.as_slice(),
|
||||
)?;
|
||||
|
||||
let mut dest_account_data = dest_account_info.data.borrow_mut();
|
||||
let mut dest_account = StateWithExtensionsMut::<Account>::unpack(&mut dest_account_data)?;
|
||||
if dest_account.base.mint != *mint_account_info.key {
|
||||
let mut destination_account_data = destination_account_info.data.borrow_mut();
|
||||
let mut destination_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(&mut destination_account_data)?;
|
||||
if destination_account.base.mint != *mint_account_info.key {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
if dest_account.base.is_frozen() {
|
||||
if destination_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
let withheld_amount = u64::from(extension.withheld_amount);
|
||||
extension.withheld_amount = 0.into();
|
||||
dest_account.base.amount = dest_account
|
||||
destination_account.base.amount = destination_account
|
||||
.base
|
||||
.amount
|
||||
.checked_add(withheld_amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
dest_account.pack_base();
|
||||
destination_account.pack_base();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -204,7 +205,7 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let mint_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
let authority_info_data_len = authority_info.data_len();
|
||||
let account_infos = account_info_iter.as_slice();
|
||||
|
@ -226,23 +227,24 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
&account_infos[..num_signers],
|
||||
)?;
|
||||
|
||||
let mut dest_account_data = dest_account_info.data.borrow_mut();
|
||||
let mut dest_account = StateWithExtensionsMut::<Account>::unpack(&mut dest_account_data)?;
|
||||
if dest_account.base.mint != *mint_account_info.key {
|
||||
let mut destination_account_data = destination_account_info.data.borrow_mut();
|
||||
let mut destination_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(&mut destination_account_data)?;
|
||||
if destination_account.base.mint != *mint_account_info.key {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
if dest_account.base.is_frozen() {
|
||||
if destination_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
for account_info in &account_infos[num_signers..] {
|
||||
// self-harvest, can't double-borrow the underlying data
|
||||
if account_info.key == dest_account_info.key {
|
||||
let token_account_extension = dest_account
|
||||
if account_info.key == destination_account_info.key {
|
||||
let token_account_extension = destination_account
|
||||
.get_extension_mut::<TransferFeeAmount>()
|
||||
.map_err(|_| TokenError::InvalidState)?;
|
||||
let account_withheld_amount = u64::from(token_account_extension.withheld_amount);
|
||||
token_account_extension.withheld_amount = 0.into();
|
||||
dest_account.base.amount = dest_account
|
||||
destination_account.base.amount = destination_account
|
||||
.base
|
||||
.amount
|
||||
.checked_add(account_withheld_amount)
|
||||
|
@ -250,7 +252,7 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
} else {
|
||||
match harvest_from_account(mint_account_info.key, account_info) {
|
||||
Ok(amount) => {
|
||||
dest_account.base.amount = dest_account
|
||||
destination_account.base.amount = destination_account
|
||||
.base
|
||||
.amount
|
||||
.checked_add(amount)
|
||||
|
@ -262,7 +264,7 @@ fn process_withdraw_withheld_tokens_from_accounts(
|
|||
}
|
||||
}
|
||||
}
|
||||
dest_account.pack_base();
|
||||
destination_account.pack_base();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ impl Processor {
|
|||
None
|
||||
};
|
||||
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
let authority_info_data_len = authority_info.data_len();
|
||||
|
||||
|
@ -321,7 +321,7 @@ impl Processor {
|
|||
}
|
||||
}
|
||||
|
||||
let self_transfer = cmp_pubkeys(source_account_info.key, dest_account_info.key);
|
||||
let self_transfer = cmp_pubkeys(source_account_info.key, destination_account_info.key);
|
||||
match source_account.base.delegate {
|
||||
COption::Some(ref delegate) if cmp_pubkeys(authority_info.key, delegate) => {
|
||||
Self::validate_owner(
|
||||
|
@ -358,7 +358,7 @@ impl Processor {
|
|||
// compute costs, ie:
|
||||
// if self_transfer || amount == 0
|
||||
check_program_account(source_account_info.owner)?;
|
||||
check_program_account(dest_account_info.owner)?;
|
||||
check_program_account(destination_account_info.owner)?;
|
||||
|
||||
// This check MUST occur just before the amounts are manipulated
|
||||
// to ensure self-transfers are fully validated
|
||||
|
@ -367,17 +367,18 @@ impl Processor {
|
|||
}
|
||||
|
||||
// self-transfer was dealt with earlier, so this *should* be safe
|
||||
let mut dest_account_data = dest_account_info.data.borrow_mut();
|
||||
let mut dest_account = StateWithExtensionsMut::<Account>::unpack(&mut dest_account_data)?;
|
||||
let mut destination_account_data = destination_account_info.data.borrow_mut();
|
||||
let mut destination_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(&mut destination_account_data)?;
|
||||
|
||||
if dest_account.base.is_frozen() {
|
||||
if destination_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
if !cmp_pubkeys(&source_account.base.mint, &dest_account.base.mint) {
|
||||
if !cmp_pubkeys(&source_account.base.mint, &destination_account.base.mint) {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
if memo_required(&dest_account) {
|
||||
if memo_required(&destination_account) {
|
||||
let is_memo_program = |program_id: &Pubkey| -> bool {
|
||||
program_id == &spl_memo::id() || program_id == &spl_memo::v1::id()
|
||||
};
|
||||
|
@ -396,13 +397,13 @@ impl Processor {
|
|||
.checked_sub(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
let credited_amount = amount.checked_sub(fee).ok_or(TokenError::Overflow)?;
|
||||
dest_account.base.amount = dest_account
|
||||
destination_account.base.amount = destination_account
|
||||
.base
|
||||
.amount
|
||||
.checked_add(credited_amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
if fee > 0 {
|
||||
if let Ok(extension) = dest_account.get_extension_mut::<TransferFeeAmount>() {
|
||||
if let Ok(extension) = destination_account.get_extension_mut::<TransferFeeAmount>() {
|
||||
let new_withheld_amount = u64::from(extension.withheld_amount)
|
||||
.checked_add(fee)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
@ -421,14 +422,14 @@ impl Processor {
|
|||
.checked_sub(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
let dest_starting_lamports = dest_account_info.lamports();
|
||||
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports
|
||||
let destination_starting_lamports = destination_account_info.lamports();
|
||||
**destination_account_info.lamports.borrow_mut() = destination_starting_lamports
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
}
|
||||
|
||||
source_account.pack_base();
|
||||
dest_account.pack_base();
|
||||
destination_account.pack_base();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -683,20 +684,21 @@ impl Processor {
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let mint_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let owner_info = next_account_info(account_info_iter)?;
|
||||
let owner_info_data_len = owner_info.data_len();
|
||||
|
||||
let mut dest_account_data = dest_account_info.data.borrow_mut();
|
||||
let mut dest_account = StateWithExtensionsMut::<Account>::unpack(&mut dest_account_data)?;
|
||||
if dest_account.base.is_frozen() {
|
||||
let mut destination_account_data = destination_account_info.data.borrow_mut();
|
||||
let mut destination_account =
|
||||
StateWithExtensionsMut::<Account>::unpack(&mut destination_account_data)?;
|
||||
if destination_account.base.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
|
||||
if dest_account.base.is_native() {
|
||||
if destination_account.base.is_native() {
|
||||
return Err(TokenError::NativeNotSupported.into());
|
||||
}
|
||||
if !cmp_pubkeys(mint_info.key, &dest_account.base.mint) {
|
||||
if !cmp_pubkeys(mint_info.key, &destination_account.base.mint) {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -723,9 +725,9 @@ impl Processor {
|
|||
// compute costs, ie:
|
||||
// if amount == 0
|
||||
check_program_account(mint_info.owner)?;
|
||||
check_program_account(dest_account_info.owner)?;
|
||||
check_program_account(destination_account_info.owner)?;
|
||||
|
||||
dest_account.base.amount = dest_account
|
||||
destination_account.base.amount = destination_account
|
||||
.base
|
||||
.amount
|
||||
.checked_add(amount)
|
||||
|
@ -738,7 +740,7 @@ impl Processor {
|
|||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
mint.pack_base();
|
||||
dest_account.pack_base();
|
||||
destination_account.pack_base();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -840,11 +842,11 @@ impl Processor {
|
|||
pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let source_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
let authority_info_data_len = authority_info.data_len();
|
||||
|
||||
if cmp_pubkeys(source_account_info.key, dest_account_info.key) {
|
||||
if cmp_pubkeys(source_account_info.key, destination_account_info.key) {
|
||||
return Err(ProgramError::InvalidAccountData);
|
||||
}
|
||||
|
||||
|
@ -895,8 +897,8 @@ impl Processor {
|
|||
return Err(ProgramError::UninitializedAccount);
|
||||
}
|
||||
|
||||
let dest_starting_lamports = dest_account_info.lamports();
|
||||
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports
|
||||
let destination_starting_lamports = destination_account_info.lamports();
|
||||
**destination_account_info.lamports.borrow_mut() = destination_starting_lamports
|
||||
.checked_add(source_account_info.lamports())
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
|
|
|
@ -235,19 +235,19 @@ impl Processor {
|
|||
None
|
||||
};
|
||||
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
|
||||
let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
|
||||
let mut dest_account = Account::unpack(&dest_account_info.data.borrow())?;
|
||||
let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
|
||||
|
||||
if source_account.is_frozen() || dest_account.is_frozen() {
|
||||
if source_account.is_frozen() || destination_account.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
if source_account.amount < amount {
|
||||
return Err(TokenError::InsufficientFunds.into());
|
||||
}
|
||||
if !Self::cmp_pubkeys(&source_account.mint, &dest_account.mint) {
|
||||
if !Self::cmp_pubkeys(&source_account.mint, &destination_account.mint) {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,8 @@ impl Processor {
|
|||
}
|
||||
}
|
||||
|
||||
let self_transfer = Self::cmp_pubkeys(source_account_info.key, dest_account_info.key);
|
||||
let self_transfer =
|
||||
Self::cmp_pubkeys(source_account_info.key, destination_account_info.key);
|
||||
|
||||
match source_account.delegate {
|
||||
COption::Some(ref delegate) if Self::cmp_pubkeys(authority_info.key, delegate) => {
|
||||
|
@ -295,7 +296,7 @@ impl Processor {
|
|||
|
||||
if self_transfer || amount == 0 {
|
||||
Self::check_account_owner(program_id, source_account_info)?;
|
||||
Self::check_account_owner(program_id, dest_account_info)?;
|
||||
Self::check_account_owner(program_id, destination_account_info)?;
|
||||
}
|
||||
|
||||
// This check MUST occur just before the amounts are manipulated
|
||||
|
@ -308,7 +309,7 @@ impl Processor {
|
|||
.amount
|
||||
.checked_sub(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
dest_account.amount = dest_account
|
||||
destination_account.amount = destination_account
|
||||
.amount
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
@ -319,14 +320,17 @@ impl Processor {
|
|||
.checked_sub(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
let dest_starting_lamports = dest_account_info.lamports();
|
||||
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports
|
||||
let destination_starting_lamports = destination_account_info.lamports();
|
||||
**destination_account_info.lamports.borrow_mut() = destination_starting_lamports
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
}
|
||||
|
||||
Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
|
||||
Account::pack(dest_account, &mut dest_account_info.data.borrow_mut())?;
|
||||
Account::pack(
|
||||
destination_account,
|
||||
&mut destination_account_info.data.borrow_mut(),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -517,18 +521,18 @@ impl Processor {
|
|||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let mint_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let owner_info = next_account_info(account_info_iter)?;
|
||||
|
||||
let mut dest_account = Account::unpack(&dest_account_info.data.borrow())?;
|
||||
if dest_account.is_frozen() {
|
||||
let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
|
||||
if destination_account.is_frozen() {
|
||||
return Err(TokenError::AccountFrozen.into());
|
||||
}
|
||||
|
||||
if dest_account.is_native() {
|
||||
if destination_account.is_native() {
|
||||
return Err(TokenError::NativeNotSupported.into());
|
||||
}
|
||||
if !Self::cmp_pubkeys(mint_info.key, &dest_account.mint) {
|
||||
if !Self::cmp_pubkeys(mint_info.key, &destination_account.mint) {
|
||||
return Err(TokenError::MintMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -551,10 +555,10 @@ impl Processor {
|
|||
|
||||
if amount == 0 {
|
||||
Self::check_account_owner(program_id, mint_info)?;
|
||||
Self::check_account_owner(program_id, dest_account_info)?;
|
||||
Self::check_account_owner(program_id, destination_account_info)?;
|
||||
}
|
||||
|
||||
dest_account.amount = dest_account
|
||||
destination_account.amount = destination_account
|
||||
.amount
|
||||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
@ -564,7 +568,10 @@ impl Processor {
|
|||
.checked_add(amount)
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
Account::pack(dest_account, &mut dest_account_info.data.borrow_mut())?;
|
||||
Account::pack(
|
||||
destination_account,
|
||||
&mut destination_account_info.data.borrow_mut(),
|
||||
)?;
|
||||
Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
|
||||
|
||||
Ok(())
|
||||
|
@ -657,10 +664,10 @@ impl Processor {
|
|||
pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let source_account_info = next_account_info(account_info_iter)?;
|
||||
let dest_account_info = next_account_info(account_info_iter)?;
|
||||
let destination_account_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
|
||||
if Self::cmp_pubkeys(source_account_info.key, dest_account_info.key) {
|
||||
if Self::cmp_pubkeys(source_account_info.key, destination_account_info.key) {
|
||||
return Err(ProgramError::InvalidAccountData);
|
||||
}
|
||||
|
||||
|
@ -679,8 +686,8 @@ impl Processor {
|
|||
account_info_iter.as_slice(),
|
||||
)?;
|
||||
|
||||
let dest_starting_lamports = dest_account_info.lamports();
|
||||
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports
|
||||
let destination_starting_lamports = destination_account_info.lamports();
|
||||
**destination_account_info.lamports.borrow_mut() = destination_starting_lamports
|
||||
.checked_add(source_account_info.lamports())
|
||||
.ok_or(TokenError::Overflow)?;
|
||||
|
||||
|
|
Loading…
Reference in New Issue