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
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/driver/src/boundary/liquidity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use {
pub mod balancer;
pub mod swapr;
pub mod uniswap;
mod zeroex;
pub mod zeroex;

/// The default poll interval for the block stream updating task.
const BLOCK_POLL_INTERVAL: Duration = Duration::from_secs(1);
Expand Down Expand Up @@ -169,7 +169,7 @@ impl Fetcher {
}
Liquidity::BalancerWeighted(pool) => balancer::v2::weighted::to_domain(id, pool),
Liquidity::BalancerStable(pool) => balancer::v2::stable::to_domain(id, pool),
Liquidity::LimitOrder(_) => unreachable!(),
Liquidity::LimitOrder(pool) => zeroex::to_domain(id, pool),
Liquidity::Concentrated(pool) => uniswap::v3::to_domain(id, pool),
}
// Ignore "bad" liquidity - this allows the driver to continue
Expand Down
71 changes: 68 additions & 3 deletions crates/driver/src/boundary/liquidity/zeroex.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,76 @@
use {
crate::{infra, infra::Ethereum},
crate::{
domain::liquidity::{
self,
zeroex::{self, Order, ZeroExSignature},
},
infra::{self, Ethereum},
},
anyhow::anyhow,
ethrpc::current_block::CurrentBlockStream,
shared::{http_client::HttpClientFactory, zeroex_api::DefaultZeroExApi},
solver::{liquidity::zeroex::ZeroExLiquidity, liquidity_collector::LiquidityCollecting},
shared::{
http_client::HttpClientFactory,
price_estimation::gas::GAS_PER_ZEROEX_ORDER,
zeroex_api::DefaultZeroExApi,
},
solver::{
liquidity::{zeroex::ZeroExLiquidity, LimitOrder},
liquidity_collector::LiquidityCollecting,
},
std::sync::Arc,
};

pub fn to_domain(
id: liquidity::Id,
limit_order: LimitOrder,
) -> anyhow::Result<liquidity::Liquidity> {
// `order` and `contract` should be provided somehow through the `LimitOrder`
// struct. Currently, it's not possible to add 0x-specific fields right to
// the `solver::LimitOrder` since it's used with different settlement
// handlers. One of the options to address it: to use a separate
// `solver::Liquidity` enum value for 0x liquidity.
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

.ok_or(anyhow!("not a zeroex::OrderSettlementHandler"))?
.clone();

let signature = ZeroExSignature {
r: handler.order.signature.r,
s: handler.order.signature.s,
v: handler.order.signature.v,
signature_type: handler.order.signature.signature_type,
};

let order = Order {
maker: handler.order.maker,
taker: handler.order.taker,
sender: handler.order.sender,
maker_token: handler.order.maker_token,
taker_token: handler.order.taker_token,
maker_amount: handler.order.maker_amount,
taker_amount: handler.order.taker_amount,
taker_token_fee_amount: handler.order.taker_token_fee_amount,
fee_recipient: handler.order.fee_recipient,
pool: handler.order.pool,
expiry: handler.order.expiry,
salt: handler.order.salt,
signature,
};

let domain = zeroex::LimitOrder {
order,
zeroex: handler.zeroex.clone(),
};

Ok(liquidity::Liquidity {
id,
gas: GAS_PER_ZEROEX_ORDER.into(),
kind: liquidity::Kind::ZeroEx(domain),
})
}

