1use alloy_primitives::{address, bytes, Address, Bytes, FixedBytes, B256};
7
8pub const BUILDER_DEPOSIT_CONTRACT_ADDRESS: Address =
10 address!("0x0000BFF46984E3725691FA540A8C7589300D8282");
11
12pub static BUILDER_DEPOSIT_CONTRACT_CODE: Bytes = bytes!("0x3373fffffffffffffffffffffffffffffffffffffffe1461011c575f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146102705760015460088111605257506058565b60089003015b601190600182026001905f5b5f821115607f57810190830284830290049160010191906064565b90939004925050503660b814609f57366102705734610270575f5260205ff35b8034106102705760383567ffffffffffffffff1680633b9aca001161027057633b9aca00029034031061027057600154600101600155600354806006026004015f358155600101602035815560010160403581556001016060358155600101608035815560010160a035905560b85f5f3760b85fa0600101600355005b60035460025480820380604011610131575060405b5f5b8181146101d7578281016006026004018160b8028154815260200181600101548152602001816002015480825260401c67ffffffffffffffff16816010018160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c816001015353602001816003015481526020018160040154815260200190600501549052600101610133565b91018092146101e957906002556101f4565b90505f6002555f6003555b36610242575f54600154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461023057600882820111610238575b50505f610264565b0160089003610264565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5f555f60015560b8025ff35b5f5ffd");
14
15pub const BUILDER_EXIT_CONTRACT_ADDRESS: Address =
17 address!("0x000064D678505AD48F8CCB093BC65613800E8282");
18
19pub static BUILDER_EXIT_CONTRACT_CODE: Bytes = bytes!("0x3373fffffffffffffffffffffffffffffffffffffffe1460e1575f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101c65760015460028111605157506057565b60029003015b601190600182026001905f5b5f821115607e57810190830284830290049160010191906063565b909390049250505036603014609e57366101c657346101c6575f5260205ff35b34106101c657600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260305f60143760445fa0600101600355005b6003546002548082038060101160f5575060105b5f5b81811461012d5782810160030260040181604402815460601b8152601401816001015481526020019060020154905260010160f7565b910180921461013f579060025561014a565b90505f6002555f6003555b36610198575f54600154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101865760028282011161018e575b50505f6101ba565b01600290036101ba565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5f555f6001556044025ff35b5f5ffd");
21
22pub const BUILDER_DEPOSIT_REQUEST_TYPE: u8 = 0x03;
25
26pub const BUILDER_EXIT_REQUEST_TYPE: u8 = 0x04;
28
29pub const MAX_BUILDER_DEPOSIT_REQUESTS_PER_BLOCK: usize = 64;
31
32pub const MAX_BUILDER_EXIT_REQUESTS_PER_BLOCK: usize = 16;
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39#[cfg_attr(feature = "ssz", derive(ssz_derive::Encode, ssz_derive::Decode))]
40#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
41pub struct BuilderDepositRequest {
42 pub pubkey: FixedBytes<48>,
44 pub withdrawal_credentials: B256,
46 #[cfg_attr(feature = "serde", serde(with = "alloy_serde::displayfromstr"))]
48 pub amount: u64,
49 pub signature: FixedBytes<96>,
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
56#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
57#[cfg_attr(feature = "ssz", derive(ssz_derive::Encode, ssz_derive::Decode))]
58#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
59pub struct BuilderExitRequest {
60 pub source_address: Address,
62 pub pubkey: FixedBytes<48>,
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use alloy_primitives::{b256, hex};
70
71 #[test]
72 #[cfg(feature = "serde")]
73 fn test_serde_builder_deposit_request() {
74 let json_data = r#"{
76 "pubkey":"0x8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b",
77 "withdrawal_credentials":"0x0100000000000000000000000ae0e8770147aaa6828a0d6f642504663f10f7d1",
78 "amount":"32000000000",
79 "signature":"0xb3c0d1a2f4e5968778190a2b3c4d5e6f708192a3b4c5d6e7f80910a2b3c4d5e6b3c0d1a2f4e5968778190a2b3c4d5e6f708192a3b4c5d6e7f80910a2b3c4d5e6b3c0d1a2f4e5968778190a2b3c4d5e6f708192a3b4c5d6e7f80910a2b3c4d5e6"
80 }"#;
81
82 let deposit_request: BuilderDepositRequest =
84 serde_json::from_str(json_data).expect("Failed to deserialize");
85
86 assert_eq!(
88 deposit_request.pubkey,
89 FixedBytes::<48>::from(hex!("8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b"))
90 );
91 assert_eq!(
92 deposit_request.withdrawal_credentials,
93 b256!("0100000000000000000000000ae0e8770147aaa6828a0d6f642504663f10f7d1")
94 );
95 assert_eq!(deposit_request.amount, 32_000_000_000);
96
97 let serialized_json = serde_json::to_string(&deposit_request).expect("Failed to serialize");
99
100 let expected_json = r#"{"pubkey":"0x8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b","withdrawal_credentials":"0x0100000000000000000000000ae0e8770147aaa6828a0d6f642504663f10f7d1","amount":"32000000000","signature":"0xb3c0d1a2f4e5968778190a2b3c4d5e6f708192a3b4c5d6e7f80910a2b3c4d5e6b3c0d1a2f4e5968778190a2b3c4d5e6f708192a3b4c5d6e7f80910a2b3c4d5e6b3c0d1a2f4e5968778190a2b3c4d5e6f708192a3b4c5d6e7f80910a2b3c4d5e6"}"#;
102 assert_eq!(serialized_json, expected_json);
103 }
104
105 #[test]
106 #[cfg(feature = "serde")]
107 fn test_serde_builder_exit_request() {
108 let json_data = r#"{
110 "source_address":"0xAE0E8770147AaA6828a0D6f642504663F10F7d1E",
111 "pubkey":"0x8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b"
112 }"#;
113
114 let exit_request: BuilderExitRequest =
116 serde_json::from_str(json_data).expect("Failed to deserialize");
117
118 assert_eq!(
120 exit_request.source_address,
121 address!("AE0E8770147AaA6828a0D6f642504663F10F7d1E")
122 );
123 assert_eq!(
124 exit_request.pubkey,
125 FixedBytes::<48>::from(hex!("8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b"))
126 );
127
128 let serialized_json = serde_json::to_string(&exit_request).expect("Failed to serialize");
130
131 let expected_json = r#"{"source_address":"0xae0e8770147aaa6828a0d6f642504663f10f7d1e","pubkey":"0x8e8d8749f6bc79b78be7cc6e49ff640e608454840c360b344c3a4d9b7428e280e7f40d2271bad65d8cbbfdd43cb8793b"}"#;
133 assert_eq!(serialized_json, expected_json);
134 }
135}