builder_relayer_client_rust/
utils.rs

1use ethers::types::{Address, U256};
2use sha3::{Digest, Keccak256};
3
4pub fn sleep_ms(ms: u64) -> tokio::time::Sleep {
5    tokio::time::sleep(std::time::Duration::from_millis(ms))
6}
7
8pub fn keccak256(bytes: &[u8]) -> [u8; 32] {
9    let mut hasher = Keccak256::new();
10    hasher.update(bytes);
11    let res = hasher.finalize();
12    let mut out = [0u8; 32];
13    out.copy_from_slice(&res);
14    out
15}
16
17pub fn hex_to_address(s: &str) -> Address {
18    s.parse().expect("invalid address")
19}
20
21pub fn u256_from_dec_str(s: &str) -> U256 {
22    U256::from_dec_str(s).expect("invalid u256")
23}
24
25/// Split and repack ECDSA signature like TS splitAndPackSig
26/// input: 0x{r}{s}{v}
27/// output: 0x{r(32)}{s(32)}{v(1)}
28pub fn split_and_pack_sig(sig_hex: &str) -> String {
29    // Mirror TS logic (splitSignature + encodePacked) so relayer validates:
30    // TS maps: 0/1 -> 31/32 and 27/28 -> 31/32 then encodes r,s,v as uint256,uint256,uint8 (decimal bigints)
31    let s = sig_hex.trim_start_matches("0x");
32    assert!(s.len() >= 130, "sig too short");
33    let r_hex = &s[0..64];
34    let s_hex = &s[64..128];
35    let v_hex = &s[128..130];
36    let mut v = u8::from_str_radix(v_hex, 16).expect("v");
37    match v {
38        0 | 1 => v += 31,  // 0/1 -> 31/32
39        27 | 28 => v += 4, // 27/28 -> 31/32
40        _ => {}
41    }
42    // r,s interpreted as uint256 decimal strings in TS. We'll keep hex then convert to U256 -> decimal.
43    use ethers::types::U256;
44    let r_u256 = U256::from_str_radix(r_hex, 16).expect("r parse");
45    let s_u256 = U256::from_str_radix(s_hex, 16).expect("s parse");
46    // encodePacked(uint256,uint256,uint8) == left padded 32 bytes for r,s then 1 byte v
47    // Simpler: manually pad r,s as 32-byte big endian.
48    let mut r_bytes = [0u8; 32];
49    let mut s_bytes = [0u8; 32];
50    r_u256.to_big_endian(&mut r_bytes);
51    s_u256.to_big_endian(&mut s_bytes);
52    let packed_bytes: Vec<u8> = [r_bytes.as_slice(), s_bytes.as_slice(), &[v]].concat();
53    format!("0x{}", hex::encode(packed_bytes))
54}