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

Implement 0x liquidity #2218

Merged
merged 19 commits into from
Apr 4, 2024
Merged

Implement 0x liquidity #2218

merged 19 commits into from
Apr 4, 2024

Conversation

squadgazzz
Copy link
Contributor

@squadgazzz squadgazzz commented Dec 27, 2023

Description

Removes all the 0x liquidity-related todos.

Changes

Some functionality is copied from the solver crate to reduce the dependencies count.

How to test

#2253

Related Issues

Fixes #1666

Comment on lines 16 to 20
solver::{
liquidity::{zeroex::ZeroExLiquidity, LimitOrder, LimitOrderExecution},
liquidity_collector::LiquidityCollecting,
settlement::SettlementEncoder,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

How much work would it be to not depend on this code but instead port what we need into the driver?
While not strictly required to achieve what we need here, it's covered by #2215 so we might as well start it here if it's not too much work.

Copy link
Contributor Author

@squadgazzz squadgazzz Dec 28, 2023

Choose a reason for hiding this comment

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

LiquidityCollecting is currently not possible to move only for 0x since this trait is used for all other liquidity providers. LimitOrder is part of it as well too.

ZeroExLiquidity probably can be moved, but it contains a lot of code and dependencies to the solver crate. It would be better to try in a separate PR. SettlementEncoder and LimitOrderExecution are removed.

Comment on lines 25 to 30
let handler = pool
.settlement_handling
.as_any()
.downcast_ref::<solver::liquidity::zeroex::OrderSettlementHandler>()
.ok_or(anyhow!("not a zeroex::OrderSettlementHandler"))?
.clone();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to avoid that, but we need to provide the contract and order somehow. Currently, it's not possible to add zeroex-specific fields right to the solver::LimitOrder since it's used with different settlement handlers. To address it, looks like the whole solver::Liquidity should be moved to the driver crate first.

Comment on lines -401 to -540
hash:
$ref: "#/components/schemas/Digest"
Copy link
Contributor Author

@squadgazzz squadgazzz Dec 28, 2023

Choose a reason for hiding this comment

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

Turned out that is not currently used at all. And also not sure how to populate it.

Comment on lines 11 to 15
pub sell_token: H160,
pub buy_token: H160,
pub sell_amount: U256,
pub buy_amount: U256,
pub order: Order,
Copy link
Contributor Author

@squadgazzz squadgazzz Dec 28, 2023

Choose a reason for hiding this comment

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

order already contains sell/buy token/amount, but the values might differ from the LimitOrder's: 1, 2.

Copy link
Contributor

Choose a reason for hiding this comment

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

How so? I think only [2] is relevant for us (the other one is a CoW native limit order which is represented differently). I think all we need is Order and IZeroEx.

Even full_execution_amount we should be able to pass along in to_interaction (using input/output fields on solution::interaction::Liquidity) since this would allow solvers to use this liquidity partially (if we set the full execution amount in to_domain we commit to the amount that needs to be executed before solving).

If I'm not mistaken (docs), takerTokenFillAmount should be what we call inputs:

/// The assets consumed by this interaction. These assets are taken from the
/// settlement contract when the interaction executes.
pub fn inputs(&self) -> Vec<eth::Asset> {

Copy link
Contributor Author

@squadgazzz squadgazzz Dec 29, 2023

Choose a reason for hiding this comment

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

If I'm not mistaken (docs), takerTokenFillAmount should be what we call inputs:

Correct me if I got it wrong:

input.0.amount.0.as_u128(),

And here, should we also use input from Liquidity or order's value?

taker_token_fee_amount: limit_order.order.taker_token_fee_amount.into(),

Comment on lines 201 to 208
id: liquidity.id.0,
address: pool.zeroex.address(),
gas_estimate: liquidity.gas.into(),
maker_token: pool.sell_token,
taker_token: pool.buy_token,
maker_amount: pool.sell_amount,
taker_amount: pool.buy_amount,
taker_token_fee_amount: pool.order.taker_token_fee_amount.into(),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not 100% sure the proper values are used here.

@squadgazzz squadgazzz marked this pull request as ready for review December 28, 2023 18:32
@squadgazzz squadgazzz requested a review from a team as a code owner December 28, 2023 18:32
Comment on lines 40 to 73
impl LimitOrder {
pub fn to_interaction(&self) -> anyhow::Result<eth::Interaction> {
let method = self.zeroex.fill_or_kill_limit_order(
(
self.order.maker_token,
self.order.taker_token,
self.order.maker_amount,
self.order.taker_amount,
self.order.taker_token_fee_amount,
self.order.maker,
self.order.taker,
self.order.sender,
self.order.fee_recipient,
Bytes(self.order.pool.0),
self.order.expiry,
self.order.salt,
),
(
self.order.signature_type,
self.order.signature_v,
Bytes(self.order.signature_r.0),
Bytes(self.order.signature_s.0),
),
self.full_execution_amount.as_u128(),
);
let calldata = method.tx.data.ok_or(anyhow!("no calldata"))?;

Ok(eth::Interaction {
target: self.zeroex.address().into(),
value: 0.into(),
call_data: calldata.0.into(),
})
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@fleupold fleupold 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! I think we can simplify the LimitOrder type much more and should document the downcasting tradeoff inside the code.

A bit of a bummer this is so hard to test, but I guess we have to mock a ZeroX API in e2e tests and write code to underwrite our own 0x order which sounds very involved.

let handler = limit_order
.settlement_handling
.as_any()
.downcast_ref::<solver::liquidity::zeroex::OrderSettlementHandler>()
Copy link
Contributor

Choose a reason for hiding this comment

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

😬 hack alert. Can we add a comment in the code on why we are chosing this workaround and how a proper solution would look like?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 11 to 15
pub sell_token: H160,
pub buy_token: H160,
pub sell_amount: U256,
pub buy_amount: U256,
pub order: Order,
Copy link
Contributor

Choose a reason for hiding this comment

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

How so? I think only [2] is relevant for us (the other one is a CoW native limit order which is represented differently). I think all we need is Order and IZeroEx.

Even full_execution_amount we should be able to pass along in to_interaction (using input/output fields on solution::interaction::Liquidity) since this would allow solvers to use this liquidity partially (if we set the full execution amount in to_domain we commit to the amount that needs to be executed before solving).

If I'm not mistaken (docs), takerTokenFillAmount should be what we call inputs:

/// The assets consumed by this interaction. These assets are taken from the
/// settlement contract when the interaction executes.
pub fn inputs(&self) -> Vec<eth::Asset> {

}

impl LimitOrder {
pub fn to_interaction(&self) -> anyhow::Result<eth::Interaction> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Noice!

@squadgazzz
Copy link
Contributor Author

A bit of a bummer this is so hard to test, but I guess we have to mock a ZeroX API in e2e tests and write code to underwrite our own 0x order which sounds very involved.

Will do

@squadgazzz squadgazzz marked this pull request as draft January 8, 2024 17:29
# Conflicts:
#	crates/solvers/openapi.yml
pub struct LimitOrder {}
pub struct LimitOrder {
pub order: Order,
pub zeroex: IZeroEx,
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe other liquidity implementations would have the IZeroEx struct via an Arc because it's pretty big and always identical.

Comment on lines 29 to 32
pub signature_type: u8,
pub signature_r: H256,
pub signature_s: H256,
pub signature_v: u8,
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be nice to collapse that into a Signature struct.

#[derive(Clone)]
pub struct OrderSettlementHandler {
pub order: Order,
pub zeroex: IZeroEx,
Copy link
Contributor

Choose a reason for hiding this comment

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

This IZeroEx struct could also be Arced.

Bytes(self.order.signature_r.0),
Bytes(self.order.signature_s.0),
),
input.0.amount.0.as_u128(),
Copy link
Contributor

Choose a reason for hiding this comment

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

This should probably do .try_into().context("executed amount does not fit into u128") because the liquidity::MaxInput type theoretically allows bigger amounts than 0x can handle.

@squadgazzz squadgazzz added the blocked This issue is blocked by some other work label Jan 29, 2024
Copy link

github-actions bot commented Feb 6, 2024

This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed.

@github-actions github-actions bot added stale and removed stale labels Feb 6, 2024
# Conflicts:
#	crates/solver/src/interactions/zeroex.rs
#	crates/solvers/src/api/routes/solve/dto/auction.rs
@squadgazzz squadgazzz removed the blocked This issue is blocked by some other work label Apr 3, 2024
@squadgazzz squadgazzz marked this pull request as ready for review April 3, 2024 16:00
@squadgazzz
Copy link
Contributor Author

Covered with the test: #2253

@squadgazzz squadgazzz enabled auto-merge (squash) April 4, 2024 13:54
@squadgazzz squadgazzz merged commit 5a6a942 into main Apr 4, 2024
9 checks passed
@squadgazzz squadgazzz deleted the fix/1666-2 branch April 4, 2024 13:58
@github-actions github-actions bot locked and limited conversation to collaborators Apr 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fetch 0x Limit Order Liquidity in colocated driver
4 participants