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

fix, refactor(sequencer): refactor ics20 logic #1495

Merged
merged 10 commits into from
Sep 19, 2024

Conversation

SuperFluffy
Copy link
Member

@SuperFluffy SuperFluffy commented Sep 12, 2024

Summary

Fixes incorrect addresses in ics20 refunds, and fixes/adds source vs sink zone detection of received/refunded asets.

Background

This PR started with the goal of using Ics20WithdrawalFromRollup.rollup_return_address when emitting ics20 deposit events instead of the rollup's bridge address (which for the rollup was quite meaningless).

However, because the original logic was overly convoluted, this patch evolved into a refactor which subsequently revealed 2 more bugs.

Changes

  • Refactor ics20 logic: split up execute_ics20_transfer into two functions receive_tokens and refund_tokens
  • Fix deposit events being emitted with the packet sender/bridge address as the receiving address on the rollup: instead use Ics20WithdrawalFromRollup.rollup_return_address which is the address originally supplied and understood by the rollup.
  • Fix bridge lock events of source tokens being emitted with an extra (port, channel) pair added (this resulting token is likely completely meaningless and not understood by the rollup): instead strip the leading (port, channel) pair to get the original token on sequencer.
  • Fix refunds to a rollup of failed ics20 transfers not checking if sequencer is their source or sink zone: instead perform the check and decrease the ibc escrow account is necessary.

Testing

Renamed and expanded tests to also check for sink vs source zone assets being received, the correct asset being emitted in bridge lock events, and the correct rollup return address being emitted in refunds. Specifically these tests were added or renamed:

  • receive_source_zone_asset_on_sequencer_account
  • receive_sink_zone_asset_on_sequencer_account
  • receive_source_zone_asset_on_bridge_account_and_emit_to_rollup
  • receive_sink_zone_asset_on_bridge_account_and_emit_to_rollup
  • transfer_to_bridge_is_rejected_due_to_invalid_memo
  • transfer_to_bridge_account_is_rejected_due_to_not_permitted_token
  • refund_sequencer_account_with_source_zone_asset
  • refund_sequencer_account_with_sink_zone_asset
  • refund_rollup_with_sink_zone_asset
  • refund_rollup_with_source_zone_asset
  • refund_rollup_with_source_zone_asset_compat_prefix

Related Issues

Closes #1439
Closes #1496
Closes #1514

@github-actions github-actions bot added the sequencer pertaining to the astria-sequencer crate label Sep 12, 2024
@SuperFluffy SuperFluffy force-pushed the ENG-711/use_rollup_address_for_refunds branch from 9ed086c to 7476516 Compare September 12, 2024 13:02
/// assert!(!denom.has_leading_port(""));
/// ```
#[must_use]
pub fn has_leading_port<T: AsRef<str>>(&self, port: T) -> bool {
Copy link
Member Author

Choose a reason for hiding this comment

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

Added has_leading_port and has_leading_channel to have a stricter prefix check instead of starts_with_str.

return false;
}
parts.next().is_none()
pub fn has_leading_channel<T: AsRef<str>>(&self, channel: T) -> bool {
Copy link
Member Author

Choose a reason for hiding this comment

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

Added has_leading_port and has_leading_channel to have a stricter prefix check instead of starts_with_str.

@@ -1291,86 +1291,23 @@ impl FilteredSequencerBlockError {
)]
pub struct Deposit {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is just a stupid container without any invariants.

Made all fields public and removed the getters.

}

