Skip to content

Commit af8f6ec

Browse files
refactor(l2): rewrite integration tests (#2681)
**Motivation** <!-- Why does this pull request exist? What are its goals? --> L2 tests were broken since two tests were waiting for funds in L2 without depositing. **Description** - Adds `test_deposit`, `test_transfer`, `test_withdraw`, `test_deploy`, `test_call_with_deposit` functions that are used by all the tests. - The deposits and transfers are now done from an L1 rich wallet to a random L2 wallet. - Adds `L1ToL2TransactionData` struct to the SDK. This struct contains the current L2 data for privileged transactions. - Adds `send_l1_to_l2_transaction` function to the SDK. - Adds `deposit_through_contract_call` function to the SDK (wrapper over the above). --------- Co-authored-by: ilitteri <ilitteri@fi.uba.ar>
1 parent 6f959f5 commit af8f6ec

File tree

3 files changed

+642
-562
lines changed

3 files changed

+642
-562
lines changed

crates/l2/sdk/src/l1_to_l2_tx_data.rs

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use crate::calldata::{self, Value};
2+
use bytes::Bytes;
3+
use ethrex_common::{Address, U256};
4+
use ethrex_rpc::{
5+
clients::{eth::errors::CalldataEncodeError, EthClientError, Overrides},
6+
EthClient,
7+
};
8+
use keccak_hash::H256;
9+
use secp256k1::SecretKey;
10+
11+
pub struct L1ToL2TransactionData {
12+
pub to: Address,
13+
pub recipient: Address,
14+
pub gas_limit: u64,
15+
pub calldata: Bytes,
16+
}
17+
18+
impl L1ToL2TransactionData {
19+
/// Creates a new L1ToL2TransactionData instance.
20+
///
21+
/// # Arguments
22+
///
23+
/// * `to` - The address of the contract to call on L2.
24+
/// * `recipient` - The address of the recipient on L2 that will receive the
25+
/// L1 transaction value.
26+
/// * `gas_limit` - The gas limit for the transaction on L2.
27+
/// * `calldata` - The calldata to send to the contract on L2.
28+
pub fn new(to: Address, recipient: Address, gas_limit: u64, calldata: Bytes) -> Self {
29+
Self {
30+
to,
31+
recipient,
32+
gas_limit,
33+
calldata,
34+
}
35+
}
36+
37+
/// Creates a new `L1ToL2TransactionData` instance for a deposit transaction.
38+
///
39+
/// In deposit transactions, the `to` and the `recipient` are the same, and
40+
/// the `calldata` is empty.
41+
///
42+
/// # Arguments
43+
///
44+
/// * `recipient` - The address of the recipient on L2 that will receive the
45+
/// L1 transaction value (the deposit).
46+
/// * `gas_limit` - The gas limit for the transaction on L2.
47+
pub fn new_deposit_data(recipient: Address, gas_limit: u64) -> Self {
48+
Self {
49+
to: recipient,
50+
recipient,
51+
gas_limit,
52+
calldata: Bytes::from_static(b""),
53+
}
54+
}
55+
56+
/// Encodes the `L1ToL2TransactionData` into a calldata.
57+
pub fn to_calldata(&self) -> Result<Vec<u8>, CalldataEncodeError> {
58+
let values = vec![Value::Tuple(vec![
59+
Value::Address(self.to),
60+
Value::Address(self.recipient),
61+
Value::Uint(U256::from(self.gas_limit)),
62+
Value::Bytes(self.calldata.clone()),
63+
])];
64+
calldata::encode_calldata("deposit((address,address,uint256,bytes))", &values)
65+
}
66+
}
67+
68+
/// This function is used to send a transaction on L2 from L1 using the `CommonBridge` contract.
69+
///
70+
/// # Arguments
71+
///
72+
/// * `l1_from` - The address of the sender on L1.
73+
/// * `l1_value` - The value to send from L1.
74+
/// * `l1_gas_limit` - The gas limit for the transaction on L1.
75+
/// * `l1_to_l2_tx_data` - The data for the transaction on L2.
76+
/// * `sender_private_key` - The private key of the sender on L1.
77+
/// * `bridge_address` - The address of the `CommonBridge` contract.
78+
/// * `eth_client` - The Ethereum client to use.
79+
#[allow(clippy::too_many_arguments)]
80+
pub async fn send_l1_to_l2_tx(
81+
l1_from: Address,
82+
l1_value: Option<impl Into<U256>>,
83+
l1_gas_limit: Option<u64>,
84+
l1_to_l2_tx_data: L1ToL2TransactionData,
85+
sender_private_key: &SecretKey,
86+
bridge_address: Address,
87+
eth_client: &EthClient,
88+
) -> Result<H256, EthClientError> {
89+
let l1_calldata = l1_to_l2_tx_data.to_calldata()?;
90+
91+
let l1_gas_price = eth_client.get_gas_price().await?.try_into().map_err(|_| {
92+
EthClientError::InternalError("Failed to convert gas_price to a u64".to_owned())
93+
})?;
94+
95+
let l1_tx_overrides = Overrides {
96+
value: l1_value.map(Into::into),
97+
from: Some(l1_from),
98+
gas_limit: l1_gas_limit.or(Some(21000 * 5)),
99+
max_fee_per_gas: Some(l1_gas_price),
100+
max_priority_fee_per_gas: Some(l1_gas_price),
101+
..Overrides::default()
102+
};
103+
104+
let l1_to_l2_tx = eth_client
105+
.build_eip1559_transaction(bridge_address, l1_from, l1_calldata.into(), l1_tx_overrides)
106+
.await?;
107+
108+
eth_client
109+
.send_eip1559_transaction(&l1_to_l2_tx, sender_private_key)
110+
.await
111+
}

crates/l2/sdk/src/sdk.rs

+30-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ use ethrex_rpc::types::receipt::RpcReceipt;
1010
use keccak_hash::keccak;
1111
use secp256k1::SecretKey;
1212
use serde::{Deserialize, Deserializer, Serialize, Serializer};
13+
1314
pub mod calldata;
15+
pub mod l1_to_l2_tx_data;
1416
pub mod merkle_tree;
1517

18+
pub use l1_to_l2_tx_data::{send_l1_to_l2_tx, L1ToL2TransactionData};
19+
1620
// 0x554a14cd047c485b3ac3edbd9fbb373d6f84ad3f
1721
pub const DEFAULT_BRIDGE_ADDRESS: Address = H160([
1822
0x55, 0x4a, 0x14, 0xcd, 0x04, 0x7c, 0x48, 0x5b, 0x3a, 0xc3, 0xed, 0xbd, 0x9f, 0xbb, 0x37, 0x3d,
@@ -70,7 +74,7 @@ pub async fn transfer(
7074
amount: U256,
7175
from: Address,
7276
to: Address,
73-
private_key: SecretKey,
77+
private_key: &SecretKey,
7478
client: &EthClient,
7579
) -> Result<H256, EthClientError> {
7680
println!(
@@ -105,13 +109,13 @@ pub async fn transfer(
105109
tx_generic.from = from;
106110
let gas_limit = client.estimate_gas(tx_generic).await?;
107111
tx.gas_limit = gas_limit;
108-
client.send_eip1559_transaction(&tx, &private_key).await
112+
client.send_eip1559_transaction(&tx, private_key).await
109113
}
110114

111-
pub async fn deposit(
115+
pub async fn deposit_through_transfer(
112116
amount: U256,
113117
from: Address,
114-
from_pk: SecretKey,
118+
from_pk: &SecretKey,
115119
eth_client: &EthClient,
116120
) -> Result<H256, EthClientError> {
117121
println!("Depositing {amount} from {from:#x} to bridge");
@@ -125,6 +129,28 @@ pub async fn deposit(
125129
.await
126130
}
127131

132+
pub async fn deposit_through_contract_call(
133+
amount: impl Into<U256>,
134+
to: Address,
135+
l1_gas_limit: u64,
136+
l2_gas_limit: u64,
137+
depositor_private_key: &SecretKey,
138+
bridge_address: Address,
139+
eth_client: &EthClient,
140+
) -> Result<H256, EthClientError> {
141+
let l1_from = get_address_from_secret_key(depositor_private_key)?;
142+
send_l1_to_l2_tx(
143+
l1_from,
144+
Some(amount),
145+
Some(l1_gas_limit),
146+
L1ToL2TransactionData::new_deposit_data(to, l2_gas_limit),
147+
depositor_private_key,
148+
bridge_address,
149+
eth_client,
150+
)
151+
.await
152+
}
153+
128154
pub async fn withdraw(
129155
amount: U256,
130156
from: Address,

0 commit comments

Comments
 (0)