1use async_trait::async_trait;
2use aztec_core::abi::{FunctionSelector, FunctionType};
3use aztec_core::tx::{ExecutionPayload, FunctionCall};
4use aztec_core::types::AztecAddress;
5use aztec_core::Error;
6
7use crate::fee_payment_method::FeePaymentMethod;
8
9pub struct SponsoredFeePaymentMethod {
15 payment_contract: AztecAddress,
17}
18
19impl SponsoredFeePaymentMethod {
20 pub fn new(payment_contract: AztecAddress) -> Self {
24 Self { payment_contract }
25 }
26}
27
28#[async_trait]
29impl FeePaymentMethod for SponsoredFeePaymentMethod {
30 async fn get_asset(&self) -> Result<AztecAddress, Error> {
31 Err(Error::InvalidData(
32 "SponsoredFeePaymentMethod does not have an associated asset".into(),
33 ))
34 }
35
36 async fn get_fee_payer(&self) -> Result<AztecAddress, Error> {
37 Ok(self.payment_contract)
38 }
39
40 async fn get_fee_execution_payload(&self) -> Result<ExecutionPayload, Error> {
41 let call = FunctionCall {
42 to: self.payment_contract,
43 selector: FunctionSelector::from_signature("sponsor_unconditionally()"),
44 args: vec![],
45 function_type: FunctionType::Private,
46 is_static: false,
47 hide_msg_sender: false,
48 };
49
50 Ok(ExecutionPayload {
51 calls: vec![call],
52 auth_witnesses: vec![],
53 capsules: vec![],
54 extra_hashed_args: vec![],
55 fee_payer: Some(self.payment_contract),
56 })
57 }
58}
59
60#[cfg(test)]
61#[allow(clippy::expect_used)]
62mod tests {
63 use super::*;
64 use aztec_core::types::Fr;
65
66 #[tokio::test]
67 async fn payload_has_single_call_to_sponsor_unconditionally() {
68 let contract = AztecAddress(Fr::from(42u64));
69 let method = SponsoredFeePaymentMethod::new(contract);
70 let payload = method.get_fee_execution_payload().await.expect("payload");
71
72 assert_eq!(payload.calls.len(), 1);
73 let call = &payload.calls[0];
74 assert_eq!(call.to, contract);
75 assert_eq!(
76 call.selector,
77 FunctionSelector::from_signature("sponsor_unconditionally()")
78 );
79 assert!(call.args.is_empty());
80 assert_eq!(call.function_type, FunctionType::Private);
81 assert!(!call.is_static);
82 }
83
84 #[tokio::test]
85 async fn fee_payer_is_payment_contract() {
86 let contract = AztecAddress(Fr::from(42u64));
87 let method = SponsoredFeePaymentMethod::new(contract);
88
89 assert_eq!(method.get_fee_payer().await.expect("fee payer"), contract);
90
91 let payload = method.get_fee_execution_payload().await.expect("payload");
92 assert_eq!(payload.fee_payer, Some(contract));
93 }
94
95 #[tokio::test]
96 async fn get_asset_returns_error() {
97 let contract = AztecAddress(Fr::from(42u64));
98 let method = SponsoredFeePaymentMethod::new(contract);
99 assert!(method.get_asset().await.is_err());
100 }
101}