11use anyhow:: Context as _;
2+ use zksync_basic_types:: protocol_version:: ProtocolSemanticVersion ;
23
34use crate :: {
45 bytecode:: BytecodeHash ,
@@ -185,17 +186,19 @@ impl NewPriorityRequest {
185186}
186187
187188/// `VerifierParams` from `l1-contracts/contracts/state-transition/chain-interfaces/IVerifier.sol`.
188- #[ derive( Default , PartialEq ) ]
189+ #[ derive( Debug , Default , PartialEq ) ]
189190pub struct VerifierParams {
190191 pub recursion_node_level_vk_hash : [ u8 ; 32 ] ,
191192 pub recursion_leaf_level_vk_hash : [ u8 ; 32 ] ,
192193 pub recursion_circuits_set_vks_hash : [ u8 ; 32 ] ,
193194}
194195
195196/// `ProposedUpgrade` from, `l1-contracts/contracts/upgrades/BazeZkSyncUpgrade.sol`.
197+ #[ derive( Debug ) ]
196198pub struct ProposedUpgrade {
197199 pub l2_protocol_upgrade_tx : Box < L2CanonicalTransaction > ,
198- pub factory_deps : Vec < Vec < u8 > > ,
200+ // Factory deps are set only pre-gateway upgrades.
201+ pub factory_deps : Option < Vec < Vec < u8 > > > ,
199202 pub bootloader_hash : [ u8 ; 32 ] ,
200203 pub default_account_hash : [ u8 ; 32 ] ,
201204 pub verifier : Address ,
@@ -250,8 +253,8 @@ impl VerifierParams {
250253}
251254
252255impl ProposedUpgrade {
253- /// RLP schema of the `ProposedUpgrade`.
254- pub fn schema ( ) -> ParamType {
256+ /// Pre-gateway RLP schema of the `ProposedUpgrade`.
257+ pub fn schema_pre_gateway ( ) -> ParamType {
255258 ParamType :: Tuple ( vec ! [
256259 L2CanonicalTransaction :: schema( ) , // transaction data
257260 ParamType :: Array ( ParamType :: Bytes . into( ) ) , // factory deps
@@ -266,16 +269,39 @@ impl ProposedUpgrade {
266269 ] )
267270 }
268271
272+ /// Post-gateway RLP schema of the `ProposedUpgrade`.
273+ pub fn schema_post_gateway ( ) -> ParamType {
274+ ParamType :: Tuple ( vec ! [
275+ L2CanonicalTransaction :: schema( ) , // transaction data
276+ ParamType :: FixedBytes ( 32 ) , // bootloader code hash
277+ ParamType :: FixedBytes ( 32 ) , // default account code hash
278+ ParamType :: Address , // verifier address
279+ VerifierParams :: schema( ) , // verifier params
280+ ParamType :: Bytes , // l1 custom data
281+ ParamType :: Bytes , // l1 post-upgrade custom data
282+ ParamType :: Uint ( 256 ) , // timestamp
283+ ParamType :: Uint ( 256 ) , // version id
284+ ] )
285+ }
286+
269287 /// Encodes `ProposedUpgrade` to a RLP token.
270288 pub fn encode ( & self ) -> Token {
271- Token :: Tuple ( vec ! [
272- self . l2_protocol_upgrade_tx. encode( ) ,
273- Token :: Array (
289+ let mut tokens = vec ! [ self . l2_protocol_upgrade_tx. encode( ) ] ;
290+
291+ let protocol_version = ProtocolSemanticVersion :: try_from_packed ( self . new_protocol_version )
292+ . expect ( "Version is not supported" )
293+ . minor ;
294+ if protocol_version. is_pre_gateway ( ) {
295+ tokens. push ( Token :: Array (
274296 self . factory_deps
275- . iter( )
276- . map( |b| Token :: Bytes ( b. clone( ) ) )
297+ . clone ( )
298+ . expect ( "Factory deps should be present in pre-gateway upgrade data" )
299+ . into_iter ( )
300+ . map ( Token :: Bytes )
277301 . collect ( ) ,
278- ) ,
302+ ) ) ;
303+ }
304+ tokens. extend ( [
279305 Token :: FixedBytes ( self . bootloader_hash . into ( ) ) ,
280306 Token :: FixedBytes ( self . default_account_hash . into ( ) ) ,
281307 Token :: Address ( self . verifier ) ,
@@ -284,32 +310,52 @@ impl ProposedUpgrade {
284310 Token :: Bytes ( self . post_upgrade_calldata . clone ( ) ) ,
285311 Token :: Uint ( self . upgrade_timestamp ) ,
286312 Token :: Uint ( self . new_protocol_version ) ,
287- ] )
313+ ] ) ;
314+
315+ Token :: Tuple ( tokens)
288316 }
289317
290318 /// Decodes `ProposedUpgrade` from a RLP token.
291319 /// Returns an error if token doesn't match the `schema()`.
292320 pub fn decode ( token : Token ) -> anyhow:: Result < Self > {
293321 let tokens = token. into_tuple ( ) . context ( "not a tuple" ) ?;
294- anyhow:: ensure!( tokens. len( ) == 10 ) ;
322+ let tokens_len = tokens. len ( ) ;
323+ anyhow:: ensure!( tokens_len >= 9 ) ;
295324 let mut t = tokens. into_iter ( ) ;
296325 let mut next = || t. next ( ) . unwrap ( ) ;
297- Ok ( Self {
298- l2_protocol_upgrade_tx : L2CanonicalTransaction :: decode ( next ( ) )
299- . context ( "l2_protocol_upgrade_tx" ) ?
300- . into ( ) ,
301- factory_deps : next ( )
302- . into_array ( )
303- . context ( "factory_deps" ) ?
304- . into_iter ( )
305- . enumerate ( )
306- . map ( |( i, b) | b. into_bytes ( ) . context ( i) )
307- . collect :: < Result < _ , _ > > ( )
308- . context ( "factory_deps" ) ?,
309- bootloader_hash : next ( )
310- . into_fixed_bytes ( )
311- . and_then ( |b| b. try_into ( ) . ok ( ) )
312- . context ( "bootloader_hash" ) ?,
326+
327+ let l2_protocol_upgrade_tx = L2CanonicalTransaction :: decode ( next ( ) )
328+ . context ( "l2_protocol_upgrade_tx" ) ?
329+ . into ( ) ;
330+ let next_token = next ( ) ;
331+ let ( factory_deps, bootloader_hash) = match next_token {
332+ Token :: Array ( tokens) => {
333+ anyhow:: ensure!( tokens_len == 10 ) ;
334+ (
335+ Some (
336+ tokens
337+ . into_iter ( )
338+ . enumerate ( )
339+ . map ( |( i, b) | b. into_bytes ( ) . context ( i) )
340+ . collect :: < Result < _ , _ > > ( )
341+ . context ( "factory_deps" ) ?,
342+ ) ,
343+ next ( ) . into_fixed_bytes ( ) ,
344+ )
345+ }
346+ Token :: FixedBytes ( bytes) => {
347+ anyhow:: ensure!( tokens_len == 9 ) ;
348+ ( None , Some ( bytes) )
349+ }
350+ _ => anyhow:: bail!( "Unexpected type of the second token" ) ,
351+ } ;
352+ let bootloader_hash = bootloader_hash
353+ . and_then ( |b| b. try_into ( ) . ok ( ) )
354+ . context ( "bootloader_hash" ) ?;
355+ let upgrade = Self {
356+ l2_protocol_upgrade_tx,
357+ factory_deps,
358+ bootloader_hash,
313359 default_account_hash : next ( )
314360 . into_fixed_bytes ( )
315361 . and_then ( |b| b. try_into ( ) . ok ( ) )
@@ -322,7 +368,16 @@ impl ProposedUpgrade {
322368 post_upgrade_calldata : next ( ) . into_bytes ( ) . context ( "post_upgrade_calldata" ) ?,
323369 upgrade_timestamp : next ( ) . into_uint ( ) . context ( "upgrade_timestamp" ) ?,
324370 new_protocol_version : next ( ) . into_uint ( ) . context ( "new_protocol_version" ) ?,
325- } )
371+ } ;
372+
373+ let protocol_version =
374+ ProtocolSemanticVersion :: try_from_packed ( upgrade. new_protocol_version )
375+ . map_err ( |err| anyhow:: anyhow!( err) )
376+ . context ( "Version is not supported" ) ?
377+ . minor ;
378+ anyhow:: ensure!( protocol_version. is_pre_gateway( ) == upgrade. factory_deps. is_some( ) ) ;
379+
380+ Ok ( upgrade)
326381 }
327382}
328383
@@ -365,3 +420,166 @@ impl Transaction {
365420 } )
366421 }
367422}
423+
424+ pub struct ForceDeployment {
425+ pub bytecode_hash : H256 ,
426+ pub new_address : Address ,
427+ pub call_constructor : bool ,
428+ pub value : U256 ,
429+ pub input : Vec < u8 > ,
430+ }
431+
432+ impl ForceDeployment {
433+ /// ABI schema of the `ForceDeployment`.
434+ pub fn schema ( ) -> ParamType {
435+ ParamType :: Tuple ( vec ! [
436+ ParamType :: FixedBytes ( 32 ) ,
437+ ParamType :: Address ,
438+ ParamType :: Bool ,
439+ ParamType :: Uint ( 256 ) ,
440+ ParamType :: Bytes ,
441+ ] )
442+ }
443+
444+ /// Encodes `ForceDeployment` to a RLP token.
445+ pub fn encode ( & self ) -> Token {
446+ Token :: Tuple ( vec ! [
447+ Token :: FixedBytes ( self . bytecode_hash. 0 . to_vec( ) ) ,
448+ Token :: Address ( self . new_address) ,
449+ Token :: Bool ( self . call_constructor) ,
450+ Token :: Uint ( self . value) ,
451+ Token :: Bytes ( self . input. clone( ) ) ,
452+ ] )
453+ }
454+
455+ /// Decodes `ForceDeployment` from a RLP token.
456+ /// Returns an error if token doesn't match the `schema()`.
457+ pub fn decode ( token : Token ) -> anyhow:: Result < Self > {
458+ let tokens = token. into_tuple ( ) . context ( "not a tuple" ) ?;
459+ anyhow:: ensure!( tokens. len( ) == 5 ) ;
460+ let mut t = tokens. into_iter ( ) ;
461+ let mut next = || t. next ( ) . unwrap ( ) ;
462+ Ok ( Self {
463+ bytecode_hash : next ( )
464+ . into_fixed_bytes ( )
465+ . and_then ( |b| Some ( H256 ( b. try_into ( ) . ok ( ) ?) ) )
466+ . context ( "bytecode_hash" ) ?,
467+ new_address : next ( ) . into_address ( ) . context ( "new_address" ) ?,
468+ call_constructor : next ( ) . into_bool ( ) . context ( "call_constructor" ) ?,
469+ value : next ( ) . into_uint ( ) . context ( "value" ) ?,
470+ input : next ( ) . into_bytes ( ) . context ( "input" ) ?,
471+ } )
472+ }
473+ }
474+
475+ pub struct GatewayUpgradeEncodedInput {
476+ pub force_deployments : Vec < ForceDeployment > ,
477+ pub l2_gateway_upgrade_position : usize ,
478+ pub fixed_force_deployments_data : Vec < u8 > ,
479+ pub ctm_deployer : Address ,
480+ pub old_validator_timelock : Address ,
481+ pub new_validator_timelock : Address ,
482+ pub wrapped_base_token_store : Address ,
483+ }
484+
485+ impl GatewayUpgradeEncodedInput {
486+ /// ABI schema of the `GatewayUpgradeEncodedInput`.
487+ pub fn schema ( ) -> ParamType {
488+ ParamType :: Tuple ( vec ! [
489+ ParamType :: Array ( Box :: new( ForceDeployment :: schema( ) ) ) ,
490+ ParamType :: Uint ( 256 ) ,
491+ ParamType :: Bytes ,
492+ ParamType :: Address ,
493+ ParamType :: Address ,
494+ ParamType :: Address ,
495+ ParamType :: Address ,
496+ ] )
497+ }
498+
499+ /// Decodes `GatewayUpgradeEncodedInput` from a RLP token.
500+ /// Returns an error if token doesn't match the `schema()`.
501+ pub fn decode ( token : Token ) -> anyhow:: Result < Self > {
502+ let tokens = token. into_tuple ( ) . context ( "not a tuple" ) ?;
503+ anyhow:: ensure!( tokens. len( ) == 7 ) ;
504+ let mut t = tokens. into_iter ( ) ;
505+ let mut next = || t. next ( ) . unwrap ( ) ;
506+
507+ let force_deployments_array = next ( ) . into_array ( ) . context ( "force_deployments_array" ) ?;
508+ let mut force_deployments = vec ! [ ] ;
509+ for token in force_deployments_array {
510+ force_deployments. push ( ForceDeployment :: decode ( token) ?) ;
511+ }
512+
513+ Ok ( Self {
514+ force_deployments,
515+ l2_gateway_upgrade_position : next ( )
516+ . into_uint ( )
517+ . context ( "l2_gateway_upgrade_position" ) ?
518+ . as_usize ( ) ,
519+ fixed_force_deployments_data : next ( )
520+ . into_bytes ( )
521+ . context ( "fixed_force_deployments_data" ) ?,
522+ ctm_deployer : next ( ) . into_address ( ) . context ( "ctm_deployer" ) ?,
523+ old_validator_timelock : next ( ) . into_address ( ) . context ( "old_validator_timelock" ) ?,
524+ new_validator_timelock : next ( ) . into_address ( ) . context ( "new_validator_timelock" ) ?,
525+ wrapped_base_token_store : next ( ) . into_address ( ) . context ( "wrapped_base_token_store" ) ?,
526+ } )
527+ }
528+ }
529+
530+ #[ derive( Debug , Clone ) ]
531+ pub struct ZkChainSpecificUpgradeData {
532+ pub base_token_asset_id : H256 ,
533+ pub l2_legacy_shared_bridge : Address ,
534+ pub predeployed_l2_weth_address : Address ,
535+ pub base_token_l1_address : Address ,
536+ pub base_token_name : String ,
537+ pub base_token_symbol : String ,
538+ }
539+
540+ impl ZkChainSpecificUpgradeData {
541+ pub fn from_partial_components (
542+ base_token_asset_id : Option < H256 > ,
543+ l2_legacy_shared_bridge : Option < Address > ,
544+ predeployed_l2_weth_address : Option < Address > ,
545+ base_token_l1_address : Option < Address > ,
546+ base_token_name : Option < String > ,
547+ base_token_symbol : Option < String > ,
548+ ) -> Option < Self > {
549+ Some ( Self {
550+ base_token_asset_id : base_token_asset_id?,
551+ l2_legacy_shared_bridge : l2_legacy_shared_bridge?,
552+ // Note, that some chains may not contain previous deployment of L2 wrapped base
553+ // token. For those, zero address is used.
554+ predeployed_l2_weth_address : predeployed_l2_weth_address. unwrap_or_default ( ) ,
555+ base_token_l1_address : base_token_l1_address?,
556+ base_token_name : base_token_name?,
557+ base_token_symbol : base_token_symbol?,
558+ } )
559+ }
560+
561+ /// ABI schema of the `ZkChainSpecificUpgradeData`.
562+ pub fn schema ( ) -> ParamType {
563+ ParamType :: Tuple ( vec ! [
564+ ParamType :: FixedBytes ( 32 ) ,
565+ ParamType :: Address ,
566+ ParamType :: Address ,
567+ ] )
568+ }
569+
570+ /// Encodes `ZkChainSpecificUpgradeData` to a RLP token.
571+ pub fn encode ( & self ) -> Token {
572+ Token :: Tuple ( vec ! [
573+ Token :: FixedBytes ( self . base_token_asset_id. 0 . to_vec( ) ) ,
574+ Token :: Address ( self . l2_legacy_shared_bridge) ,
575+ Token :: Address ( self . predeployed_l2_weth_address) ,
576+ Token :: Address ( self . base_token_l1_address) ,
577+ Token :: String ( self . base_token_name. clone( ) ) ,
578+ Token :: String ( self . base_token_symbol. clone( ) ) ,
579+ ] )
580+ }
581+
582+ pub fn encode_bytes ( & self ) -> Vec < u8 > {
583+ ethabi:: encode ( & [ self . encode ( ) ] )
584+ }
585+ }
0 commit comments