From 74a1271c344e057a81870569216b803b832f676c Mon Sep 17 00:00:00 2001 From: Felix Leupold Date: Fri, 26 Jul 2024 11:56:49 +0200 Subject: [PATCH] Deny lint.cast_possible_wrap in the whole codebase (#2834) # Description Cf. discussion in #2828 Casting uXX into their corresponding iXX is dangerous as it can lead to silent overflow with very weird outcomes. # Changes - [x] Adds a workspace specific lint rule set and imports it into all subspaces - [x] Adds `cast_possible_wrap=deny` to catch all occurrences where we do these unsafe conversions Up for discussion if other `as` lints (e.g. `cast_lossless/cast_possible_truncation/cast_precision_loss/cast_sign_loss`) or even `clippy::as_conversions` as a whole should be denied. ## How to test Clippy --- Cargo.toml | 3 +++ crates/alerter/Cargo.toml | 3 +++ crates/app-data-hash/Cargo.toml | 3 +++ crates/app-data/Cargo.toml | 3 +++ crates/autopilot/Cargo.toml | 3 +++ .../src/database/ethflow_events/event_storing.rs | 4 ++-- crates/autopilot/src/database/events.rs | 4 ++-- crates/autopilot/src/shadow.rs | 4 +++- crates/autopilot/src/solvable_orders.rs | 6 +++--- crates/bytes-hex/Cargo.toml | 3 +++ crates/contracts/Cargo.toml | 3 +++ crates/cow-amm/Cargo.toml | 3 +++ crates/database/Cargo.toml | 3 +++ crates/database/src/ethflow_orders.rs | 2 +- crates/database/src/events.rs | 9 +++++---- crates/database/src/settlements.rs | 14 ++++++++++---- crates/driver/Cargo.toml | 3 +++ crates/e2e/Cargo.toml | 3 +++ crates/ethrpc/Cargo.toml | 3 +++ crates/model/Cargo.toml | 3 +++ crates/number/Cargo.toml | 3 +++ crates/observe/Cargo.toml | 3 +++ crates/order-validation/Cargo.toml | 3 +++ crates/orderbook/Cargo.toml | 3 +++ crates/orderbook/src/database/orders.rs | 4 ++-- crates/rate-limit/Cargo.toml | 3 +++ crates/refunder/Cargo.toml | 3 +++ crates/refunder/src/lib.rs | 2 +- crates/s3/Cargo.toml | 3 +++ crates/shared/Cargo.toml | 3 +++ crates/shared/src/maintenance.rs | 8 ++++++-- .../src/price_estimation/native_price_cache.rs | 4 ++-- .../src/sources/balancer_v2/swap/stable_math.rs | 6 ++++-- crates/shared/src/zeroex_api.rs | 4 +++- crates/solver/Cargo.toml | 3 +++ crates/solvers-dto/Cargo.toml | 3 +++ crates/solvers/Cargo.toml | 3 +++ crates/testlib/Cargo.toml | 3 +++ 38 files changed, 119 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 51a31c72a8..eea3c60994 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,3 +54,6 @@ tracing-subscriber = "0.3.18" url = "2.5.0" warp = { git = 'https://github.com/cowprotocol/warp.git', rev = "586244e", default-features = false } web3 = { version = "0.19.0", default-features = false } + +[workspace.lints] +clippy.cast_possible_wrap = "deny" diff --git a/crates/alerter/Cargo.toml b/crates/alerter/Cargo.toml index be7e392727..ca5cbbd13a 100644 --- a/crates/alerter/Cargo.toml +++ b/crates/alerter/Cargo.toml @@ -24,3 +24,6 @@ tracing = { workspace = true } tracing-subscriber = { workspace = true } url = { workspace = true } warp = { workspace = true } + +[lints] +workspace = true diff --git a/crates/app-data-hash/Cargo.toml b/crates/app-data-hash/Cargo.toml index a995b5fb0d..33c032e838 100644 --- a/crates/app-data-hash/Cargo.toml +++ b/crates/app-data-hash/Cargo.toml @@ -8,3 +8,6 @@ license = "MIT OR Apache-2.0" [dependencies] hex-literal = { workspace = true } tiny-keccak = { version = "2.0.2", features = ["keccak"] } + +[lints] +workspace = true diff --git a/crates/app-data/Cargo.toml b/crates/app-data/Cargo.toml index 2c9a670a42..7e8eb86926 100644 --- a/crates/app-data/Cargo.toml +++ b/crates/app-data/Cargo.toml @@ -20,3 +20,6 @@ ethcontract = { workspace = true } [features] test_helpers = [] + +[lints] +workspace = true diff --git a/crates/autopilot/Cargo.toml b/crates/autopilot/Cargo.toml index a0dfe1d506..d604acf173 100644 --- a/crates/autopilot/Cargo.toml +++ b/crates/autopilot/Cargo.toml @@ -64,3 +64,6 @@ web3 = { workspace = true } mockall = { workspace = true } testlib = { path = "../testlib" } tokio = { workspace = true, features = ["test-util"] } + +[lints] +workspace = true diff --git a/crates/autopilot/src/database/ethflow_events/event_storing.rs b/crates/autopilot/src/database/ethflow_events/event_storing.rs index 1a65875ccd..9bf284a8cd 100644 --- a/crates/autopilot/src/database/ethflow_events/event_storing.rs +++ b/crates/autopilot/src/database/ethflow_events/event_storing.rs @@ -71,8 +71,8 @@ impl EventStoring for Postgres { let mut ex = self.pool.begin().await?; database::ethflow_orders::delete_refunds( &mut ex, - *range.start() as i64, - *range.end() as i64, + i64::try_from(*range.start()).unwrap_or(i64::MAX), + i64::try_from(*range.end()).unwrap_or(i64::MAX), ) .await?; database::ethflow_orders::insert_refund_tx_hashes(&mut ex, &refunds).await?; diff --git a/crates/autopilot/src/database/events.rs b/crates/autopilot/src/database/events.rs index 719894c0c5..63647f092d 100644 --- a/crates/autopilot/src/database/events.rs +++ b/crates/autopilot/src/database/events.rs @@ -93,8 +93,8 @@ pub async fn replace_events( pub fn meta_to_event_index(meta: &EventMetadata) -> EventIndex { EventIndex { - block_number: meta.block_number as i64, - log_index: meta.log_index as i64, + block_number: i64::try_from(meta.block_number).unwrap_or(i64::MAX), + log_index: i64::try_from(meta.log_index).unwrap_or(i64::MAX), } } diff --git a/crates/autopilot/src/shadow.rs b/crates/autopilot/src/shadow.rs index 5fda4245e9..fa32a134f1 100644 --- a/crates/autopilot/src/shadow.rs +++ b/crates/autopilot/src/shadow.rs @@ -113,7 +113,9 @@ impl RunLoop { async fn single_run(&self, id: domain::auction::Id, auction: &domain::Auction) { tracing::info!("solving"); Metrics::get().auction.set(id); - Metrics::get().orders.set(auction.orders.len() as _); + Metrics::get() + .orders + .set(i64::try_from(auction.orders.len()).unwrap_or(i64::MAX)); let mut participants = self.competition(id, auction).await; diff --git a/crates/autopilot/src/solvable_orders.rs b/crates/autopilot/src/solvable_orders.rs index 10c0ad6550..5821db810e 100644 --- a/crates/autopilot/src/solvable_orders.rs +++ b/crates/autopilot/src/solvable_orders.rs @@ -673,7 +673,7 @@ impl OrderFilterCounter { metrics .auction_candidate_orders .with_label_values(&[class]) - .set(count as _); + .set(i64::try_from(count).unwrap_or(i64::MAX)); } Self { @@ -724,14 +724,14 @@ impl OrderFilterCounter { self.metrics .auction_solvable_orders .with_label_values(&[class]) - .set(count as _); + .set(i64::try_from(count).unwrap_or(i64::MAX)); } for (reason, count) in self.counts { self.metrics .auction_filtered_orders .with_label_values(&[reason]) - .set(count as _); + .set(i64::try_from(count).unwrap_or(i64::MAX)); } removed diff --git a/crates/bytes-hex/Cargo.toml b/crates/bytes-hex/Cargo.toml index fddb6bd654..c407657776 100644 --- a/crates/bytes-hex/Cargo.toml +++ b/crates/bytes-hex/Cargo.toml @@ -12,3 +12,6 @@ serde = { workspace = true } serde_json = { workspace = true } serde_with = { workspace = true } hex = { workspace = true } + +[lints] +workspace = true diff --git a/crates/contracts/Cargo.toml b/crates/contracts/Cargo.toml index dc9c11886c..f50c7760bb 100644 --- a/crates/contracts/Cargo.toml +++ b/crates/contracts/Cargo.toml @@ -36,3 +36,6 @@ tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"], optio [build-dependencies] ethcontract = { workspace = true } ethcontract-generate = { workspace = true } + +[lints] +workspace = true diff --git a/crates/cow-amm/Cargo.toml b/crates/cow-amm/Cargo.toml index a8b4456884..e4a949b6b5 100644 --- a/crates/cow-amm/Cargo.toml +++ b/crates/cow-amm/Cargo.toml @@ -17,3 +17,6 @@ tokio = { workspace = true, features = [] } tracing = { workspace = true } hex = { workspace = true } hex-literal = { workspace = true } + +[lints] +workspace = true diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 6ad32d9125..86efbc346c 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -17,3 +17,6 @@ strum = { workspace = true } [dev-dependencies] hex-literal = { workspace = true } tokio = { workspace = true, features = ["macros"] } + +[lints] +workspace = true diff --git a/crates/database/src/ethflow_orders.rs b/crates/database/src/ethflow_orders.rs index 81d271c882..b15bc34db9 100644 --- a/crates/database/src/ethflow_orders.rs +++ b/crates/database/src/ethflow_orders.rs @@ -103,7 +103,7 @@ pub async fn insert_refund_tx_hash( ex.execute( sqlx::query(QUERY) .bind(refund.order_uid) - .bind(refund.block_number as i64) + .bind(i64::try_from(refund.block_number).unwrap_or(i64::MAX)) .bind(refund.tx_hash), ) .await?; diff --git a/crates/database/src/events.rs b/crates/database/src/events.rs index 66a65ac617..19caa006fc 100644 --- a/crates/database/src/events.rs +++ b/crates/database/src/events.rs @@ -56,20 +56,21 @@ pub async fn delete( ex: &mut PgTransaction<'_>, delete_from_block_number: u64, ) -> Result<(), sqlx::Error> { + let delete_from_block_number = i64::try_from(delete_from_block_number).unwrap_or(i64::MAX); const QUERY_INVALIDATION: &str = "DELETE FROM invalidations WHERE block_number >= $1;"; - ex.execute(sqlx::query(QUERY_INVALIDATION).bind(delete_from_block_number as i64)) + ex.execute(sqlx::query(QUERY_INVALIDATION).bind(delete_from_block_number)) .await?; const QUERY_TRADE: &str = "DELETE FROM trades WHERE block_number >= $1;"; - ex.execute(sqlx::query(QUERY_TRADE).bind(delete_from_block_number as i64)) + ex.execute(sqlx::query(QUERY_TRADE).bind(delete_from_block_number)) .await?; const QUERY_SETTLEMENTS: &str = "DELETE FROM settlements WHERE block_number >= $1;"; - ex.execute(sqlx::query(QUERY_SETTLEMENTS).bind(delete_from_block_number as i64)) + ex.execute(sqlx::query(QUERY_SETTLEMENTS).bind(delete_from_block_number)) .await?; const QUERY_PRESIGNATURES: &str = "DELETE FROM presignature_events WHERE block_number >= $1;"; - ex.execute(sqlx::query(QUERY_PRESIGNATURES).bind(delete_from_block_number as i64)) + ex.execute(sqlx::query(QUERY_PRESIGNATURES).bind(delete_from_block_number)) .await?; Ok(()) diff --git a/crates/database/src/settlements.rs b/crates/database/src/settlements.rs index 43c63d07c1..4d4a89d43b 100644 --- a/crates/database/src/settlements.rs +++ b/crates/database/src/settlements.rs @@ -95,12 +95,18 @@ pub async fn delete( ) -> Result<(), sqlx::Error> { const QUERY_OBSERVATIONS: &str = "DELETE FROM settlement_observations WHERE block_number >= $1;"; - ex.execute(sqlx::query(QUERY_OBSERVATIONS).bind(delete_from_block_number as i64)) - .await?; + ex.execute( + sqlx::query(QUERY_OBSERVATIONS) + .bind(i64::try_from(delete_from_block_number).unwrap_or(i64::MAX)), + ) + .await?; const QUERY_ORDER_EXECUTIONS: &str = "DELETE FROM order_execution WHERE block_number >= $1;"; - ex.execute(sqlx::query(QUERY_ORDER_EXECUTIONS).bind(delete_from_block_number as i64)) - .await?; + ex.execute( + sqlx::query(QUERY_ORDER_EXECUTIONS) + .bind(i64::try_from(delete_from_block_number).unwrap_or(i64::MAX)), + ) + .await?; Ok(()) } diff --git a/crates/driver/Cargo.toml b/crates/driver/Cargo.toml index 5d60b5a471..0b491dd86b 100644 --- a/crates/driver/Cargo.toml +++ b/crates/driver/Cargo.toml @@ -80,3 +80,6 @@ mockall = { workspace = true } solvers-dto = { path = "../solvers-dto" } tokio = { workspace = true, features = ["test-util", "process"] } tempfile = { workspace = true } + +[lints] +workspace = true diff --git a/crates/e2e/Cargo.toml b/crates/e2e/Cargo.toml index fb16affecb..381eb4297a 100644 --- a/crates/e2e/Cargo.toml +++ b/crates/e2e/Cargo.toml @@ -48,3 +48,6 @@ app-data-hash = { path = "../app-data-hash" } futures = { workspace = true } rand = { workspace = true } refunder = { path = "../refunder" } + +[lints] +workspace = true diff --git a/crates/ethrpc/Cargo.toml b/crates/ethrpc/Cargo.toml index 6ac4df07f3..1d26464d9b 100644 --- a/crates/ethrpc/Cargo.toml +++ b/crates/ethrpc/Cargo.toml @@ -39,3 +39,6 @@ itertools = { workspace = true } [dev-dependencies] maplit = { workspace = true } testlib = { path = "../testlib" } + +[lints] +workspace = true diff --git a/crates/model/Cargo.toml b/crates/model/Cargo.toml index ae220f93e9..d3ef8935df 100644 --- a/crates/model/Cargo.toml +++ b/crates/model/Cargo.toml @@ -35,3 +35,6 @@ maplit = { workspace = true } [features] e2e = [] + +[lints] +workspace = true diff --git a/crates/number/Cargo.toml b/crates/number/Cargo.toml index b23587ca86..66a2f51b16 100644 --- a/crates/number/Cargo.toml +++ b/crates/number/Cargo.toml @@ -12,3 +12,6 @@ num = { workspace = true } primitive-types = { workspace = true } serde_with = { workspace = true } serde = { workspace = true } + +[lints] +workspace = true diff --git a/crates/observe/Cargo.toml b/crates/observe/Cargo.toml index 47b7853fb9..e4db7decc4 100644 --- a/crates/observe/Cargo.toml +++ b/crates/observe/Cargo.toml @@ -16,3 +16,6 @@ time = { workspace = true } tokio = { workspace = true, features = [] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter", "fmt", "time"] } + +[lints] +workspace = true diff --git a/crates/order-validation/Cargo.toml b/crates/order-validation/Cargo.toml index 984ec470f6..fd7ba28fd9 100644 --- a/crates/order-validation/Cargo.toml +++ b/crates/order-validation/Cargo.toml @@ -11,3 +11,6 @@ contracts = { path = "../contracts" } ethcontract = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } + +[lints] +workspace = true diff --git a/crates/orderbook/Cargo.toml b/crates/orderbook/Cargo.toml index 1227840df0..70a9847db6 100644 --- a/crates/orderbook/Cargo.toml +++ b/crates/orderbook/Cargo.toml @@ -65,3 +65,6 @@ tokio = { workspace = true, features = ["test-util"] } [build-dependencies] anyhow = { workspace = true } vergen = { version = "8", features = ["git", "gitcl"] } + +[lints] +workspace = true diff --git a/crates/orderbook/src/database/orders.rs b/crates/orderbook/src/database/orders.rs index 00cf02a1d1..0831e360d7 100644 --- a/crates/orderbook/src/database/orders.rs +++ b/crates/orderbook/src/database/orders.rs @@ -346,8 +346,8 @@ impl OrderStoring for Postgres { database::orders::user_orders( &mut ex, &ByteArray(owner.0), - offset as i64, - limit.map(|l| l as i64), + i64::try_from(offset).unwrap_or(i64::MAX), + limit.map(|l| i64::try_from(l).unwrap_or(i64::MAX)), ) .map(|result| match result { Ok(order) => full_order_into_model_order(order), diff --git a/crates/rate-limit/Cargo.toml b/crates/rate-limit/Cargo.toml index 13748f8268..864e794c44 100644 --- a/crates/rate-limit/Cargo.toml +++ b/crates/rate-limit/Cargo.toml @@ -16,3 +16,6 @@ reqwest = { workspace = true, features = ["json"] } thiserror = { workspace = true } tokio = { workspace = true, features = [] } tracing = { workspace = true } + +[lints] +workspace = true diff --git a/crates/refunder/Cargo.toml b/crates/refunder/Cargo.toml index 2813e1f8ba..7276ef9b36 100644 --- a/crates/refunder/Cargo.toml +++ b/crates/refunder/Cargo.toml @@ -30,3 +30,6 @@ tokio = { workspace = true, features = ["macros", "time", "rt-multi-thread"] } tracing = { workspace = true } tracing-subscriber = { workspace = true } url = { workspace = true } + +[lints] +workspace = true diff --git a/crates/refunder/src/lib.rs b/crates/refunder/src/lib.rs index 63f92ee7d7..43f52ab924 100644 --- a/crates/refunder/src/lib.rs +++ b/crates/refunder/src/lib.rs @@ -62,7 +62,7 @@ pub async fn run(args: arguments::Arguments) { pg_pool, web3, ethflow_contract, - args.min_validity_duration.as_secs() as i64, + i64::try_from(args.min_validity_duration.as_secs()).unwrap_or(i64::MAX), args.min_slippage_bps, refunder_account, ); diff --git a/crates/s3/Cargo.toml b/crates/s3/Cargo.toml index 79f1dba7a2..8a02095cf3 100644 --- a/crates/s3/Cargo.toml +++ b/crates/s3/Cargo.toml @@ -16,3 +16,6 @@ serde_json = { workspace = true } [dev-dependencies] chrono = { workspace = true, features = ["clock"] } tokio = { workspace = true, features = ["test-util", "macros"] } + +[lints] +workspace = true diff --git a/crates/shared/Cargo.toml b/crates/shared/Cargo.toml index de82138f11..16c687c686 100644 --- a/crates/shared/Cargo.toml +++ b/crates/shared/Cargo.toml @@ -68,3 +68,6 @@ regex = { workspace = true } testlib = { path = "../testlib" } app-data = { path = "../app-data", features = ["test_helpers"] } tokio = { workspace = true, features = ["rt-multi-thread"] } + +[lints] +workspace = true diff --git a/crates/shared/src/maintenance.rs b/crates/shared/src/maintenance.rs index 1af2210a15..f138e4ba1a 100644 --- a/crates/shared/src/maintenance.rs +++ b/crates/shared/src/maintenance.rs @@ -99,7 +99,9 @@ impl ServiceMaintenance { "running maintenance", ); - self.metrics.last_seen_block.set(block.number as _); + self.metrics + .last_seen_block + .set(i64::try_from(block.number).unwrap_or(i64::MAX)); if let Err(err) = self .run_maintenance() @@ -115,7 +117,9 @@ impl ServiceMaintenance { continue; } - self.metrics.last_updated_block.set(block.number as _); + self.metrics + .last_updated_block + .set(i64::try_from(block.number).unwrap_or(i64::MAX)); self.metrics .runs .with_label_values(&["success", self.name()]) diff --git a/crates/shared/src/price_estimation/native_price_cache.rs b/crates/shared/src/price_estimation/native_price_cache.rs index 79dfbc99dd..b652fea746 100644 --- a/crates/shared/src/price_estimation/native_price_cache.rs +++ b/crates/shared/src/price_estimation/native_price_cache.rs @@ -192,14 +192,14 @@ impl UpdateTask { let metrics = Metrics::get(); metrics .native_price_cache_size - .set(inner.cache.lock().unwrap().len() as i64); + .set(i64::try_from(inner.cache.lock().unwrap().len()).unwrap_or(i64::MAX)); let max_age = inner.max_age.saturating_sub(self.prefetch_time); let mut outdated_entries = inner.sorted_tokens_to_update(max_age, Instant::now()); metrics .native_price_cache_outdated_entries - .set(outdated_entries.len() as i64); + .set(i64::try_from(outdated_entries.len()).unwrap_or(i64::MAX)); outdated_entries.truncate(self.update_size.unwrap_or(usize::MAX)); diff --git a/crates/shared/src/sources/balancer_v2/swap/stable_math.rs b/crates/shared/src/sources/balancer_v2/swap/stable_math.rs index d1e60c4ec9..bedd679b78 100644 --- a/crates/shared/src/sources/balancer_v2/swap/stable_math.rs +++ b/crates/shared/src/sources/balancer_v2/swap/stable_math.rs @@ -292,8 +292,10 @@ mod tests { } } let b = (invariant / (amplification_parameter * num_tokens)) + sum - invariant; - let c = (invariant.powi(num_tokens_usize as i32 + 1) * -1.) - / (amplification_parameter * num_tokens.powi(num_tokens_usize as i32 + 1) * prod); + let c = (invariant.powi(i32::try_from(num_tokens_usize).unwrap_or(i32::MAX) + 1) * -1.) + / (amplification_parameter + * num_tokens.powi(i32::try_from(num_tokens_usize).unwrap_or(i32::MAX) + 1) + * prod); let x = b.powi(2) - (c * 4.); let root_x = x.powf(0.5); let neg_b = b * -1.; diff --git a/crates/shared/src/zeroex_api.rs b/crates/shared/src/zeroex_api.rs index 2522de7719..ce0d5826ae 100644 --- a/crates/shared/src/zeroex_api.rs +++ b/crates/shared/src/zeroex_api.rs @@ -366,7 +366,9 @@ fn retain_valid_orders(orders: &mut Vec) { let mut included_orders = HashSet::new(); let now = chrono::offset::Utc::now(); orders.retain(|order| { - let expiry = Utc.timestamp_opt(order.order().expiry as i64, 0).unwrap(); + let expiry = Utc + .timestamp_opt(i64::try_from(order.order().expiry).unwrap_or(i64::MAX), 0) + .unwrap(); // only keep orders which are still valid and unique expiry > now && included_orders.insert(order.metadata().order_hash.clone()) diff --git a/crates/solver/Cargo.toml b/crates/solver/Cargo.toml index 75a0ab4d71..cbb488c755 100644 --- a/crates/solver/Cargo.toml +++ b/crates/solver/Cargo.toml @@ -58,3 +58,6 @@ ethcontract-mock = { workspace = true } tokio = { workspace = true, features = ["test-util"] } tracing-subscriber = { workspace = true } testlib = { path = "../testlib" } + +[lints] +workspace = true diff --git a/crates/solvers-dto/Cargo.toml b/crates/solvers-dto/Cargo.toml index e996db1480..90389bda1c 100644 --- a/crates/solvers-dto/Cargo.toml +++ b/crates/solvers-dto/Cargo.toml @@ -15,3 +15,6 @@ number = { path = "../number" } serde = { workspace = true } serde_with = { workspace = true } web3 = { workspace = true } + +[lints] +workspace = true diff --git a/crates/solvers/Cargo.toml b/crates/solvers/Cargo.toml index 96ec7bf51c..531ef55b3a 100644 --- a/crates/solvers/Cargo.toml +++ b/crates/solvers/Cargo.toml @@ -55,3 +55,6 @@ tracing = { workspace = true } tempfile = { workspace = true } hex-literal = { workspace = true } ethcontract = { workspace = true } + +[lints] +workspace = true diff --git a/crates/testlib/Cargo.toml b/crates/testlib/Cargo.toml index 78730c2352..200b31571c 100644 --- a/crates/testlib/Cargo.toml +++ b/crates/testlib/Cargo.toml @@ -9,3 +9,6 @@ license = "MIT OR Apache-2.0" ethcontract = { workspace = true } ethcontract-mock = { workspace = true } hex-literal = { workspace = true } + +[lints] +workspace = true