-
Notifications
You must be signed in to change notification settings - Fork 90
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
Observe multiple contracts for ETH flow #3249
base: main
Are you sure you want to change the base?
Conversation
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.
Approach looks like it should work but I think the code in the refunder could be simplified quite a lot.
// Theoretically, multiple orders with the same order_hash can exist in multiple | ||
// contracts at the same time. That's why we need to return a list of contracts | ||
// from which the order should be refunded. |
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.
The entire order owner is part of the order_uid so since the ethflow contract is technically the order owner the owner bytes of the 2 order uids would be different for identical orders placed on multiple ethflow contracts.
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.
contract is technically the order owner
I assumed the same but apparently this is not true for PreSign orders (although I couldn't find the right example to double check):
https://github.com/cowprotocol/services/blob/main/crates/autopilot/src/database/onchain_order_events/mod.rs#L642
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.
Now I see this: https://github.com/cowprotocol/ethflowcontract/blob/f466b7a8d5df80b593aeb05488e1c27afc7f2704/src/CoWSwapEthFlow.sol#L105
This means that all orders are 1271 orders, I guess, meaning I can leverage the fact that owner is always the EthFlowContract
.map(|contract| { | ||
contract | ||
.orders(ethcontract::tokens::Bytes(order_hash)) | ||
.batch_call(&mut batch) |
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.
The refunder
uses our auto batching logic under the hood. If make use of this this function would probably end up being a lot easier to read.
tracing::error!( | ||
"Error while getting the currentonchain status of orderhash \ | ||
{:?}, {:?}", | ||
H256(order_hash), | ||
err | ||
); |
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.
nit: Let's apply the usual pattern for logs while we change the code anyway.
tracing::error!( | |
"Error while getting the currentonchain status of orderhash \ | |
{:?}, {:?}", | |
H256(order_hash), | |
err | |
); | |
tracing::error!( | |
uid =? H256(order_hash), | |
?err, | |
"Error while getting the current onchain status ot the order" | |
); |
.context(format!("uid {uid:?}")) | ||
|
||
// Go over all order uids and group them by ethflow contract address | ||
let mut uids_by_contract: HashMap<CoWSwapEthFlowAddress, Vec<OrderUid>> = HashMap::new(); |
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.
This could probably be replace with Itertools::group_by
@@ -98,63 +93,55 @@ impl RefundService { | |||
async fn identify_uids_refunding_status_via_web3_calls( | |||
&self, | |||
refundable_order_uids: Vec<EthOrderPlacement>, | |||
) -> Result<Vec<OrderUid>> { | |||
) -> Vec<(OrderUid, Vec<CoWSwapEthFlowAddress>)> { |
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.
Given that an OrderUid
can only belong to a single contract we can ditch the vector. And I would suggest to simply copy the contract type instead of messing around with the address to make the code easier to read. The refunder is doing barely any work anyway so I think we should optimize for readability over performance here.
) -> Vec<(OrderUid, Vec<CoWSwapEthFlowAddress>)> { | |
) -> Vec<(OrderUid, CoWSwapEthFlow)> { |
let mut events = | ||
AllEventsBuilder::new(self.web3.clone(), *self.addresses.first().unwrap(), None); | ||
// We want to observe multiple addresses for events. | ||
events.filter = events.filter.address(self.addresses.clone()); |
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.
In the future, it probably makes sense to adjust the new
function signature in the ethcontract
crate to allow for the collection of addresses.
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.
LGTM, assuming all the comments above will be addressed.
Description
Implements the idea explained here: #3248 (comment)
The Ethflow contract of interest: https://etherscan.io/address/0x40a50cf069e992aa4536211b23f286ef88752187#code (probably useful to better review and understand refunder code changes)
This solution has a limitation: we can't specify a block number to start indexing the new contract. Upon autopilot restart, indexing resumes from the latest block recorded in the database. This approach assumes synchronized and atomic insertion of events for both the old and new contracts.
As a result, new contract events will only be indexed from the point when the new contract address is added to the autopilot configuration.
This is acceptable under the following assumptions:
Changes
EthFlowRefundRetriever
andCoWSwapOnchainOrdersContract
are now observing multiple ethflow contracts at the same time.How to test
Existing e2e tests.
Updated refunder e2e test to simulate two orders being created on two different ethflow contracts and being properly refunded.
I also manually verified (through observing logs on e2e tests) that indexing from multiple contracts works properly.