pub async fn collector(
eth: &Ethereum,
blocks: CurrentBlockStream,
Expand Down
4 changes: 3 additions & 1 deletion crates/driver/src/boundary/settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,9 @@ pub fn to_boundary_interaction(
liquidity::Kind::Swapr(pool) => pool
.swap(&input, &output, &settlement_contract.into())
.context("invalid swapr execution")?,
liquidity::Kind::ZeroEx(_) => todo!(),
liquidity::Kind::ZeroEx(limit_order) => limit_order
.to_interaction(&input)
.context("invalid zeroex execution")?,
};

Ok(InteractionData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl Interaction {
liquidity::Kind::BalancerV2Stable(pool) => pool.vault.into(),
liquidity::Kind::BalancerV2Weighted(pool) => pool.vault.into(),
liquidity::Kind::Swapr(pool) => pool.base.router.into(),
liquidity::Kind::ZeroEx(_) => todo!(),
liquidity::Kind::ZeroEx(pool) => pool.zeroex.address().into(),
};
vec![eth::Allowance {
token: interaction.input.token,
Expand Down
83 changes: 79 additions & 4 deletions crates/driver/src/domain/liquidity/zeroex.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,80 @@
/// A signed 0x Protocol Limit Order [^1].
///
/// [^1]: <https://docs.0x.org/limit-orders-advanced-traders/docs/introduction>
use {
crate::domain::{eth, liquidity},
anyhow::{anyhow, Context},
contracts::IZeroEx,
ethcontract::Bytes,
primitive_types::{H160, H256, U256},
std::sync::Arc,
};

#[derive(Clone, Debug)]
pub struct LimitOrder {}
pub struct LimitOrder {
pub order: Order,
pub zeroex: Arc<IZeroEx>,
}

#[derive(Clone, Debug)]
pub struct Order {
pub maker: H160,
pub taker: H160,
pub sender: H160,
pub maker_token: H160,
pub taker_token: H160,
pub maker_amount: u128,
pub taker_amount: u128,
pub taker_token_fee_amount: u128,
pub fee_recipient: H160,
pub pool: H256,
pub expiry: u64,
pub salt: U256,
pub signature: ZeroExSignature,
}

#[derive(Clone, Debug)]
pub struct ZeroExSignature {
pub r: H256,
pub s: H256,
pub v: u8,
pub signature_type: u8,
}

impl LimitOrder {
pub fn to_interaction(&self, input: &liquidity::MaxInput) -> anyhow::Result<eth::Interaction> {
let method = self.zeroex.clone().fill_or_kill_limit_order(
(
squadgazzz marked this conversation as resolved.
Show resolved Hide resolved
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.signature_type,
self.order.signature.v,
Bytes(self.order.signature.r.0),
Bytes(self.order.signature.s.0),
),
input
.0
.amount
.0
.try_into()
.map_err(|err: &str| anyhow!(err))
.context("executed amount does not fit into u128")?,
squadgazzz marked this conversation as resolved.
Show resolved Hide resolved
);
let calldata = method.tx.data.ok_or(anyhow!("no calldata"))?;

Ok(eth::Interaction {
target: self.zeroex.clone().address().into(),
value: 0.into(),
squadgazzz marked this conversation as resolved.
Show resolved Hide resolved
call_data: calldata.0.into(),
})
}
}
22 changes: 18 additions & 4 deletions crates/driver/src/infra/solver/dto/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ impl Auction {
liquidity::Kind::Swapr(pool) => {
pool.base.reserves.iter().map(|r| r.token).collect()
}
liquidity::Kind::ZeroEx(_) => todo!(),
liquidity::Kind::ZeroEx(limit_order) => {
vec![
limit_order.order.maker_token.into(),
limit_order.order.taker_token.into(),
]
}
})
{
tokens.entry(token.into()).or_insert_with(Default::default);
Expand Down Expand Up @@ -249,7 +254,18 @@ impl Auction {
fee: bigdecimal::BigDecimal::new(pool.fee.bps().into(), 4),
})
}
liquidity::Kind::ZeroEx(_) => todo!(),
liquidity::Kind::ZeroEx(limit_order) => {
Liquidity::LimitOrder(ForeignLimitOrder {
id: liquidity.id.0,
address: limit_order.zeroex.address(),
gas_estimate: liquidity.gas.into(),
maker_token: limit_order.order.maker_token,
taker_token: limit_order.order.taker_token,
maker_amount: limit_order.order.maker_amount.into(),
taker_amount: limit_order.order.taker_amount.into(),
taker_token_fee_amount: limit_order.order.taker_token_fee_amount.into(),
})
}
})
.collect(),
tokens,
Expand Down Expand Up @@ -504,8 +520,6 @@ struct ForeignLimitOrder {
address: eth::H160,
#[serde_as(as = "serialize::U256")]
gas_estimate: eth::U256,
#[serde_as(as = "serialize::Hex")]
hash: [u8; 32],
maker_token: eth::H160,
taker_token: eth::H160,
#[serde_as(as = "serialize::U256")]
Expand Down
3 changes: 2 additions & 1 deletion crates/solver/src/interactions/zeroex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ use {
interaction::{EncodedInteraction, Interaction},
zeroex_api::Order,
},
std::sync::Arc,
};

