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: DOT swap output less than existential deposit #4062

Merged
merged 10 commits into from
Oct 19, 2023
Merged

Conversation

marcellorigotti
Copy link
Contributor

@marcellorigotti marcellorigotti commented Sep 28, 2023

Pull Request

Closes: PRO-871

Issue to resolve comments about the test: PRO-926

Checklist

Please conduct a thorough self-review before opening the PR.

  • I am confident that the code works.
  • I have updated documentation where appropriate.

Summary

This test perform 2 swaps:

  • the first one 5 usdc for less than 1 dot, resulting in an output < Existential deposit, the transaction should be still broadcasted successfully, but the balance of the destination address remain 0.00
  • the second swap is a normal USDC -> DOT swap to showcase that the resulting balance is correctly increased after the swap

Dot egress fix:

  • For dot egress, Instead of just looking at extrinsics with transfer events, we look at all extrinsics with ExtrinsicSuccess

@linear
Copy link

linear bot commented Sep 28, 2023

PRO-814 Handle egress below existential deposit

It seems like we still don't completely handle this case. AFAIK we use force transfer to ensure the legitimate transfers go through, even if one of them cannot because it's below the ED. However, it seems we're still expecting to witness the success of the egress, which of course, cannot occur. So we will still see a broadcast aborted, despite the transaction succeeding.

alastair saw this on his localnet.

@codecov
Copy link

codecov bot commented Sep 28, 2023

Codecov Report

Merging #4062 (a504bd3) into main (03c4f3c) will increase coverage by 0%.
Report is 13 commits behind head on main.
The diff coverage is 53%.

@@          Coverage Diff           @@
##            main   #4062    +/-   ##
======================================
  Coverage     72%     72%            
======================================
  Files        378     378            
  Lines      60663   60906   +243     
  Branches   60663   60906   +243     
======================================
+ Hits       43495   43677   +182     
- Misses     14904   14964    +60     
- Partials    2264    2265     +1     
Files Coverage Δ
engine/src/witness/dot/dot_deposits.rs 60% <75%> (-1%) ⬇️
engine/src/witness/dot.rs 29% <48%> (+5%) ⬆️

... and 16 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@marcellorigotti
Copy link
Contributor Author

Bouncer will never complete because of the test I just added.
When doing a single swap containing only a <ED dot as output we never emit the event BroadcastSuccess, hence the test will loop endlessly waiting for the event.

@linear
Copy link

linear bot commented Oct 18, 2023

PRO-871 Fix Polkadot broadcast success witnessing

Problem

We can currently ignore polkadot broadcast successes if they don't emit a Transfer event.

If we make a force_batch tx containing a single transfer that is below the existential deposit, the broadcast succeeds, since force_batch succeeds regardless of if the internal txs succeed or not. But since the inner transfer doesn't emit a transfer event - because it didn't succeed, we ignore it.

Current code break down

The current dot witnessing code collects extrinsic indices, which are the extrinsic indices of that block, which produced events that are relevant to us. In the dot_depositsadapter not that we check that we received a Transfer event, and that

				if &PolkadotAccountId::from_aliased(from.0) == our_vault ||
					&deposit_address == our_vault 

This if statement checks:

  • We have received something from our vault. This is currently capturing egress transactions to other dot addresses.
  • The deposit address is our vault. This is the case when we fetch funds from our generated addresses that have received deposits into our root/"vault" account.

Solution

For both of these we could instead use the ProxyExeucted event - and this would of course be done in a separate component not as part of the Deposit capturing. Currently the responsibilities are a bit blurred, so this should help fix that too.

Since all transactions we create are via the proxy, and we get a ProxyExecuted event from our vault, we can use this is broadcast success. This is conceptually similar to what we do to witness Ethereum broadcast successes, since we use the SignatureAcceptedevent from the KeyManager contract.

For the broadcast to be registered as success, we must submit the transaction_succeeed extrinsic.

To test this works, of course all the current bouncer tests should work, and the test in PRO-814 should pass too. That PR can be rebased onto this one in order to test it (CC: marcello - whoever picks this up might take over that branch).

Alternative Solutions Considered

Use the list of TxOutIds to filter the extrinsics we are watching, and then filter only the events from these extrinsics.

