为什么Transfer fee更改后要等2个Epoch?
为了防止更改Transfer fee费率被随意更改,Solana规定每次更改Transfer fee后,必须等待2个Epoch才能生效。
代码见:https://github.com/solana-program/token-2022/blob/6ae924718a5a4b0a35a25795f6d581d8310559a4/program/src/extension/transfer_fee/processor.rs#L103
fn process_set_transfer_fee(
program_id: &Pubkey,
accounts: &[AccountInfo],
transfer_fee_basis_points: u16,
maximum_fee: u64,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let mint_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 mut mint_data = mint_account_info.data.borrow_mut();
let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
let extension = mint.get_extension_mut::<TransferFeeConfig>()?;
let transfer_fee_config_authority =
Option::<Pubkey>::from(extension.transfer_fee_config_authority)
.ok_or(TokenError::NoAuthorityExists)?;
Processor::validate_owner(
program_id,
&transfer_fee_config_authority,
authority_info,
authority_info_data_len,
account_info_iter.as_slice(),
)?;
if transfer_fee_basis_points > MAX_FEE_BASIS_POINTS {
return Err(TokenError::TransferFeeExceedsMaximum.into());
}
// When setting the transfer fee, we have two situations:
// * newer transfer fee epoch <= current epoch: newer transfer fee is the active
// one, so overwrite older transfer fee with newer, then overwrite newer
// transfer fee
// * newer transfer fee epoch >= next epoch: it was never used, so just
// overwrite next transfer fee
let epoch = Clock::get()?.epoch;
if u64::from(extension.newer_transfer_fee.epoch) <= epoch {
extension.older_transfer_fee = extension.newer_transfer_fee;
}
// set two epochs ahead to avoid rug pulls at the end of an epoch
let newer_fee_start_epoch = epoch.saturating_add(2); <--- 2 epochs ahead
let transfer_fee = TransferFee {
epoch: newer_fee_start_epoch.into(),
transfer_fee_basis_points: transfer_fee_basis_points.into(),
maximum_fee: maximum_fee.into(),
};
extension.newer_transfer_fee = transfer_fee;
Ok(())
}