Skip to content

Commit

Permalink
resolve priority order based on block number
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongeric committed Aug 16, 2024
1 parent ece59a3 commit 996b485
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 24 deletions.
11 changes: 8 additions & 3 deletions crates/uniswapx-rs/src/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ pub enum Order {
}

impl Order {
pub fn resolve(&self, timestamp: u64, priority_fee: Uint<256, 4>) -> OrderResolution {
pub fn resolve(&self, block_number: u64, timestamp: u64, priority_fee: Uint<256, 4>) -> OrderResolution {
match self {
Order::V2DutchOrder(order) => order.resolve(timestamp),
Order::PriorityOrder(order) => order.resolve(timestamp, priority_fee),
Order::PriorityOrder(order) => order.resolve(block_number, timestamp, priority_fee),
}
}

Expand Down Expand Up @@ -130,6 +130,7 @@ pub enum OrderResolution {
Resolved(ResolvedOrder),
Expired,
Invalid,
NotFillableYet(ResolvedOrder)
}

impl V2DutchOrder {
Expand Down Expand Up @@ -202,7 +203,7 @@ impl PriorityOrder {
PriorityOrder::encode_single(self)
}

pub fn resolve(&self, timestamp: u64, priority_fee: Uint<256, 4>) -> OrderResolution {
pub fn resolve(&self, block_number: u64, timestamp: u64, priority_fee: Uint<256, 4>) -> OrderResolution {
let timestamp = Uint::from(timestamp);

if self.info.deadline.lt(&timestamp) {
Expand All @@ -216,6 +217,10 @@ impl PriorityOrder {
.map(|output| output.scale(priority_fee))
.collect();

if self.cosignerData.auctionTargetBlock.lt(&Uint::from(block_number)) {
return OrderResolution::NotFillableYet(ResolvedOrder { input, outputs });
};

OrderResolution::Resolved(ResolvedOrder { input, outputs })
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/executors/public_1559_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use artemis_core::types::Executor;
use async_trait::async_trait;
use ethers::{providers::Middleware, types::U256};

use crate::strategies::types::SubmitTxToMempoolWithAdvancedProfitCalculation;
use crate::strategies::types::SubmitTxToMempoolWithExecutionMetadata;

/// An executor that sends transactions to the public mempool.
pub struct Public1559Executor<M, N> {
Expand All @@ -24,15 +24,15 @@ impl<M: Middleware, N: Middleware> Public1559Executor<M, N> {
}

#[async_trait]
impl<M, N> Executor<SubmitTxToMempoolWithAdvancedProfitCalculation> for Public1559Executor<M, N>
impl<M, N> Executor<SubmitTxToMempoolWithExecutionMetadata> for Public1559Executor<M, N>
where
M: Middleware,
M::Error: 'static,
N: Middleware,
N::Error: 'static,
{
/// Send a transaction to the mempool.
async fn execute(&self, mut action: SubmitTxToMempoolWithAdvancedProfitCalculation) -> Result<()> {
async fn execute(&self, mut action: SubmitTxToMempoolWithExecutionMetadata) -> Result<()> {
let gas_usage_result = self
.client
.estimate_gas(&action.execution.tx, None)
Expand All @@ -51,7 +51,7 @@ where
if let Some(gas_bid_info) = action.execution.gas_bid_info {
// priority fee at which we'd break even, meaning 100% of profit goes to user in the form of price improvement
// TODO: use gas estimate here
bid_priority_fee = action.profit_calculation.calculate_priority_fee(gas_bid_info.bid_percentage)
bid_priority_fee = action.metadata.calculate_priority_fee(gas_bid_info.bid_percentage)
} else {
bid_priority_fee = Some(U256::from(50));
}
Expand Down
28 changes: 15 additions & 13 deletions src/strategies/priority_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{collectors::{
block_collector::NewBlock,
uniswapx_order_collector::UniswapXOrder,
uniswapx_route_collector::{OrderBatchData, OrderData, PriorityOrderData, RoutedOrder},
}, strategies::types::SubmitTxToMempoolWithAdvancedProfitCalculation};
}, strategies::types::SubmitTxToMempoolWithExecutionMetadata};
use alloy_primitives::Uint;
use anyhow::Result;
use artemis_core::executors::mempool_executor::{GasBidInfo, SubmitTxToMempool};
Expand Down Expand Up @@ -35,14 +35,14 @@ const REACTOR_ADDRESS: &str = "0x000000001Ec5656dcdB24D90DFa42742738De729";
pub const WETH_ADDRESS: &str = "0x4200000000000000000000000000000000000006";

#[derive(Debug, Clone)]
pub struct ProfitCalculation {
pub struct ExecutionMetadata {
// amount of quote token we can get
quote: U256,
// amount of quote token needed to fill the order
amount_out_required: U256,
}

impl ProfitCalculation {
impl ExecutionMetadata {
pub fn new(quote: U256, amount_out_required: U256) -> Self {
Self {
quote,
Expand Down Expand Up @@ -177,7 +177,7 @@ impl<M: Middleware + 'static> UniswapXPriorityFill<M> {
..
} = &event.request;

if let Some(profit) = self.get_profit_calculation(&event) {
if let Some(profit) = self.get_execution_metadata(&event) {
info!(
"Sending trade: num trades: {} routed quote: {}, batch needs: {}",
orders.len(),
Expand All @@ -186,18 +186,19 @@ impl<M: Middleware + 'static> UniswapXPriorityFill<M> {
);

let signed_orders = self.get_signed_orders(orders.clone()).ok()?;
return Some(Action::SubmitPublicTx(SubmitTxToMempoolWithAdvancedProfitCalculation {
return Some(Action::SubmitPublicTx(SubmitTxToMempoolWithExecutionMetadata {
execution: SubmitTxToMempool {
tx: self
.build_fill(self.client.clone(), &self.executor_address, signed_orders, event)
.await
.ok()?,
gas_bid_info: Some(GasBidInfo {
bid_percentage: self.bid_percentage,
// this field is not used for priority orders
total_profit: U256::from(0),
}),
},
profit_calculation: profit,
metadata: profit,
}));
}

Expand Down Expand Up @@ -298,12 +299,12 @@ impl<M: Middleware + 'static> UniswapXPriorityFill<M> {
Ok(())
}

/// We still calculate profit in terms of ETH for priority fee orders
/// The profit of a priority order is calculated a bit differently
/// Rationale:
/// - we have to bid at least the base fee
/// - the priority fee set for the transaction is essentially total_profit_eth - base_fee
/// - at 100% bid_percentage, our priority fee is total_profit_eth and thus gives the maximum amount to the user
fn get_profit_calculation(&self, RoutedOrder { request, route }: &RoutedOrder) -> Option<ProfitCalculation> {
/// - we will always bid the base fee
/// - since we have to provide 1 MP (1/1000th of a bp) for every wei of priority fee
/// - we return the data needed to calculate the maximum MPS of improvement we can offer from our quote and the order specs
fn get_execution_metadata(&self, RoutedOrder { request, route }: &RoutedOrder) -> Option<ExecutionMetadata> {
let quote = U256::from_str_radix(&route.quote, 10).ok()?;
let amount_out_required =
U256::from_str_radix(&request.amount_out_required.to_string(), 10).ok()?;
Expand All @@ -312,18 +313,19 @@ impl<M: Middleware + 'static> UniswapXPriorityFill<M> {
}

return Some({
ProfitCalculation {
ExecutionMetadata {
quote,
amount_out_required,
}
})
}

fn update_order_state(&mut self, order: PriorityOrder, signature: String, order_hash: String) {
let resolved = order.resolve( self.last_block_timestamp + BLOCK_TIME, Uint::from(0));
let resolved = order.resolve( self.last_block_number, self.last_block_timestamp + BLOCK_TIME, Uint::from(0));
let order_status: OrderStatus = match resolved {
OrderResolution::Expired => OrderStatus::Done,
OrderResolution::Invalid => OrderStatus::Done,
OrderResolution::NotFillableYet(resolved_order) => OrderStatus::Open(resolved_order), // TODO: gracefully handle this, currently this will cause a revert if we try to fill too earlty
OrderResolution::Resolved(resolved_order) => OrderStatus::Open(resolved_order),
};

Expand Down
8 changes: 4 additions & 4 deletions src/strategies/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::collectors::{
use artemis_core::executors::mempool_executor::SubmitTxToMempool;
use uniswapx_rs::order::ResolvedOrder;

use super::priority_strategy::ProfitCalculation;
use super::priority_strategy::ExecutionMetadata;

/// Core Event enum for the current strategy.
#[derive(Debug, Clone)]
Expand All @@ -17,16 +17,16 @@ pub enum Event {
}

#[derive(Debug, Clone)]
pub struct SubmitTxToMempoolWithAdvancedProfitCalculation {
pub struct SubmitTxToMempoolWithExecutionMetadata {
pub execution: SubmitTxToMempool,
pub profit_calculation: ProfitCalculation,
pub metadata: ExecutionMetadata,
}

/// Core Action enum for the current strategy.
#[derive(Debug, Clone)]
pub enum Action {
SubmitTx(SubmitTxToMempool),
SubmitPublicTx(SubmitTxToMempoolWithAdvancedProfitCalculation),
SubmitPublicTx(SubmitTxToMempoolWithExecutionMetadata),
}

/// Configuration for variables we need to pass to the strategy.
Expand Down
1 change: 1 addition & 0 deletions src/strategies/uniswapx_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ impl<M: Middleware + 'static> UniswapXUniswapFill<M> {
OrderResolution::Expired => OrderStatus::Done,
OrderResolution::Invalid => OrderStatus::Done,
OrderResolution::Resolved(resolved_order) => OrderStatus::Open(resolved_order),
_ => OrderStatus::Done
};

match order_status {
Expand Down

0 comments on commit 996b485

Please sign in to comment.