pub fn finalize_payment<P: MintProvider + RuntimeProvider>(
        provider: &mut P,
        amount_spent: U512,
        account: AccountHash,
        target: URef,
    ) -> Result<(), Error> {
        let caller = provider.get_caller();
        if caller != PublicKey::System.to_account_hash() {
            return Err(Error::SystemFunctionCalledByUserAccount);
        }

        let payment_purse = get_payment_purse(provider)?;
        let total = match provider.balance(payment_purse)? {
            Some(balance) => balance,
            None => return Err(Error::PaymentPurseBalanceNotFound),
        };

        if total < amount_spent {
            return Err(Error::InsufficientPaymentForAmountSpent);
        }

        // User's part
        let refund_amount = {
            let refund_amount_raw = total
                .checked_sub(amount_spent)
                .ok_or(Error::ArithmeticOverflow)?;
            // Currently refund percentage is zero and we expect no overflows.
            // However, we put this check should the constant change in the future.
            refund_amount_raw
                .checked_mul(REFUND_PERCENTAGE)
                .ok_or(Error::ArithmeticOverflow)?
        };

        // Validator reward
        let validator_reward = total
            .checked_sub(refund_amount)
            .ok_or(Error::ArithmeticOverflow)?;

        // Makes sure both parts: for user, and for validator sums to the total amount in the
        // payment's purse.
        debug_assert_eq!(validator_reward + refund_amount, total);

        let refund_purse = get_refund_purse(provider)?;

        if let Some(refund_purse) = refund_purse {
            if refund_purse.remove_access_rights() == payment_purse.remove_access_rights() {
                // Make sure we're not refunding into a payment purse to invalidate payment code
                // postconditions.
                return Err(Error::RefundPurseIsPaymentPurse);
            }
        }

        provider.remove_key(REFUND_PURSE_KEY)?; //unset refund purse after reading it

        // pay target validator
        provider
            .transfer_purse_to_purse(payment_purse, target, validator_reward)
            .map_err(|_| Error::FailedTransferToRewardsPurse)?;

        if refund_amount.is_zero() {
            return Ok(());
        }

        // give refund
        let refund_purse = match refund_purse {
            Some(uref) => uref,
            None => return refund_to_account::<P>(provider, payment_purse, account, refund_amount),
        };

        // in case of failure to transfer to refund purse we fall back on the account's main purse
        if provider
            .transfer_purse_to_purse(payment_purse, refund_purse, refund_amount)
            .is_err()
        {
            return refund_to_account::<P>(provider, payment_purse, account, refund_amount);
        }

        Ok(())
    }
/// Transfers funds from the payment purse to the validator rewards purse, as well as to the
/// refund purse, depending on how much was spent on the computation. This function maintains
/// the invariant that the balance of the payment purse is zero at the beginning and end of each
/// deploy and that the refund purse is unset at the beginning and end of each deploy.
Transfers funds from the payment purse to the validator rewards purse, as well as to the
refund purse, depending on how much was spent on the computation. This function maintains
the invariant that the balance of the payment purse is zero at the beginning and end of each
deploy and that the refund purse is unset at the beginning and end of each deploy.
Transfers funds from the payment purse to the validator rewards purse as well as to the refund purse depending on how much was spent on the computation . This function maintains the invariant that the balance of the payment purse is zero at the beginning and end of each deploy and that the refund purse is unset at the beginning and end of each deploy .
pub fn finalize_payment<P: MintProvider + RuntimeProvider>(
        provider: &mut P,
        amount_spent: U512,
        account: AccountHash,
        target: URef,
    ) -> Result<(), Error> {
        let caller = provider.get_caller();
        if caller != PublicKey::System.to_account_hash() {
            return Err(Error::SystemFunctionCalledByUserAccount);
        }
        let payment_purse = get_payment_purse(provider)?;
        let total = match provider.balance(payment_purse)? {
            Some(balance) => balance,
            None => return Err(Error::PaymentPurseBalanceNotFound),
        };
        if total < amount_spent {
            return Err(Error::InsufficientPaymentForAmountSpent);
        }
        // User's part
        let refund_amount = {
            let refund_amount_raw = total
                .checked_sub(amount_spent)
                .ok_or(Error::ArithmeticOverflow)?;
            // Currently refund percentage is zero and we expect no overflows.
            // However, we put this check should the constant change in the future.
            refund_amount_raw
                .checked_mul(REFUND_PERCENTAGE)
                .ok_or(Error::ArithmeticOverflow)?
        };
        // Validator reward
        let validator_reward = total
            .checked_sub(refund_amount)
            .ok_or(Error::ArithmeticOverflow)?;
        // Makes sure both parts: for user, and for validator sums to the total amount in the
        // payment's purse.
        debug_assert_eq!(validator_reward + refund_amount, total);
        let refund_purse = get_refund_purse(provider)?;
        if let Some(refund_purse) = refund_purse {
            if refund_purse.remove_access_rights() == payment_purse.remove_access_rights() {
                // Make sure we're not refunding into a payment purse to invalidate payment code
                // postconditions.
                return Err(Error::RefundPurseIsPaymentPurse);
            }
        }
        provider.remove_key(REFUND_PURSE_KEY)?; //unset refund purse after reading it
        // pay target validator
        provider
            .transfer_purse_to_purse(payment_purse, target, validator_reward)
            .map_err(|_| Error::FailedTransferToRewardsPurse)?;
        if refund_amount.is_zero() {
            return Ok(());
        }
        // give refund
        let refund_purse = match refund_purse {
            Some(uref) => uref,
            None => return refund_to_account::<P>(provider, payment_purse, account, refund_amount),
        };
        // in case of failure to transfer to refund purse we fall back on the account's main purse
        if provider
            .transfer_purse_to_purse(payment_purse, refund_purse, refund_amount)
            .is_err()
        {
            return refund_to_account::<P>(provider, payment_purse, account, refund_amount);
        }
        Ok(())
    }
