@@ -16,16 +16,44 @@ use system_hooks::addresses_constants::{
1616#[ derive( Clone , Copy , Debug ) ]
1717pub ( 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+
2957pub const SERVICE_TX_TYPE : u8 = 0x7d ;
3058
3159impl < ' 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