Skip to content

Commit

Permalink
chore: adds utility to build calldata for withdrawal from db (#239)
Browse files Browse the repository at this point in the history
* chore: adds utility to build calldata for withdrawal from db

* clippy

* adds a readme

* reword readme
  • Loading branch information
montekki authored Oct 18, 2023
1 parent 075f70d commit d8f5d31
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 1 deletion.
120 changes: 120 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"bin/withdrawal-finalizer",
"bin/delete-db-content-migration",
"bin/delete-finalization-data-migration",
"bin/prepare-calldata-for-withdrawal",
"ethers-log-decode",
"finalizer",
"client",
Expand All @@ -21,6 +22,7 @@ auto_impl = "1.1.0"
async-trait = "0.1.74"
ethers = { version = "2.0.10", default-features = false }
tokio = "1.33.0"
clap = "4.4.6"
tracing = "0.1"
tracing-subscriber = "0.3"
lru = "0.12.0"
Expand Down
17 changes: 17 additions & 0 deletions bin/prepare-calldata-for-withdrawal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "prepare-calldata-for-withdrawal"
version = "0.1.11"
authors = ["The Matter Labs Team <[email protected]>"]
homepage = "https://zksync.io/"
license = "MIT OR Apache-2.0"
edition = "2021"

[dependencies]
sqlx = { workspace = true, features = ["postgres", "runtime-tokio-rustls"] }
tokio = { workspace = true, features = ["full"] }
client = { workspace = true }
storage = { workspace = true }
bincode = { workspace = true }
hex = { workspace = true }
ethers = { workspace = true }
clap = { workspace = true, features = ["derive"] }
27 changes: 27 additions & 0 deletions bin/prepare-calldata-for-withdrawal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
This is a utility that prepares a calldata for `finalizeWithdrawals` call for a single
withdrawal with a known withdrawal id. Typically you use this calldata when tracing
unsuccessful withdrawals on a service such as `tenderly`.

Suppose you have a case of a single withdrawal being predicted as unfinalizable by
the contract:

```
message: "predicting results for withdrawals: [2069871]"
message: "predicted results for withdrawals: [Result { l_2_block_number: 271910, l_2_message_index: 1, gas: 0, success: false }]"
```

What you want to do is take the same calldata and trace it on `tenderly` to figure
out what is going on.

This utility allows you to connect to your prod database that contains this withdrawal
and by providing the withdrawal id in question it constructs hax-encoded
calldata for you as such (note that you need to set the relevant gas limit for this withdrawal yourself):

```
cargo run -- -d $DATABASE_URL -w 2069871 -g 300000
building finalization calldata for withdrawal with id 2069871
hex payload is
32bfc64d0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000042626000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000493e000000000000000000000000000000000000000000000000000000000000000386c0960f932400084c286cf3e17e7b677ea9583e60a000324000000000000000000000000000000000000000000000000000000174876e80000000000000000000000000000000000000000000000000000000000000000000000000000000009e2b46711cae1b8f60bae9d46df7ce9c8c39ffeccd452182854eef12bba7499377e158aaa61feffd84335d7677ffdaaee40d59453ac23068aa929ccc1c6afce16e3697c7f33c31a9b0f0aeb8542287d0d21e8c4cf82163d0c44c7a98aa11aa111199cc5812543ddceeddd0fc82807646a4899444240db2c0d2f20c3cceb5f51fae4733f281f18ba3ea8775dd62d2fcd84011c8c938f16ea5790fd29a03bf8db891798a1fd9c8fbb818c98cff190daa7cc10b6e5ac9716b4a2649f7c2ebcef227266d7c5983afe44cf15ea8cf565b34c6c31ff0cb4dd744524f7842b942d08770db04e5ee349086985f74b73971ce9dfe76bbed95c84906c5dffd96504e1e5396cac506ecb5465659b3a927143f6d724f91d8d9c4bdb2463aee111d9aa869874db
```

You can then take this calldata and perform tracing on `tenderly`.
45 changes: 45 additions & 0 deletions bin/prepare-calldata-for-withdrawal/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use clap::Parser;
use client::withdrawal_finalizer::codegen::FinalizeWithdrawalsCall;
use ethers::abi::AbiEncode;
use sqlx::postgres::PgPool;

#[derive(Parser, Debug)]
struct Args {
/// id of withdrawal
#[arg(short, long)]
withdrawal_id: u64,

/// database url
#[arg(short, long)]
database_url: String,

/// gas
#[arg(short, long)]
gas: u64,
}

#[tokio::main]
async fn main() {
let args = Args::parse();

println!(
"building finalization calldata for withdrawal with id {}",
args.withdrawal_id
);

let pool = PgPool::connect(&args.database_url).await.unwrap();

let request_finalize_withdrawal =
storage::get_finalize_withdrawal_params(&pool, args.withdrawal_id, args.gas)
.await
.unwrap()
.unwrap();

let finalize_withdrawal_call = FinalizeWithdrawalsCall {
requests: vec![request_finalize_withdrawal],
};

let encoded = finalize_withdrawal_call.encode();

println!("hex payload is\n{}", hex::encode(encoded));
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 43 additions & 1 deletion storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use ethers::types::{Address, H160, H256};
use sqlx::{PgConnection, PgPool};

use chain_events::L2TokenInitEvent;
use client::{zksync_contract::L2ToL1Event, WithdrawalEvent, WithdrawalKey, WithdrawalParams};
use client::{
is_eth, withdrawal_finalizer::codegen::RequestFinalizeWithdrawal, zksync_contract::L2ToL1Event,
WithdrawalEvent, WithdrawalKey, WithdrawalParams,
};

mod error;
mod metrics;
Expand Down Expand Up @@ -807,6 +810,45 @@ pub async fn withdrwals_to_finalize(pool: &PgPool, limit_by: u64) -> Result<Vec<
Ok(data)
}

/// Fetch finalization parameters for some withdrawal
pub async fn get_finalize_withdrawal_params(
pool: &PgPool,
id: u64,
gas: u64,
) -> Result<Option<RequestFinalizeWithdrawal>> {
let res = sqlx::query!(
"
SELECT
finalization_data.l2_block_number,
l1_batch_number,
l2_message_index,
l2_tx_number_in_block,
message,
proof,
withdrawals.token
FROM
finalization_data
JOIN withdrawals ON withdrawals.id = finalization_data.withdrawal_id
WHERE
withdrawal_id = $1
",
id as i64
)
.fetch_optional(pool)
.await?
.map(|r| RequestFinalizeWithdrawal {
l_2_block_number: r.l1_batch_number.into(),
l_2_message_index: r.l2_message_index.into(),
l_2_tx_number_in_block: r.l2_tx_number_in_block as u16,
message: r.message.into(),
merkle_proof: bincode::deserialize(&r.proof).unwrap(),
is_eth: is_eth(Address::from_slice(&r.token)),
gas: gas.into(),
});

Ok(res)
}

/// Set status of a set of withdrawals in `finalization_data` to finalized
pub async fn finalization_data_set_finalized_in_tx(
pool: &PgPool,
Expand Down

0 comments on commit d8f5d31

Please sign in to comment.