Skip to content

Commit

Permalink
Provide module for Vec<u8> to hex string serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
vkgnosis committed May 2, 2022
1 parent 3011d69 commit b26bae8
Show file tree
Hide file tree
Showing 15 changed files with 81 additions and 40 deletions.
51 changes: 51 additions & 0 deletions crates/model/src/bytes_hex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! Serialization of Vec<u8> to 0x prefixed hex string

use serde::{de::Error, Deserialize, Deserializer, Serializer};
use std::borrow::Cow;

pub fn serialize<S, T>(bytes: T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: AsRef<[u8]>,
{
let mut v = vec![0u8; 2 + bytes.as_ref().len() * 2];
v[0] = b'0';
v[1] = b'x';
// Unwrap because only possible error is vector wrong size which cannot happen.
hex::encode_to_slice(bytes, &mut v[2..]).unwrap();
// Unwrap because encoded data is always valid utf8.
serializer.serialize_str(&String::from_utf8(v).unwrap())
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let prefixed_hex_str = Cow::<str>::deserialize(deserializer)?;
let hex_str = prefixed_hex_str
.strip_prefix("0x")
.ok_or_else(|| D::Error::custom("missing '0x' prefix"))?;
hex::decode(hex_str).map_err(D::Error::custom)
}

#[cfg(test)]
mod tests {

#[derive(Debug, serde::Deserialize, serde::Serialize, Eq, PartialEq)]
struct S {
#[serde(with = "super")]
b: Vec<u8>,
}

#[test]
fn json() {
let orig = S { b: vec![0, 1] };
let serialized = serde_json::to_value(&orig).unwrap();
let expected = serde_json::json!({
"b": "0x0001"
});
assert_eq!(serialized, expected);
let deserialized: S = serde_json::from_value(expected).unwrap();
assert_eq!(orig, deserialized);
}
}
1 change: 1 addition & 0 deletions crates/model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

pub mod app_id;
pub mod auction;
pub mod bytes_hex;
pub mod order;
pub mod ratio_as_decimal;
pub mod signature;
Expand Down
4 changes: 2 additions & 2 deletions crates/shared/src/balancer_sor_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use model::u256_decimal;
use num::BigInt;
use reqwest::{Client, IntoUrl, Url};
use serde::{Deserialize, Serialize};
use web3::types::Bytes;

/// Trait for mockable Balancer SOR API.
#[mockall::automock]
Expand Down Expand Up @@ -149,7 +148,8 @@ pub struct Swap {
#[serde(with = "u256_decimal")]
pub amount: U256,
/// Additional user data to pass to the pool.
pub user_data: Bytes,
#[serde(with = "model::bytes_hex")]
pub user_data: Vec<u8>,
}

impl Quote {
Expand Down
5 changes: 2 additions & 3 deletions crates/shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ use std::{
future::Future,
time::{Duration, Instant},
};
use web3::types::Bytes;

pub type Web3Transport = DynTransport;
pub type Web3 = DynWeb3;
Expand All @@ -66,10 +65,10 @@ pub async fn measure_time<T>(future: impl Future<Output = T>, timer: impl FnOnce
}

pub fn debug_bytes(
bytes: &Bytes,
bytes: impl AsRef<[u8]>,
formatter: &mut std::fmt::Formatter,
) -> Result<(), std::fmt::Error> {
formatter.write_fmt(format_args!("0x{}", hex::encode(&bytes.0)))
formatter.write_fmt(format_args!("0x{}", hex::encode(bytes.as_ref())))
}

/// anyhow errors are not clonable natively. This is a workaround that creates a new anyhow error
Expand Down
4 changes: 2 additions & 2 deletions crates/shared/src/oneinch_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! <https://docs.1inch.io/docs/aggregation-protocol/api/swagger>
//! Although there is no documentation about API v4.1, it exists and is identical to v4.0 except it
//! uses EIP 1559 gas prices.
use crate::solver_utils::{deserialize_prefixed_hex, Slippage};
use crate::solver_utils::Slippage;
use anyhow::{ensure, Context, Result};
use cached::{Cached, TimedCache};
use ethcontract::{H160, U256};
Expand Down Expand Up @@ -360,7 +360,7 @@ pub struct ProtocolRouteSegment {
pub struct Transaction {
pub from: H160,
pub to: H160,
#[serde(deserialize_with = "deserialize_prefixed_hex")]
#[serde(with = "model::bytes_hex")]
pub data: Vec<u8>,
#[serde(with = "u256_decimal")]
pub value: U256,
Expand Down
4 changes: 2 additions & 2 deletions crates/shared/src/paraswap_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use serde::{
};
use serde_json::Value;
use thiserror::Error;
use web3::types::Bytes;

const BASE_URL: &str = "https://apiv5.paraswap.io";

Expand Down Expand Up @@ -325,7 +324,8 @@ pub struct TransactionBuilderResponse {
pub value: U256,
/// the calldata for the transaction
#[derivative(Debug(format_with = "debug_bytes"))]
pub data: Bytes,
#[serde(with = "model::bytes_hex")]
pub data: Vec<u8>,
/// the suggested gas price
#[serde(with = "u256_decimal")]
pub gas_price: U256,
Expand Down
11 changes: 0 additions & 11 deletions crates/shared/src/solver_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,3 @@ where
let decimal_str = Cow::<str>::deserialize(deserializer)?;
decimal_str.parse::<f64>().map_err(D::Error::custom)
}

pub fn deserialize_prefixed_hex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let prefixed_hex_str = Cow::<str>::deserialize(deserializer)?;
let hex_str = prefixed_hex_str
.strip_prefix("0x")
.ok_or_else(|| D::Error::custom("hex missing '0x' prefix"))?;
hex::decode(hex_str).map_err(D::Error::custom)
}
3 changes: 1 addition & 2 deletions crates/shared/src/univ3_router_api.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Bindings for an instance of https://github.com/cowprotocol/univ3-api .

use crate::solver_utils::deserialize_prefixed_hex;
use anyhow::{Context, Result};
use model::u256_decimal;
use primitive_types::{H160, U256};
Expand Down Expand Up @@ -32,7 +31,7 @@ pub struct Response {
pub quote: U256,
#[serde(with = "serde_with::rust::display_fromstr")]
pub gas: u64,
#[serde(deserialize_with = "deserialize_prefixed_hex")]
#[serde(with = "model::bytes_hex")]
pub call_data: Vec<u8>,
}

Expand Down
16 changes: 8 additions & 8 deletions crates/shared/src/zeroex_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use reqwest::{Client, IntoUrl, Url};
use serde::Deserialize;
use std::collections::HashSet;
use thiserror::Error;
use web3::types::Bytes;

const ORDERS_MAX_PAGE_SIZE: usize = 1_000;

Expand Down Expand Up @@ -137,7 +136,8 @@ impl Default for OrdersQuery {
pub struct OrderMetadata {
#[derivative(Default(value = "chrono::MIN_DATETIME"))]
pub created_at: DateTime<Utc>,
pub order_hash: Bytes,
#[serde(with = "model::bytes_hex")]
pub order_hash: Vec<u8>,
#[serde(with = "serde_with::rust::display_fromstr")]
pub remaining_fillable_taker_amount: u128,
}
Expand Down Expand Up @@ -261,7 +261,8 @@ pub struct SwapResponse {
pub price: PriceResponse,
pub to: H160,
#[derivative(Debug(format_with = "debug_bytes"))]
pub data: Bytes,
#[serde(with = "model::bytes_hex")]
pub data: Vec<u8>,
#[serde(with = "u256_decimal")]
pub value: U256,
}
Expand Down Expand Up @@ -587,11 +588,10 @@ mod tests {
per_page: 1000,
records: vec![OrderRecord {
metadata: OrderMetadata {
order_hash: Bytes(
order_hash:
hex::decode(
"003427369d4c2a6b0aceeb7b315bb9a6086bc6fc4c887aa51efc73b662c9d127"
).unwrap()
),
).unwrap(),
remaining_fillable_taker_amount: 262467000000000000u128,
created_at: Utc.ymd(2022, 2, 26).and_hms_milli(6, 59, 0, 440)
},
Expand Down Expand Up @@ -646,9 +646,9 @@ mod tests {
estimated_gas: 111000,
},
to: crate::addr!("def1c0ded9bec7f1a1670819833240f027b25eff"),
data: Bytes(hex::decode(
data: hex::decode(
"d9627aa40000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000001206e6c0056936e100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006810e776880c02933d47db1b9fc05908e5386b96869584cd0000000000000000000000001000000000000000000000000000000000000011000000000000000000000000000000000000000000000092415e982f60d431ba"
).unwrap()),
).unwrap(),
value: U256::from_dec_str("0").unwrap(),
}
);
Expand Down
2 changes: 1 addition & 1 deletion crates/solver/src/liquidity/zeroex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl ZeroExLiquidity {
}

let limit_order = LimitOrder {
id: hex::encode(&record.metadata.order_hash.0),
id: hex::encode(&record.metadata.order_hash),
sell_token: record.order.maker_token,
buy_token: record.order.taker_token,
sell_amount,
Expand Down
1 change: 1 addition & 0 deletions crates/solver/src/settlement_access_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ impl AccessListEstimating for TenderlyAccessList {
) -> Result<Vec<Result<AccessList>>> {
Ok(futures::future::join_all(txs.iter().map(|tx| async {
let (from, to, input) = resolve_call_request(tx)?;
let input = input.0;
let block_number = self.tenderly.block_number(&self.network_id).await?;

let request = TenderlyRequest {
Expand Down
7 changes: 4 additions & 3 deletions crates/solver/src/settlement_simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use reqwest::{
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use shared::Web3;
use web3::types::{AccessList, BlockId, Bytes};
use web3::types::{AccessList, BlockId};

const SIMULATE_BATCH_SIZE: usize = 10;

Expand Down Expand Up @@ -169,7 +169,7 @@ pub async fn simulate_before_after_access_list(
network_id,
block_number,
from,
input: transaction.input,
input: transaction.input.0,
to,
generate_access_list: false,
transaction_index: Some(transaction_index),
Expand Down Expand Up @@ -248,7 +248,8 @@ pub struct TenderlyRequest {
pub network_id: String,
pub block_number: u64,
pub from: Address,
pub input: Bytes,
#[serde(with = "model::bytes_hex")]
pub input: Vec<u8>,
pub to: Address,
#[serde(skip_serializing_if = "Option::is_none")]
pub transaction_index: Option<u64>,
Expand Down
2 changes: 1 addition & 1 deletion crates/solver/src/solver/balancer_sor_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl Interaction for BatchSwap {
swap.asset_in_index.into(),
swap.asset_out_index.into(),
swap.amount,
Bytes(swap.user_data.0.clone()),
Bytes(swap.user_data.clone()),
)
})
.collect();
Expand Down
2 changes: 1 addition & 1 deletion crates/solver/src/solver/paraswap_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ fn decimals(token_info: &HashMap<H160, TokenInfo>, token: &H160) -> Result<usize

impl Interaction for TransactionBuilderResponse {
fn encode(&self) -> Vec<EncodedInteraction> {
vec![(self.to, self.value, Bytes(self.data.0.clone()))]
vec![(self.to, self.value, Bytes(self.data.clone()))]
}
}

Expand Down
8 changes: 4 additions & 4 deletions crates/solver/src/solver/zeroex_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl From<ZeroExResponseError> for SettlementError {

impl Interaction for SwapResponse {
fn encode(&self) -> Vec<EncodedInteraction> {
vec![(self.to, self.value, Bytes(self.data.0.clone()))]
vec![(self.to, self.value, Bytes(self.data.clone()))]
}
}

Expand Down Expand Up @@ -269,7 +269,7 @@ mod tests {
estimated_gas: Default::default(),
},
to: shared::addr!("0000000000000000000000000000000000000000"),
data: web3::types::Bytes(hex::decode("00").unwrap()),
data: hex::decode("00").unwrap(),
value: U256::from_dec_str("0").unwrap(),
})
});
Expand Down Expand Up @@ -407,7 +407,7 @@ mod tests {
estimated_gas: Default::default(),
},
to: shared::addr!("0000000000000000000000000000000000000000"),
data: web3::types::Bytes(hex::decode("").unwrap()),
data: hex::decode("").unwrap(),
value: U256::from_dec_str("0").unwrap(),
})
});
Expand Down Expand Up @@ -483,7 +483,7 @@ mod tests {
estimated_gas: Default::default(),
},
to: shared::addr!("0000000000000000000000000000000000000000"),
data: web3::types::Bytes(vec![]),
data: vec![],
value: 0.into(),
})
});
Expand Down

0 comments on commit b26bae8

Please sign in to comment.