impl Deposit {
#[must_use]
pub fn new(
Copy link
Member Author

Choose a reason for hiding this comment

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

Terrible evergrowing constructor. Since there are no invariants to be upheld I removed it in favor of directly constructing Deposit from public fields.

@@ -1439,6 +1376,12 @@ impl Deposit {
}
}

impl From<Deposit> for crate::generated::sequencerblock::v1alpha1::Deposit {
Copy link
Member Author

@SuperFluffy SuperFluffy Sep 12, 2024

Choose a reason for hiding this comment

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

Not new, just moved down from above; this is an artifact of the refactor, but the trait impl fits better down here.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.


#[async_trait]
pub(crate) trait StateWriteExt: StateWrite {
#[instrument(skip_all, fields(%channel))]
async fn decrease_ibc_channel_balance<TAsset>(
Copy link
Member Author

Choose a reason for hiding this comment

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

New utility to atomically read-update-write the balance on the escrow account.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to deposit losing its getters

let ack: TokenTransferAcknowledgement =
serde_json::from_slice(msg.acknowledgement.as_slice())
.context("failed to deserialize token transfer acknowledgement")?;
if !ack.is_successful() {
Copy link
Member Author

Choose a reason for hiding this comment

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

This just flips the logic: instead of returning early on success, success is now the fall-through case while failure triggers a refund.

Copy link
Member Author

Choose a reason for hiding this comment

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

This file should probably not be reviewed using its diff, but instead read from source.

As a high level overview:

execute_ics20_transfer (that branched on an argument is_refund) is split up into receive_tokens and refund_tokens.

Both functions were cleaned up and should be much easier to read.


// check if this is a transfer to a bridge account and
// execute relevant state changes if it is
execute_ics20_transfer_bridge_lock(
Copy link
Member Author

Choose a reason for hiding this comment

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

I believe this function was incorrect: its argument trace_with_dest = dest_port/dest_channel/source_port/source_channel/asset was always constructed irrespective of whether sequencer was a source or a sink zone, but the construction is only correct if sequencer is a sink!

If sequencer is a source, then dest_port/dest_channel must not be prepended, and instead source_port/soure_channel removed, leaving just asset.

bridge_address,
&denom,
memo.rollup_return_address,
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the actual fix for the incorrect deposit: instead of bridge_address being used twice, the memo.rollup_return_address is now put into destination_chain_address field.

@SuperFluffy SuperFluffy force-pushed the ENG-711/use_rollup_address_for_refunds branch from 7476516 to 34e8132 Compare September 12, 2024 13:24
Copy link
Member Author

Choose a reason for hiding this comment

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

contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.

@SuperFluffy SuperFluffy force-pushed the ENG-711/use_rollup_address_for_refunds branch from 34e8132 to b8d2f27 Compare September 12, 2024 13:56
@SuperFluffy SuperFluffy marked this pull request as ready for review September 12, 2024 13:56
@SuperFluffy SuperFluffy requested a review from a team as a code owner September 12, 2024 13:56
@SuperFluffy SuperFluffy force-pushed the ENG-711/use_rollup_address_for_refunds branch from 0b09c08 to 5673d04 Compare September 18, 2024 10:24
@SuperFluffy
Copy link
Member Author

Rebased on top of recent main.

In addition I instrumented all code that's called during ics20 execution, injecting address information, assets, amounts, etc into the generated spans. Function calls using eyre Reports as errors also generates an event in error cases.

Copy link
Collaborator

@noot noot left a comment

Choose a reason for hiding this comment

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

looks good to me :D

SuperFluffy and others added 2 commits September 19, 2024 18:46
Co-authored-by: noot <36753753+noot@users.noreply.github.com>
@SuperFluffy SuperFluffy force-pushed the ENG-711/use_rollup_address_for_refunds branch from 15efaec to be88e99 Compare September 19, 2024 16:51
@SuperFluffy SuperFluffy added this pull request to the merge queue Sep 19, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 19, 2024
@SuperFluffy SuperFluffy added this pull request to the merge queue Sep 19, 2024
github-merge-queue bot pushed a commit that referenced this pull request Sep 19, 2024
## Summary
Fixes incorrect addresses in ics20 refunds, and fixes/adds source vs
sink zone detection of received/refunded asets.

## Background
This PR started with the goal of using
`Ics20WithdrawalFromRollup.rollup_return_address` when emitting ics20
deposit events instead of the rollup's bridge address (which for the
rollup was quite meaningless).

However, because the original logic was overly convoluted, this patch
evolved into a refactor which subsequently revealed 2 more bugs.

## Changes
- Refactor ics20 logic: split up `execute_ics20_transfer` into two
functions `receive_tokens` and `refund_tokens`
- Fix deposit events being emitted with the packet sender/bridge address
as the receiving address on the rollup: instead use
`Ics20WithdrawalFromRollup.rollup_return_address` which is the address
originally supplied and understood by the rollup.
- Fix bridge lock events of source tokens being emitted with an extra
(port, channel) pair added (this resulting token is likely completely
meaningless and not understood by the rollup): instead strip the leading
(port, channel) pair to get the original token on sequencer.
- Fix refunds to a rollup of failed ics20 transfers not checking if
sequencer is their source or sink zone: instead perform the check and
decrease the ibc escrow account is necessary.

## Testing

Renamed and expanded tests to also check for sink vs source zone assets
being received, the correct asset being emitted in bridge lock events,
and the correct rollup return address being emitted in refunds.
Specifically these tests were added or renamed:


- `receive_source_zone_asset_on_sequencer_account`
- `receive_sink_zone_asset_on_sequencer_account`
- `receive_source_zone_asset_on_bridge_account_and_emit_to_rollup`
- `receive_sink_zone_asset_on_bridge_account_and_emit_to_rollup`
- `transfer_to_bridge_is_rejected_due_to_invalid_memo`
- `transfer_to_bridge_account_is_rejected_due_to_not_permitted_token`
- `refund_sequencer_account_with_source_zone_asset`
- `refund_sequencer_account_with_sink_zone_asset`
- `refund_rollup_with_sink_zone_asset`
- `refund_rollup_with_source_zone_asset`
- `refund_rollup_with_source_zone_asset_compat_prefix`

## Related Issues
Closes #1439
Closes #1496
Closes #1514

---------

Co-authored-by: noot <36753753+noot@users.noreply.github.com>
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 19, 2024
@SuperFluffy SuperFluffy added this pull request to the merge queue Sep 19, 2024
Merged via the queue into main with commit c38ce8e Sep 19, 2024
42 checks passed
@SuperFluffy SuperFluffy deleted the ENG-711/use_rollup_address_for_refunds branch September 19, 2024 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sequencer pertaining to the astria-sequencer crate
Projects
None yet
2 participants