-
Notifications
You must be signed in to change notification settings - Fork 302
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
dex: Swap alt fee tokens for native fee token #4643
Conversation
Testing:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments and ACK, will test this later (pairing on testing would be cool if there are takers)
LGTM overall, I have some bandwidth to write some state machine tests |
What should happen if there isn't enough liquidity to perform a swap for the alternative fee token? Currently it will be burned, which seems fine. What about when the funding component is implemented; will tips be paid out in alternative assets if there isn't liquidity available to swap them? |
I'm working on this branch, and then will post updates on testing |
This commit moves fee handling out of the Transaction's ActionHandler and into the component, which accumulates fees (in any token), and adds hooks to the DEX thatadd chain-submitted swaps for any non-native fee tokens into the native token. These are then accumulated back into the fee component. The base fee and tip are tracked separately through this whole process, in order to support the intended behaviour (the base fee is burned to account for the _chain_'s resource use, the tip is sent to the proposer to encourage them to include transactions in fee priority order). However, tip handling is not currently implemented, so both are burned. Later, the funding/distribution components should extract the tip and send it to the proposer's funding streams. However, until a robust fee market develops, this form of proposer incentivization can be deferred. The accounting will be there for it when it arises.
Tested on a devnet earlier today, I was able to observe:
I am close to done with a SM test that prove that a multiswap block is accounted for correctly by the VCB mechanism. #4645 is a WIP with SM test of a spend transaction generating alt fees that get swapped. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are still working on assurance. However, for the sake of not blocking release readiness I am in favor of merging this as-is once it has collected an additional ACK. We commit to following-up with application tests shortly.
I haven't sufficiently tested to ACK, but I support optimistically merging if you have and I'll do more testing later. |
// Obtain the base fee and tip amounts in the native token, discarding any unfilled amounts. | ||
let (swapped_base, swapped_tip) = if pair.asset_1() == *asset_id { | ||
// If `asset_id` is `R_1` we want to pull the other leg of the pair. | ||
(base_output.1, tip_output.1) | ||
} else { | ||
// and vice-versa. `R_1` contains native tokens. | ||
(base_output.0, tip_output.0) | ||
}; | ||
|
||
// Finally, accumulate the swapped base fee and tip back into the fee component. | ||
// (We already took all the fees out). | ||
state_ref.raw_accumulate_base_fee(Fee::from_staking_token_amount(swapped_base)); | ||
state_ref.raw_accumulate_tip(Fee::from_staking_token_amount(swapped_tip)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Obtain the base fee and tip amounts in the native token, discarding any unfilled amounts. | |
let (swapped_base, swapped_tip) = if pair.asset_1() == *asset_id { | |
// If `asset_id` is `R_1` we want to pull the other leg of the pair. | |
(base_output.1, tip_output.1) | |
} else { | |
// and vice-versa. `R_1` contains native tokens. | |
(base_output.0, tip_output.0) | |
}; | |
// Finally, accumulate the swapped base fee and tip back into the fee component. | |
// (We already took all the fees out). | |
state_ref.raw_accumulate_base_fee(Fee::from_staking_token_amount(swapped_base)); | |
state_ref.raw_accumulate_tip(Fee::from_staking_token_amount(swapped_tip)); | |
// Obtain the base fee and tip amounts in the native token, discarding any unfilled amounts. | |
let ((swapped_base, unswapped_base), (swapped_tip, unswapped_tip)) = if pair.asset_1() == *asset_id { | |
// If `asset_id` is `R_1` we want to pull the other leg of the pair. | |
((base_output.1, base_output.0), (tip_output.1, tip_output.0)) | |
} else { | |
// and vice-versa. `R_1` contains native tokens. | |
((base_output.0, base_output.1), (tip_output.0, tip_output.1)) | |
}; | |
// Finally, accumulate the swapped base fee and tip back into the fee component. | |
// (We already took all the fees out). | |
state_ref.raw_accumulate_base_fee(Fee::from_staking_token_amount(swapped_base)); | |
state_ref.raw_accumulate_tip(Fee::from_staking_token_amount(swapped_tip)); | |
state_ref.raw_accumulate_base_fee(Fee(Value { amount: unswapped_base, asset_id: *asset_id })); | |
state_ref.raw_accumulate_tip(Fee(Value { amount: unswapped_tip, asset_id: *asset_id })); |
What if we also accumulated the unswapped portion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the goal is to collapse all the user supplied fee amounts to the native token
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, main thing I'm unsure about is whether or not we correctly handle the accumulated state of fees at an end of a block:
- Do we want to keep the unswapped amounts over to the next block, to try swapping again?
- Do we need to clear the amounts, or is the intention to accumulate them forever, so that the event is the total fees since the start? (I don't think that's the case)
On keeping the unwrapped fees: I don't think so. That case shouldn't happen, now or in the future:
|
On clearing the accumulated fees: this is supposed to act as a defense measure against value creation bugs, by "taking" the value out before swapping it. |
This contains the VCB repro, app test to follow shortly. |
Describe your changes
Moves fee handling out of the Transaction's ActionHandler and into
the component, which accumulates fees (in any token), and adds hooks to the DEX
thatadd chain-submitted swaps for any non-native fee tokens into the native
token. These are then accumulated back into the fee component.
The base fee and tip are tracked separately through this whole process, in
order to support the intended behaviour (the base fee is burned to account for
the chain's resource use, the tip is sent to the proposer to encourage them
to include transactions in fee priority order). However, tip handling is not
currently implemented, so both are burned. Later, the funding/distribution
components should extract the tip and send it to the proposer's funding
streams. However, until a robust fee market develops, this form of proposer
incentivization can be deferred. The accounting will be there for it when it
arises.
Issue ticket number and link
#4328
Checklist before requesting a review
If this code contains consensus-breaking changes, I have added the "consensus-breaking" label. Otherwise, I declare my belief that there are not consensus-breaking changes, for the following reason: