aztec_fee/
native.rs

1use async_trait::async_trait;
2use aztec_core::constants::protocol_contract_address;
3use aztec_core::tx::ExecutionPayload;
4use aztec_core::types::AztecAddress;
5use aztec_core::Error;
6
7use crate::fee_payment_method::FeePaymentMethod;
8
9/// Pays transaction fees using the sender's existing Fee Juice balance.
10///
11/// This is the default fee payment strategy. It doesn't add any extra
12/// function calls to the transaction — it simply declares who is paying.
13/// The sender must already have sufficient Fee Juice balance.
14pub struct NativeFeePaymentMethod {
15    /// Address of the account paying fees from its existing balance.
16    sender: AztecAddress,
17}
18
19impl NativeFeePaymentMethod {
20    /// Create a new native fee payment method.
21    ///
22    /// `sender` is the account that will pay fees from its existing Fee Juice balance.
23    pub fn new(sender: AztecAddress) -> Self {
24        Self { sender }
25    }
26}
27
28#[async_trait]
29impl FeePaymentMethod for NativeFeePaymentMethod {
30    async fn get_asset(&self) -> Result<AztecAddress, Error> {
31        Ok(protocol_contract_address::fee_juice())
32    }
33
34    async fn get_fee_payer(&self) -> Result<AztecAddress, Error> {
35        Ok(self.sender)
36    }
37
38    async fn get_fee_execution_payload(&self) -> Result<ExecutionPayload, Error> {
39        Ok(ExecutionPayload {
40            calls: vec![],
41            auth_witnesses: vec![],
42            capsules: vec![],
43            extra_hashed_args: vec![],
44            fee_payer: Some(self.sender),
45        })
46    }
47}
48
49#[cfg(test)]
50#[allow(clippy::expect_used)]
51mod tests {
52    use super::*;
53    use aztec_core::types::Fr;
54
55    #[tokio::test]
56    async fn payload_is_empty_except_fee_payer() {
57        let sender = AztecAddress(Fr::from(10u64));
58        let method = NativeFeePaymentMethod::new(sender);
59        let payload = method.get_fee_execution_payload().await.expect("payload");
60
61        assert!(payload.calls.is_empty());
62        assert!(payload.auth_witnesses.is_empty());
63        assert!(payload.capsules.is_empty());
64        assert!(payload.extra_hashed_args.is_empty());
65        assert_eq!(payload.fee_payer, Some(sender));
66    }
67
68    #[tokio::test]
69    async fn asset_is_fee_juice() {
70        let sender = AztecAddress(Fr::from(10u64));
71        let method = NativeFeePaymentMethod::new(sender);
72        assert_eq!(
73            method.get_asset().await.expect("asset"),
74            protocol_contract_address::fee_juice()
75        );
76    }
77
78    #[tokio::test]
79    async fn fee_payer_is_sender() {
80        let sender = AztecAddress(Fr::from(10u64));
81        let method = NativeFeePaymentMethod::new(sender);
82        assert_eq!(method.get_fee_payer().await.expect("fee payer"), sender);
83    }
84}