fix, refactor(sequencer): refactor ics20 logic#1495
Conversation
9ed086c to
7476516
Compare
| /// assert!(!denom.has_leading_port("")); | ||
| /// ``` | ||
| #[must_use] | ||
| pub fn has_leading_port<T: AsRef<str>>(&self, port: T) -> bool { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { | |||
There was a problem hiding this comment.
This is just a stupid container without any invariants.
Made all fields public and removed the getters.
|
|
||
| impl Deposit { | ||
| #[must_use] | ||
| pub fn new( |
There was a problem hiding this comment.
Terrible evergrowing constructor. Since there are no invariants to be upheld I removed it in favor of directly constructing Deposit from public fields.
| } | ||
| } | ||
|
|
||
| impl From<Deposit> for crate::generated::sequencerblock::v1alpha1::Deposit { |
There was a problem hiding this comment.
Not new, just moved down from above; this is an artifact of the refactor, but the trait impl fits better down here.
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
There was a problem hiding this comment.
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>( |
There was a problem hiding this comment.
New utility to atomically read-update-write the balance on the escrow account.
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
This just flips the logic: instead of returning early on success, success is now the fall-through case while failure triggers a refund.
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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.
| &mut state, | ||
| bridge_address, | ||
| &denom, | ||
| memo.rollup_return_address, |
There was a problem hiding this comment.
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.
7476516 to
34e8132
Compare
There was a problem hiding this comment.
contains only changes due to Deposit::new being replaced by direction declaration Deposit {}.
34e8132 to
b8d2f27
Compare
0b09c08 to
5673d04
Compare
|
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. |
Co-authored-by: noot <36753753+noot@users.noreply.github.com>
15efaec to
be88e99
Compare
## 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>
* main: feat(conductor): implement restart logic (#1463) fix: ignore `RUSTSEC-2024-0370` (#1483) fix, refactor(sequencer): refactor ics20 logic (#1495) fix(ci): use commit SHA instead of PR number preview-env images (#1501) chore(bridge-withdrawer): pass GRPC and CometBFT clients to consumers directly (#1510) fix(sequencer): Fix incorrect error message from BridgeUnlock actions (#1505) fix(bridge-contracts): fix memo transaction hash encoding (#1428) fix: build docker when workflow explicitly includes component (#1498) chore(sequencer): migrate from `anyhow::Result` to `eyre::Result` (#1387) fix(ci): typo for required field in sequencer preview-env (#1500) feat(ci): provide demo/preview environments (#1406)
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_addresswhen 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
execute_ics20_transferinto two functionsreceive_tokensandrefund_tokensIcs20WithdrawalFromRollup.rollup_return_addresswhich is the address originally supplied and understood by the rollup.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_accountreceive_sink_zone_asset_on_sequencer_accountreceive_source_zone_asset_on_bridge_account_and_emit_to_rollupreceive_sink_zone_asset_on_bridge_account_and_emit_to_rolluptransfer_to_bridge_is_rejected_due_to_invalid_memotransfer_to_bridge_account_is_rejected_due_to_not_permitted_tokenrefund_sequencer_account_with_source_zone_assetrefund_sequencer_account_with_sink_zone_assetrefund_rollup_with_sink_zone_assetrefund_rollup_with_source_zone_assetrefund_rollup_with_source_zone_asset_compat_prefixRelated Issues
Closes #1439
Closes #1496
Closes #1514