Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

[zk-token-sdk] Fix transfer with fee edge case error #34314

Merged
merged 3 commits into from
Dec 6, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions zk-token-sdk/src/instruction/transfer/with_fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ use {
const MAX_FEE_BASIS_POINTS: u64 = 10_000;
#[cfg(not(target_os = "solana"))]
const ONE_IN_BASIS_POINTS: u128 = MAX_FEE_BASIS_POINTS as u128;
#[cfg(not(target_os = "solana"))]
const MAX_DELTA_RANGE: u64 = MAX_FEE_BASIS_POINTS - 1;

#[cfg(not(target_os = "solana"))]
const TRANSFER_SOURCE_AMOUNT_BITS: usize = 64;
Expand All @@ -51,7 +53,7 @@ const TRANSFER_AMOUNT_LO_NEGATED_BITS: usize = 16;
#[cfg(not(target_os = "solana"))]
const TRANSFER_AMOUNT_HI_BITS: usize = 32;
#[cfg(not(target_os = "solana"))]
const TRANSFER_DELTA_BITS: usize = 48;
const TRANSFER_DELTA_BITS: usize = 16;
#[cfg(not(target_os = "solana"))]
const FEE_AMOUNT_LO_BITS: usize = 16;
#[cfg(not(target_os = "solana"))]
Expand All @@ -62,6 +64,7 @@ lazy_static::lazy_static! {
pub static ref COMMITMENT_MAX: PedersenCommitment = Pedersen::encode((1_u64 <<
TRANSFER_AMOUNT_LO_NEGATED_BITS) - 1);
pub static ref COMMITMENT_MAX_FEE_BASIS_POINTS: PedersenCommitment = Pedersen::encode(MAX_FEE_BASIS_POINTS);
pub static ref COMMITMENT_MAX_DELTA_RANGE: PedersenCommitment = Pedersen::encode(MAX_DELTA_RANGE);
}

/// The instruction data that is needed for the `ProofInstruction::TransferWithFee` instruction.
Expand Down Expand Up @@ -557,24 +560,41 @@ impl TransferWithFeeProof {

// generate the range proof
let opening_claimed_negated = &PedersenOpening::default() - &opening_claimed;

let combined_amount = combine_lo_hi_u64(
transfer_amount_lo,
transfer_amount_hi,
TRANSFER_AMOUNT_LO_BITS,
);
let amount_sub_fee = combined_amount
.checked_sub(combined_fee_amount)
.ok_or(ProofGenerationError::FeeCalculation)?;
let amount_sub_fee_opening = combined_opening - combined_fee_opening;

let delta_negated = MAX_DELTA_RANGE
.checked_sub(delta_fee)
.ok_or(ProofGenerationError::FeeCalculation)?;

let range_proof = RangeProof::new(
vec![
source_new_balance,
transfer_amount_lo,
transfer_amount_hi,
delta_fee,
MAX_FEE_BASIS_POINTS - delta_fee,
delta_negated,
fee_amount_lo,
fee_amount_hi,
amount_sub_fee,
],
vec![
TRANSFER_SOURCE_AMOUNT_BITS, // 64
TRANSFER_AMOUNT_LO_BITS, // 16
TRANSFER_AMOUNT_HI_BITS, // 32
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 16
TRANSFER_DELTA_BITS, // 16
FEE_AMOUNT_LO_BITS, // 16
FEE_AMOUNT_HI_BITS, // 32
TRANSFER_SOURCE_AMOUNT_BITS, // 64
],
vec![
&opening_source,
Expand All @@ -584,6 +604,7 @@ impl TransferWithFeeProof {
&opening_claimed_negated,
opening_fee_lo,
opening_fee_hi,
&amount_sub_fee_opening,
],
transcript,
)?;
Expand Down Expand Up @@ -708,7 +729,8 @@ impl TransferWithFeeProof {

// verify range proof
let new_source_commitment = self.new_source_commitment.try_into()?;
let claimed_commitment_negated = &(*COMMITMENT_MAX_FEE_BASIS_POINTS) - &claimed_commitment;
let claimed_commitment_negated = &(*COMMITMENT_MAX_DELTA_RANGE) - &claimed_commitment;
let amount_sub_fee_commitment = combined_commitment - combined_fee_commitment;

range_proof.verify(
vec![
Expand All @@ -719,15 +741,17 @@ impl TransferWithFeeProof {
&claimed_commitment_negated,
fee_ciphertext_lo.get_commitment(),
fee_ciphertext_hi.get_commitment(),
&amount_sub_fee_commitment,
],
vec![
TRANSFER_SOURCE_AMOUNT_BITS, // 64
TRANSFER_AMOUNT_LO_BITS, // 16
TRANSFER_AMOUNT_HI_BITS, // 32
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 16
TRANSFER_DELTA_BITS, // 16
FEE_AMOUNT_LO_BITS, // 16
FEE_AMOUNT_HI_BITS, // 32
TRANSFER_SOURCE_AMOUNT_BITS, // 64
],
transcript,
)?;
Expand Down