pub fn finalize_payment < P : MintProvider + RuntimeProvider > ( provider : & mut P , amount_spent : U512 , account : AccountHash , target : URef , ) -> Result < ( ) , Error > { let caller = provider . get_caller ( ) ; if caller != PublicKey :: System . to_account_hash ( ) { return Err ( Error :: SystemFunctionCalledByUserAccount ) ; } let payment_purse = get_payment_purse ( provider ) ? ; let total = match provider . balance ( payment_purse ) ? { Some ( balance ) => balance , None => return Err ( Error :: PaymentPurseBalanceNotFound ) , } ; if total < amount_spent { return Err ( Error :: InsufficientPaymentForAmountSpent ) ; } // User's part let refund_amount = { let refund_amount_raw = total . checked_sub ( amount_spent ) . ok_or ( Error :: ArithmeticOverflow ) ? ; // Currently refund percentage is zero and we expect no overflows. // However, we put this check should the constant change in the future. refund_amount_raw . checked_mul ( REFUND_PERCENTAGE ) . ok_or ( Error :: ArithmeticOverflow ) ? } ; // Validator reward let validator_reward = total . checked_sub ( refund_amount ) . ok_or ( Error :: ArithmeticOverflow ) ? ; // Makes sure both parts: for user, and for validator sums to the total amount in the // payment's purse. debug_assert_eq ! ( validator_reward refund_amount total ) ; let refund_purse = get_refund_purse ( provider ) ? ; if let Some ( refund_purse ) = refund_purse { if refund_purse . remove_access_rights ( ) == payment_purse . remove_access_rights ( ) { // Make sure we're not refunding into a payment purse to invalidate payment code // postconditions. return Err ( Error :: RefundPurseIsPaymentPurse ) ; } } provider . remove_key ( REFUND_PURSE_KEY ) ? ; //unset refund purse after reading it // pay target validator provider . transfer_purse_to_purse ( payment_purse , target , validator_reward ) . map_err ( | _ | Error :: FailedTransferToRewardsPurse ) ? ; if refund_amount . is_zero ( ) { return Ok ( ( ) ) ; } // give refund let refund_purse = match refund_purse { Some ( uref ) => uref , None => return refund_to_account :: < P > ( provider , payment_purse , account , refund_amount ) , } ; // in case of failure to transfer to refund purse we fall back on the account's main purse if provider . transfer_purse_to_purse ( payment_purse , refund_purse , refund_amount ) . is_err ( ) { return refund_to_account :: < P > ( provider , payment_purse , account , refund_amount ) ; } Ok ( ( ) ) }
Transfers funds from the payment purse to the validator rewards purse, as well as to the
refund purse, depending on how much was spent on the computation.
Transfers funds from the payment purse to the validator rewards purse as well as to the refund purse depending on how much was spent on the computation .
provider
&mut P
amount_spent
U512
account
AccountHash
target
URef
provider
&mut P
amount_spent
U512
account
AccountHash
target
URef