Skip to content

Commit

Permalink
Fee quoter review and nits (#473)
Browse files Browse the repository at this point in the history
* Fee quoter review and nits

* fix double-counted slots in EVM message

* address comments

* more nits
  • Loading branch information
matYang authored Jan 22, 2025
1 parent 5d987b7 commit 23551e1
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ use super::pools::CCIP_LOCK_OR_BURN_V1_RET_BYTES;
use super::price_math::get_validated_token_price;
use super::price_math::{Exponential, Usd18Decimals};

/// Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (data, receiver and tokenAmounts).
/// SVM2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (data, sender and tokenAmounts).
/// Each variable array takes 1 more slot to store its length.
/// When abi encoded, excluding array contents,
/// Any2EVMMessage takes up a fixed number of 13 slots, 32 bytes each.
/// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 14.
/// The fixed bytes does not cover struct data (this is represented by ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN)
pub const ANY_2_EVM_MESSAGE_FIXED_BYTES: U256 = U256::new(32 * 14);
/// SVM2AnyMessage takes up a fixed number of 13 slots, 32 bytes each.
/// We assume sender always takes 1 slot.
/// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 15.
/// The fixed bytes does not cover struct data (this is represented by SVM_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN)
pub const SVM_2_EVM_MESSAGE_FIXED_BYTES: U256 = U256::new(32 * 15);

/// Each token transfer adds 1 RampTokenAmount
/// RampTokenAmount has 5 fields, 2 of which are bytes type, 1 Address, 1 uint256 and 1 uint32.
/// Each bytes type takes 1 slot for length, 1 slot for data and 1 slot for the offset.
/// address
/// uint256 amount takes 1 slot.
/// uint32 destGasAmount takes 1 slot.
pub const ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN: U256 = U256::new(32 * ((2 * 3) + 3));
pub const SVM_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN: U256 = U256::new(32 * ((2 * 3) + 3));

pub fn fee_for_msg(
_dest_chain_selector: u64,
message: &SVM2AnyMessage,
dest_chain: &DestChain,
fee_token_config: &BillingTokenConfig,
Expand Down Expand Up @@ -76,7 +76,7 @@ pub fn fee_for_msg(

let execution_gas = gas_limit
+ U256::new(dest_chain.config.dest_gas_overhead as u128)
+ U256::new(message.data.len() as u128)
+ (U256::new(message.data.len() as u128) + network_fee.transfer_bytes_overhead)
* U256::new(dest_chain.config.dest_gas_per_payload_byte as u128)
+ network_fee.transfer_gas;

Expand Down Expand Up @@ -113,10 +113,10 @@ fn data_availability_cost(
) -> Usd18Decimals {
// Sums up byte lengths of fixed message fields and dynamic message fields.
// Fixed message fields do account for the offset and length slot of the dynamic fields.
let data_availability_length_bytes = ANY_2_EVM_MESSAGE_FIXED_BYTES
let data_availability_length_bytes = SVM_2_EVM_MESSAGE_FIXED_BYTES
+ U256::new(message.data.len() as u128)
+ (U256::new(message.token_amounts.len() as u128)
* ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN)
* SVM_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN)
+ token_transfer_bytes_overhead;

// dest_data_availability_overhead_gas is a separate config value for flexibility to be updated
Expand Down Expand Up @@ -171,7 +171,7 @@ fn network_fee(
token_network_fees(&token_configs[i], token_amount, config_for_dest_chain)?
} else {
// If the token has no specific overrides configured, we use the global defaults.
global_network_fees(dest_chain)
default_token_network_fees(dest_chain)
};

fee += token_network_fee;
Expand Down Expand Up @@ -213,7 +213,7 @@ fn token_network_fees(
})
}

fn global_network_fees(dest_chain: &DestChain) -> NetworkFee {
fn default_token_network_fees(dest_chain: &DestChain) -> NetworkFee {
let (premium, global_gas, global_overhead) = (
Usd18Decimals::from_usd_cents(dest_chain.config.default_token_fee_usdcents.into()),
U256::new(dest_chain.config.default_token_dest_gas_overhead.into()),
Expand Down Expand Up @@ -250,9 +250,9 @@ impl From<&TimestampedPackedU224> for UnpackedDoubleU224 {
fn from(packed: &TimestampedPackedU224) -> Self {
let mut u128_buffer = [0u8; 16];
u128_buffer[2..16].clone_from_slice(&packed.value[14..]);
let high = u128::from_be_bytes(u128_buffer);
u128_buffer[2..16].clone_from_slice(&packed.value[..14]);
let low = u128::from_be_bytes(u128_buffer);
u128_buffer[2..16].clone_from_slice(&packed.value[..14]);
let high = u128::from_be_bytes(u128_buffer);
Self { high, low }
}
}
Expand Down Expand Up @@ -389,7 +389,6 @@ pub mod tests {
set_syscall_stubs(Box::new(TestStubs));
assert_eq!(
fee_for_msg(
0,
&sample_message(),
&sample_dest_chain(),
&sample_billing_config(),
Expand All @@ -411,7 +410,6 @@ pub mod tests {
chain.config.network_fee_usdcents *= 12;
assert_eq!(
fee_for_msg(
0,
&sample_message(),
&chain,
&sample_billing_config(),
Expand All @@ -437,7 +435,6 @@ pub mod tests {
set_syscall_stubs(Box::new(TestStubs));
assert_eq!(
fee_for_msg(
0,
&message,
&sample_dest_chain(),
&sample_billing_config(),
Expand Down Expand Up @@ -473,7 +470,6 @@ pub mod tests {
set_syscall_stubs(Box::new(TestStubs));
assert_eq!(
fee_for_msg(
0,
&message,
&chain,
&sample_billing_config(),
Expand All @@ -483,7 +479,7 @@ pub mod tests {
.unwrap(),
SVMTokenAmount {
token: native_mint::ID,
amount: 52885511932309044,
amount: 52911699750913573,
}
);
}
Expand All @@ -508,7 +504,6 @@ pub mod tests {
set_syscall_stubs(Box::new(TestStubs));
assert_eq!(
fee_for_msg(
0,
&message,
&chain,
&sample_billing_config(),
Expand All @@ -519,7 +514,7 @@ pub mod tests {
SVMTokenAmount {
token: native_mint::ID,
// Increases proportionally to the min_fee
amount: 398110981980079407
amount: 398634738352169990
}
);
}
Expand All @@ -546,7 +541,6 @@ pub mod tests {
set_syscall_stubs(Box::new(TestStubs));
assert_eq!(
fee_for_msg(
0,
&message,
&chain,
&sample_billing_config(),
Expand All @@ -556,7 +550,7 @@ pub mod tests {
.unwrap(),
SVMTokenAmount {
token: native_mint::ID,
amount: 36130696584140229
amount: 36654452956230811
}
);

Expand All @@ -565,7 +559,6 @@ pub mod tests {

assert_eq!(
fee_for_msg(
0,
&message,
&chain,
&sample_billing_config(),
Expand All @@ -576,7 +569,7 @@ pub mod tests {
SVMTokenAmount {
token: native_mint::ID,
// Slight increase in price
amount: 37480696584140229
amount: 38004452956230811
}
);
}
Expand All @@ -601,7 +594,6 @@ pub mod tests {
set_syscall_stubs(Box::new(TestStubs));
assert_eq!(
fee_for_msg(
0,
&message,
&chain,
&sample_billing_config(),
Expand All @@ -611,7 +603,7 @@ pub mod tests {
.unwrap(),
SVMTokenAmount {
token: native_mint::ID,
amount: 35234859440885153
amount: 35758615812975735
}
);

Expand All @@ -620,7 +612,6 @@ pub mod tests {

assert_eq!(
fee_for_msg(
0,
&message,
&chain,
&sample_billing_config(),
Expand All @@ -630,7 +621,7 @@ pub mod tests {
.unwrap(),
SVMTokenAmount {
token: native_mint::ID,
amount: 35234859440885153
amount: 35758615812975735
}
);
}
Expand All @@ -657,7 +648,6 @@ pub mod tests {
chain.config.max_number_of_tokens_per_msg = 5;
assert_eq!(
fee_for_msg(
0,
&message,
&chain,
&sample_billing_config(),
Expand All @@ -668,7 +658,7 @@ pub mod tests {
SVMTokenAmount {
token: native_mint::ID,
// Increases proportionally to the number of tokens
amount: 153233232867589323
amount: 155328258355951652
}
);
}
Expand Down Expand Up @@ -699,7 +689,6 @@ pub mod tests {
billing_config.usd_per_token.timestamp = 0;
assert_eq!(
fee_for_msg(
0,
&sample_message(),
&sample_dest_chain(),
&billing_config,
Expand All @@ -717,7 +706,6 @@ pub mod tests {
billing_config.usd_per_token.value = [0u8; 28];
assert_eq!(
fee_for_msg(
0,
&sample_message(),
&sample_dest_chain(),
&billing_config,
Expand All @@ -739,7 +727,6 @@ pub mod tests {
-2 * chain.config.gas_price_staleness_threshold as i64;
assert_eq!(
fee_for_msg(
0,
&sample_message(),
&chain,
&sample_billing_config(),
Expand All @@ -764,4 +751,23 @@ pub mod tests {

assert_eq!(price, roundtrip);
}

#[test]
fn test_packed_price_from_bytes() {
// 2gwei DA encoded in higher order 112 bits, 1gwei Exec gas price encoded in lower order 112 bits
let bytes = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xc1, 0x6d, 0x67, 0x4e, 0xc8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00,
];

let ts_packed = TimestampedPackedU224 {
value: bytes,
timestamp: 0,
};

let price: PackedPrice = (&ts_packed).into();

assert_eq!(price.execution_gas_price, Usd18Decimals(1u32.e(18)));
assert_eq!(price.data_availability_gas_price, Usd18Decimals(2u32.e(18)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ pub mod ramps {
impl UnpackedDoubleU224 {
pub fn pack(self, timestamp: i64) -> TimestampedPackedU224 {
let mut value = [0u8; 28];
value[14..].clone_from_slice(&self.high.to_be_bytes()[2..16]);
value[..14].clone_from_slice(&self.low.to_be_bytes()[2..16]);
value[14..].clone_from_slice(&self.low.to_be_bytes()[2..16]);
value[..14].clone_from_slice(&self.high.to_be_bytes()[2..16]);
TimestampedPackedU224 { value, timestamp }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ pub fn get_fee<'info>(
.collect::<Result<Vec<_>>>()?;

Ok(fee_for_msg(
dest_chain_selector,
message,
&ctx.accounts.dest_chain_state,
&ctx.accounts.billing_token_config.config,
Expand Down Expand Up @@ -109,7 +108,6 @@ pub fn ccip_send<'info>(
.collect::<Result<Vec<_>>>()?;

let fee = fee_for_msg(
dest_chain_selector,
&message,
dest_chain,
&ctx.accounts.fee_token_config.config,
Expand Down

0 comments on commit 23551e1

Please sign in to comment.