#[derive(Clone, Debug)]
pub struct ZeroExInteraction {
pub order: Order,
pub taker_token_fill_amount: u128,
pub zeroex: IZeroEx,
pub zeroex: Arc<IZeroEx>,
}

impl Interaction for ZeroExInteraction {
Expand Down
21 changes: 11 additions & 10 deletions crates/solver/src/liquidity/zeroex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use {

pub struct ZeroExLiquidity {
pub api: Arc<dyn ZeroExApi>,
pub zeroex: IZeroEx,
pub zeroex: Arc<IZeroEx>,
pub gpv2: GPv2Settlement,
pub allowance_manager: Box<dyn AllowanceManaging>,
}
Expand All @@ -39,7 +39,7 @@ impl ZeroExLiquidity {
let allowance_manager = AllowanceManager::new(web3, gpv2.address());
Self {
api,
zeroex,
zeroex: Arc::new(zeroex),
gpv2,
allowance_manager: Box::new(allowance_manager),
}
Expand Down Expand Up @@ -176,10 +176,11 @@ fn get_useful_orders(order_buckets: OrderBuckets, orders_per_type: usize) -> Vec
filtered_zeroex_orders
}

struct OrderSettlementHandler {
order: Order,
zeroex: IZeroEx,
allowances: Arc<Allowances>,
#[derive(Clone)]
pub struct OrderSettlementHandler {
pub order: Order,
pub zeroex: Arc<IZeroEx>,
pub allowances: Arc<Allowances>,
squadgazzz marked this conversation as resolved.
Show resolved Hide resolved
}

impl SettlementHandling<LimitOrder> for OrderSettlementHandler {
Expand Down Expand Up @@ -355,7 +356,7 @@ pub mod tests {
#[tokio::test]
async fn interaction_encodes_approval_when_insufficient() {
let sell_token = H160::from_low_u64_be(1);
let zeroex = contracts::dummy_contract!(IZeroEx, H160::default());
let zeroex = Arc::new(contracts::dummy_contract!(IZeroEx, H160::default()));
let allowances = Allowances::new(zeroex.address(), hashmap! { sell_token => 99.into() });
let order = Order {
taker_amount: 100,
Expand Down Expand Up @@ -384,7 +385,7 @@ pub mod tests {
ZeroExInteraction {
order,
taker_token_fill_amount: 100,
zeroex
zeroex: zeroex.clone(),
}
.encode(),
],
Expand All @@ -394,7 +395,7 @@ pub mod tests {
#[tokio::test]
async fn interaction_encodes_no_approval_when_sufficient() {
let sell_token = H160::from_low_u64_be(1);
let zeroex = contracts::dummy_contract!(IZeroEx, H160::default());
let zeroex = Arc::new(contracts::dummy_contract!(IZeroEx, H160::default()));
let allowances = Allowances::new(zeroex.address(), hashmap! { sell_token => 100.into() });
let order = Order {
taker_amount: 100,
Expand All @@ -417,7 +418,7 @@ pub mod tests {
[ZeroExInteraction {
order,
taker_token_fill_amount: 100,
zeroex
zeroex: zeroex.clone(),
}
.encode()],
);
Expand Down
9 changes: 0 additions & 9 deletions crates/solvers/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,6 @@ components:
type: string
example: "13.37"

Digest:
description: |
A hex-encoded 32 byte digest.
type: string
example: "0x1e66721bb1bd77d2641c77ea1d61e8abb92bf69c64fcc90c2c6ad518d1b50db1"

NativePrice:
description: |
The price in wei of the native token (Ether on Mainnet for example) to
Expand Down Expand Up @@ -526,7 +520,6 @@ components:
type: object
required:
- kind
- hash
- makerToken
- takerToken
- makerAmount
Expand All @@ -536,8 +529,6 @@ components:
kind:
type: string
enum: [limitOrder]
hash:
$ref: "#/components/schemas/Digest"
Comment on lines -539 to -540
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.

makerToken:
$ref: "#/components/schemas/Token"
takerToken:
Expand Down
Loading