casper_storage/system/
handle_payment.rs

1mod handle_payment_native;
2mod internal;
3/// Provides mint logic for handle payment processing.
4pub mod mint_provider;
5/// Provides runtime logic for handle payment processing.
6pub mod runtime_provider;
7/// Provides storage logic for handle payment processing.
8pub mod storage_provider;
9
10use casper_types::{
11    system::handle_payment::{Error, REFUND_PURSE_KEY},
12    AccessRights, PublicKey, URef, U512,
13};
14use num_rational::Ratio;
15use tracing::error;
16
17use crate::system::handle_payment::{
18    mint_provider::MintProvider, runtime_provider::RuntimeProvider,
19    storage_provider::StorageProvider,
20};
21
22/// Handle payment functionality implementation.
23pub trait HandlePayment: MintProvider + RuntimeProvider + StorageProvider + Sized {
24    /// Get payment purse.
25    fn get_payment_purse(&mut self) -> Result<URef, Error> {
26        let purse = internal::get_payment_purse(self)?;
27        // Limit the access rights so only balance query and deposit are allowed.
28        Ok(URef::new(purse.addr(), AccessRights::READ_ADD))
29    }
30
31    /// Set refund purse.
32    fn set_refund_purse(&mut self, purse: URef) -> Result<(), Error> {
33        // make sure the passed uref is actually a purse...
34        // if it has a balance it is a purse and if not it isn't
35        let _balance = self.available_balance(purse)?;
36        internal::set_refund(self, purse)
37    }
38
39    /// Get refund purse.
40    fn get_refund_purse(&mut self) -> Result<Option<URef>, Error> {
41        // We purposely choose to remove the access rights so that we do not
42        // accidentally give rights for a purse to some contract that is not
43        // supposed to have it.
44        let maybe_purse = internal::get_refund_purse(self)?;
45        Ok(maybe_purse.map(|p| p.remove_access_rights()))
46    }
47
48    /// Clear refund purse.
49    fn clear_refund_purse(&mut self) -> Result<(), Error> {
50        if self.get_caller() != PublicKey::System.to_account_hash() {
51            error!("invalid caller to clear refund purse");
52            return Err(Error::InvalidCaller);
53        }
54
55        self.remove_key(REFUND_PURSE_KEY)
56    }
57
58    /// Calculate overpayment and fees (if any) for payment finalization.
59    #[allow(clippy::too_many_arguments)]
60    fn calculate_overpayment_and_fee(
61        &mut self,
62        limit: U512,
63        gas_price: u8,
64        cost: U512,
65        consumed: U512,
66        source_purse: URef,
67        refund_ratio: Ratio<U512>,
68    ) -> Result<(U512, U512), Error> {
69        if self.get_caller() != PublicKey::System.to_account_hash() {
70            error!("invalid caller to calculate overpayment and fee");
71            return Err(Error::InvalidCaller);
72        }
73
74        let available_balance = match self.available_balance(source_purse)? {
75            Some(balance) => balance,
76            None => return Err(Error::PaymentPurseBalanceNotFound),
77        };
78        internal::calculate_overpayment_and_fee(
79            limit,
80            gas_price,
81            cost,
82            consumed,
83            available_balance,
84            refund_ratio,
85        )
86    }
87
88    /// Distribute fees from an accumulation purse.
89    fn distribute_accumulated_fees(
90        &mut self,
91        source_uref: URef,
92        amount: Option<U512>,
93    ) -> Result<(), Error> {
94        if self.get_caller() != PublicKey::System.to_account_hash() {
95            error!("invalid caller to distribute accumulated fee");
96            return Err(Error::InvalidCaller);
97        }
98
99        internal::distribute_accumulated_fees(self, source_uref, amount)
100    }
101
102    /// Burns the imputed amount from the imputed purse.
103    fn payment_burn(&mut self, source_uref: URef, amount: Option<U512>) -> Result<(), Error> {
104        if self.get_caller() != PublicKey::System.to_account_hash() {
105            error!("invalid caller to payment burn");
106            return Err(Error::InvalidCaller);
107        }
108
109        internal::payment_burn(self, source_uref, amount)
110    }
111}