Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transfer Ethereum fees to Treasury & Author, rather than burning them #1388

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

branan
Copy link
Contributor

@branan branan commented Jun 7, 2023

This implements a custom OnChargeEVMTransaction for our chain.

Unfortunately the EVM handling of base_fee+priority is slightly different from how pallet_transaction_payment handles fees+tips, so we have to reimplement quite a bit more logic than I would have ideally liked. Fortunately, it's all pretty straightforward fee handling bits.

Changes and Descriptions

  • EVM Fees are now distributed identically to Substrate fees

Checklist:

  • I have added Rust doc comments to structs, enums, traits and functions
  • I have made corresponding changes to the documentation
  • I have performed a self-review of my code

Comment on lines +53 to +66
fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, Error<R>> {
if fee.is_zero() {
return Ok(None);
}
let account_id = R::AddressMapping::into_account_id(*who);
Balances::<R>::withdraw(
&account_id,
fee.unique_saturated_into(),
WithdrawReasons::FEE,
ExistenceRequirement::AllowDeath,
)
.map(Some)
.map_err(|_| Error::<R>::BalanceLow)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wondered if we could implement this trait with calls to our pallet-fees. Does it make sense? i.e. in this case this would be a call to Fees::withdraw_fee()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're not going to use fee_to_author and fee_to_treasury (See my response below), I'm not sure that it makes sense to go through the Fees pallet just for this?

.map_err(|_| Error::<R>::BalanceLow)
}

fn correct_and_deposit_fee(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this, in turn, would be calls to Fees::fee_to_author() and Fees::fee_to_treasury().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fee_to_author and fee_to_treasury both do a withdraw internally, so they're not suitable here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I understand 👍🏻

base_fee: U256,
already_withdrawn: Self::LiquidityInfo,
) -> Self::LiquidityInfo {
let Some(paid) = already_withdrawn else { return None };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is so cool that even Github is unable to highlight it well 😲

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustfmt also unfortunately does not handle let else properly yet, so we should probably only use it for small things like this. Otherwise we'll end up with a bunch of reformats when rustfmt finally gets updated

Comment on lines 115 to 122
// Handle base fee and tips
let (treasury_amount, mut author_amount) = base_fee.ration(
TREASURY_FEE_RATIO.deconstruct(),
(Perbill::one() - TREASURY_FEE_RATIO).deconstruct(),
);
tip.merge_into(&mut author_amount);
<Treasury<R> as OnUnbalanced<_>>::on_unbalanced(treasury_amount);
<ToAuthor<R> as OnUnbalanced<_>>::on_unbalanced(author_amount);
Copy link
Contributor

@lemunozm lemunozm Jun 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section reminds me to DealWithFees type, located in runtime/common/src/lib.rs. I think the implementation is the same. Maybe we can call it to avoid duplicate code:

DealWithFees::on_unbalanceds([base_fee, tip].iter());

Or similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 yeah, originally I had the tip handling done in pay_priority_fee, but since I rolled it all into one place it makes sense to call up into DealWithFees so we only have one place to update

@lemunozm lemunozm self-requested a review June 8, 2023 05:20
lemunozm
lemunozm previously approved these changes Jun 8, 2023
Copy link
Contributor

@lemunozm lemunozm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great another couple of eyes, but LGTM!

wischli
wischli previously approved these changes Jun 8, 2023
Copy link
Contributor

@wischli wischli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I have a tiny nit that totally can be ignored.

A dumb question from my side would be, why we do not simply apply the impl_on_charge_evm_transaction macro boilerplate as done in Moonbeam?

// If we tried to refund something, the account still empty and the ED is set to
// 0, we call `make_free_balance_be` with the refunded amount.
let refund_imbalance = if Balances::<R>::minimum_balance().is_zero()
&& refund_amount > <Balance<R>>::zero()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
&& refund_amount > <Balance<R>>::zero()
&& !refund_amount.is_zero()

@mustermeiszer
Copy link
Collaborator

What is the state of this?

Branan Riley added 2 commits August 21, 2023 15:24
This implements a custom `OnChargeEVMTransaction` for our chain.

Unfortunately the EVM handling of base_fee+priority is slightly
different from how pallet_transaction_payment handles fees+tips,
so we have to reimplement quite a bit more logic than I would have
ideally liked. Fortunately, it's all pretty straightforward fee
handling bits.
@wischli wischli added this to the Centrifuge 10xx milestone Apr 16, 2024
@wischli wischli added the P0-someday-maybe Issue might be worth doing someday. label Apr 16, 2024
@wischli
Copy link
Contributor

wischli commented Apr 16, 2024

@mustermeiszer I suppose we still want this at some point or can we close it?

@mustermeiszer
Copy link
Collaborator

Yes, I would say so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P0-someday-maybe Issue might be worth doing someday.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants