Skip to content

Commit ad723e5

Browse files
tomip01ilitteri
andauthored
feat(sdk): add function to withdraw erc20 tokens (#162)
**Motivation** We want to add support for the withdraw of erc20 tokens in the sdk. **Description** * Added the `withdraw_erc20` and the `claim_erc20withdraw` function in `sdk/src/l2/withdraw.rs` to handle ERC20 token withdrawals. * Introduced `L2_WITHDRAW_SIGNATURE_ERC20` and `CLAIM_WITHDRAWAL_ERC20_SIGNATURE` in `sdk/src/l2/constants.rs` to define the signature for ERC20 withdrawal calldata encoding. Closes #157 --------- Co-authored-by: Ivan Litteri <[email protected]>
1 parent 7d77486 commit ad723e5

File tree

3 files changed

+99
-6
lines changed

3 files changed

+99
-6
lines changed

cli/src/commands/l2.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,18 +364,19 @@ impl Command {
364364
private_key,
365365
rpc_url,
366366
} => {
367+
let from = get_address_from_secret_key(&private_key)?;
368+
369+
let client = EthClient::new(&rpc_url)?;
370+
367371
if explorer_url {
368372
todo!("Display transaction URL in the explorer")
369373
}
370374

371375
if token_address.is_some() {
376+
// withdraw_erc20(..)
372377
todo!("Handle ERC20 withdrawals")
373378
}
374379

375-
let from = get_address_from_secret_key(&private_key)?;
376-
377-
let client = EthClient::new(&rpc_url)?;
378-
379380
let tx_hash = withdraw(amount, from, private_key, &client, nonce).await?;
380381

381382
println!("Withdrawal sent: {tx_hash:#x}");

sdk/src/l2/constants.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@ pub const COMMON_BRIDGE_L2_ADDRESS: Address = H160([
1111

1212
pub const L2_WITHDRAW_SIGNATURE: &str = "withdraw(address)";
1313

14+
pub const L2_WITHDRAW_SIGNATURE_ERC20: &str = "withdrawERC20(address,address,address,uint256)";
15+
16+
pub const CLAIM_WITHDRAWAL_ERC20_SIGNATURE: &str =
17+
"claimWithdrawalERC20(address,address,uint256,uint256,uint256,bytes32[])";
18+
1419
// Function Selectors

sdk/src/l2/withdraw.rs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
use crate::{
22
calldata::{Value, encode_calldata},
3-
client::{EthClient, EthClientError, Overrides, eth::L1MessageProof},
3+
client::{
4+
EthClient, EthClientError, Overrides,
5+
eth::{L1MessageProof, get_address_from_secret_key},
6+
},
47
l2::{
5-
constants::{COMMON_BRIDGE_L2_ADDRESS, L2_WITHDRAW_SIGNATURE},
8+
constants::{
9+
CLAIM_WITHDRAWAL_ERC20_SIGNATURE, COMMON_BRIDGE_L2_ADDRESS, L2_WITHDRAW_SIGNATURE,
10+
L2_WITHDRAW_SIGNATURE_ERC20,
11+
},
612
merkle_tree::merkle_proof,
713
},
814
};
@@ -42,6 +48,36 @@ pub async fn withdraw(
4248
.await
4349
}
4450

51+
pub async fn withdraw_erc20(
52+
amount: U256,
53+
from: Address,
54+
from_pk: SecretKey,
55+
token_l1: Address,
56+
token_l2: Address,
57+
l2_client: &EthClient,
58+
) -> Result<H256, EthClientError> {
59+
let data = [
60+
Value::Address(token_l1),
61+
Value::Address(token_l2),
62+
Value::Address(from),
63+
Value::Uint(amount),
64+
];
65+
let withdraw_data = encode_calldata(L2_WITHDRAW_SIGNATURE_ERC20, &data)
66+
.expect("Failed to encode calldata for withdraw ERC20");
67+
let withdraw_transaction = l2_client
68+
.build_eip1559_transaction(
69+
COMMON_BRIDGE_L2_ADDRESS,
70+
from,
71+
Bytes::from(withdraw_data),
72+
Default::default(),
73+
)
74+
.await?;
75+
76+
l2_client
77+
.send_eip1559_transaction(&withdraw_transaction, &from_pk)
78+
.await
79+
}
80+
4581
pub async fn claim_withdraw(
4682
amount: U256,
4783
from: Address,
@@ -92,6 +128,57 @@ pub async fn claim_withdraw(
92128
.await
93129
}
94130

131+
pub async fn claim_erc20withdraw(
132+
token_l1: Address,
133+
token_l2: Address,
134+
amount: U256,
135+
from_pk: SecretKey,
136+
eth_client: &EthClient,
137+
message_proof: &L1MessageProof,
138+
bridge_address: Address,
139+
) -> Result<H256, EthClientError> {
140+
let from = get_address_from_secret_key(&from_pk)?;
141+
let calldata_values = vec![
142+
Value::Address(token_l1),
143+
Value::Address(token_l2),
144+
Value::Uint(amount),
145+
Value::Uint(U256::from(message_proof.batch_number)),
146+
Value::Uint(message_proof.message_id),
147+
Value::Array(
148+
message_proof
149+
.merkle_proof
150+
.clone()
151+
.into_iter()
152+
.map(|v| Value::FixedBytes(Bytes::copy_from_slice(v.as_bytes())))
153+
.collect(),
154+
),
155+
];
156+
157+
let claim_withdrawal_data =
158+
encode_calldata(CLAIM_WITHDRAWAL_ERC20_SIGNATURE, &calldata_values)?;
159+
160+
println!(
161+
"Claiming withdrawal with calldata: {}",
162+
hex::encode(&claim_withdrawal_data)
163+
);
164+
165+
let claim_tx = eth_client
166+
.build_eip1559_transaction(
167+
bridge_address,
168+
from,
169+
claim_withdrawal_data.into(),
170+
Overrides {
171+
from: Some(from),
172+
..Default::default()
173+
},
174+
)
175+
.await?;
176+
177+
eth_client
178+
.send_eip1559_transaction(&claim_tx, &from_pk)
179+
.await
180+
}
181+
95182
/// Returns the formatted hash of the withdrawal transaction,
96183
/// or None if the transaction is not a withdrawal.
97184
/// The hash is computed as keccak256(to || value || tx_hash)

0 commit comments

Comments
 (0)