The drawback of this might be that we would not witness events that are triggered independently (for example governance intervention).

@j4m1ef0rd j4m1ef0rd marked this pull request as ready for review October 18, 2023 06:03
@kylezs kylezs changed the title swap (output less than ED of DOT) test to bouncer fix: DOT swap output less than existential deposit Oct 18, 2023
Copy link
Contributor

@kylezs kylezs left a comment

Choose a reason for hiding this comment

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

In the interests of getting this in quickly. I'm happy if the code comments are resolved, and an issue is created about the test changes

@@ -2,6 +2,7 @@ set -e
./commands/observe_block.ts 5
./commands/setup_vaults.ts
./commands/setup_swaps.ts
./tests/swap_less_than_existential_deposit_dot.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

we should put this as part of the concurrent tests - though, see comment further down

runWithTimeout,
} from '../shared/utils';

// This code is duplicated to allow us to specify a specific amount we want to swap
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is it duplicated? We should factor out the common code here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because I needed a custom version of the function where I could specify the amount to swap to be sure the output was less than ED, and where the result was determined by observing broadcastSuccess instead of balanceUpdated.

Copy link
Contributor

@kylezs kylezs Oct 18, 2023

Choose a reason for hiding this comment

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

Sure, it's not all common, but we can factor out the common code, potentially have one function where you can optionally provide an event to observe - haven't thought deeply about how exactly to do it, but it can be done

Copy link
Contributor

Choose a reason for hiding this comment

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

testSwap, performSwap and doPerformSwap have "amount" arguments as of commit 0a09832

amount: string,
balanceIncrease: boolean,
tag = '',
messageMetadata?: CcmDepositMetadata,
Copy link
Contributor

Choose a reason for hiding this comment

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

this isn't used - deduplicating ofc fixes this too

// and to wait for some specific events
export async function doPerformSwap(
{ sourceAsset, destAsset, destAddress, depositAddress, channelId }: SwapParams,
amount: string,
Copy link
Contributor

Choose a reason for hiding this comment

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

why string and not number?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no reason sendERC20 uses string so I just used it as well, we can change it if it makes things more clear

let stopObserving = false;
const observingBadEvents = observeBadEvents(':BroadcastAborted', () => stopObserving);

// The initial price is 10USDC = 1DOT,
Copy link
Contributor

Choose a reason for hiding this comment

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

How do we know this? This test is going to be quite flakey with hardcoded values. Ideally we query for the price, and then swap an amount that results in an egress less than the ED.

  • This might mean this test can't be part of concurrent tests, but that's fine, would rather have a test that when run individually we know is correct, regardless of the state of the pools at any point in time.

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 that's why I put this test as first, because I knew the states of the pool at the beginning of the bouncer (I wasn't sure how to query the prices but maybe it is easy to do so?), and that's also why it wasn't inside the concurrent tests, to be sure that when this is executed the price doesn't suddenly change with another swap.

Copy link
Contributor

Choose a reason for hiding this comment

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

It might not be easy to do, to check the price, but
a) this is a more useful / robust if we do
b) being able to query for the price will be useful for other more complex / granular swapping tests in the future
c) we can test the relevant price APIs too

so I think it's worth doing, but as mentioned, since I'm unsure how long it'll take I don't mind merging this as is, since the test passed in this order, and then fixing this as part of another issue.

Copy link
Contributor Author

@marcellorigotti marcellorigotti Oct 18, 2023

Choose a reason for hiding this comment

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

If we can query the price of the pool and move this in the concurrent tests then we should also update the observeEvent call to be sure to observe the correct polkadotBrodcast:
I guess we can easily derive the broadcastID knowing the swap channel, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sorry replied before reading your answer, anyway I'll create a linear ticket with all this info so we don't forget if we merge this!

@j4m1ef0rd j4m1ef0rd requested a review from kylezs October 19, 2023 02:58
@kylezs kylezs enabled auto-merge (squash) October 19, 2023 08:49
@kylezs kylezs merged commit abb0f48 into main Oct 19, 2023
@kylezs kylezs deleted the feature/pro-814 branch October 19, 2023 09:22
@linear linear bot mentioned this pull request Nov 2, 2023
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants