Skip to content

Commit ed89872

Browse files
Check selectors too in whitelist
1 parent 4057eb7 commit ed89872

File tree

1 file changed

+36
-9
lines changed
  • basic_bootloader/src/bootloader/transaction/rlp_encoded/transaction_types

1 file changed

+36
-9
lines changed

basic_bootloader/src/bootloader/transaction/rlp_encoded/transaction_types/service_tx.rs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,44 @@ use system_hooks::addresses_constants::{
1616
#[derive(Clone, Copy, Debug)]
1717
pub(crate) struct ServiceTx<'a> {
1818
pub(crate) to: &'a [u8; 20], // NOTE: has to be one of the addresses in SERVICE_DESTINATION_WHITELIST
19-
pub(crate) data: &'a [u8],
19+
pub(crate) data: &'a [u8], // NOTE: has start with one of the selectors in SERVICE_DESTINATION_WHITELIST
2020
salt: u64, // Some salt used by the server to identify service transactions. Ignored by ZKsync OS.
2121
}
2222

23-
const SERVICE_DESTINATION_WHITELIST: &[B160] = &[
24-
L2_INTEROP_ROOT_STORAGE_ADDRESS,
25-
SYSTEM_CONTEXT_ADDRESS,
26-
L2_INTEROP_CENTER_ADDRESS,
23+
/// Selector for
24+
/// addInteropRootsInBatch((uint256,uint256,bytes32[])[])
25+
/// -> cca2f7bc
26+
const ADD_INTEROP_ROOTS_IN_BATCH_SELECTOR: [u8; 4] = [0xcc, 0xa2, 0xf7, 0xbc];
27+
28+
/// Selector for
29+
/// setSettlementLayerChainId(uint256)
30+
/// -> 0x040203e6
31+
const SET_SL_CHAIN_ID_SELECTOR: [u8; 4] = [0x04, 0x02, 0x03, 0xe6];
32+
33+
/// Selector for
34+
/// setInteropFee(uint256)
35+
/// -> 0x08273d8a
36+
const SET_INTEROP_FEE_SELECTOR: [u8; 4] = [0x09, 0x27, 0x3d, 0x8a];
37+
38+
/// Pairs (destination, selector) that service transactions are allowed
39+
/// to interact with.
40+
const SERVICE_DESTINATION_WHITELIST: &[(B160, [u8; 4])] = &[
41+
(
42+
L2_INTEROP_ROOT_STORAGE_ADDRESS,
43+
ADD_INTEROP_ROOTS_IN_BATCH_SELECTOR,
44+
),
45+
(SYSTEM_CONTEXT_ADDRESS, SET_SL_CHAIN_ID_SELECTOR),
46+
(L2_INTEROP_CENTER_ADDRESS, SET_INTEROP_FEE_SELECTOR),
2747
];
2848

49+
fn whitelisted(to: B160, data: &[u8]) -> bool {
50+
let selector: [u8; 4] = match data.get(..4).and_then(|bytes| bytes.try_into().ok()) {
51+
Some(selector) => selector,
52+
None => return false,
53+
};
54+
SERVICE_DESTINATION_WHITELIST.contains(&(to, selector))
55+
}
56+
2957
pub const SERVICE_TX_TYPE: u8 = 0x7d;
3058

3159
impl<'a> EthereumTxType for ServiceTx<'a> {
@@ -46,12 +74,11 @@ impl<'a> RlpListDecode<'a> for ServiceTx<'a> {
4674

4775
let to_b160 = B160::from_be_bytes(*to);
4876

77+
let data = r.bytes()?;
4978
// Validate whitelist
50-
if !SERVICE_DESTINATION_WHITELIST.contains(&to_b160) {
79+
if !whitelisted(to_b160, data) {
5180
return Err(InvalidTransaction::InvalidStructure);
5281
}
53-
54-
let data = r.bytes()?;
5582
let salt = r.u64()?;
5683
Ok(Self { to, data, salt })
5784
}
@@ -112,7 +139,7 @@ mod tests {
112139
#[test]
113140
fn to_in_whitelist_parses() {
114141
let to_bytes: [u8; 20] = L2_INTEROP_ROOT_STORAGE_ADDRESS.to_be_bytes();
115-
let data: Vec<u8> = vec![0xde, 0xad, 0xbe, 0xef];
142+
let data: Vec<u8> = ADD_INTEROP_ROOTS_IN_BATCH_SELECTOR.to_vec();
116143

117144
let bytes = encode_service_tx(&to_bytes, &data, 0);
118145

0 commit comments

Comments
 (0)