diff --git a/artifacts/lez/programs/cross_zone_inbox.bin b/artifacts/lez/programs/cross_zone_inbox.bin index 39d851d8..0239df93 100644 Binary files a/artifacts/lez/programs/cross_zone_inbox.bin and b/artifacts/lez/programs/cross_zone_inbox.bin differ diff --git a/artifacts/lez/programs/wrapped_token.bin b/artifacts/lez/programs/wrapped_token.bin index 5a7d0f59..4b9d02a0 100644 Binary files a/artifacts/lez/programs/wrapped_token.bin and b/artifacts/lez/programs/wrapped_token.bin differ diff --git a/lez/programs/cross_zone_inbox/src/main.rs b/lez/programs/cross_zone_inbox/src/main.rs index 480a7274..bea71c69 100644 --- a/lez/programs/cross_zone_inbox/src/main.rs +++ b/lez/programs/cross_zone_inbox/src/main.rs @@ -168,14 +168,23 @@ fn init_config( inbox_config_account_id(self_program_id), "account must be the inbox config PDA" ); - // Init-once: a default pre-state cannot be re-run to overwrite the allowlists, - // and `new_claimed_if_default` alone would not stop the owning program from + // Init-once, idempotent under genesis replay: a `default` config is a first + // init; an already-owned config must already hold exactly these allowlists (the + // genesis block is replayed onto seeded state during multi-sequencer + // reconstruction), otherwise reject a post-genesis attempt to change them. + // `new_claimed_if_default` alone would not stop the owning program from // rewriting its own config data on a later call. - assert_eq!( - config_meta.account, - Account::default(), - "inbox config already initialized" - ); + if config_meta.account != Account::default() { + assert_eq!( + config_meta.account.program_owner, self_program_id, + "inbox config PDA is owned by another program" + ); + assert_eq!( + config_meta.account.data.clone().into_inner(), + config.to_bytes(), + "inbox config already initialized with different allowlists" + ); + } let mut config_account = config_meta.account.clone(); config_account.data = config diff --git a/lez/programs/wrapped_token/src/main.rs b/lez/programs/wrapped_token/src/main.rs index 12525756..19095e39 100644 --- a/lez/programs/wrapped_token/src/main.rs +++ b/lez/programs/wrapped_token/src/main.rs @@ -115,14 +115,23 @@ fn init_config( config_account_id(self_program_id), "account must be the wrapped-token config PDA" ); - // Init-once: a default pre-state cannot be re-run to overwrite the minter, and - // `new_claimed_if_default` alone would not stop the owning program from + // Init-once, idempotent under genesis replay: a `default` config is a first + // init; an already-owned config must already hold exactly this minter (the + // genesis block is replayed onto seeded state during multi-sequencer + // reconstruction), otherwise reject a post-genesis attempt to set a different + // minter. `new_claimed_if_default` alone would not stop the owning program from // rewriting its own config data on a later call. - assert_eq!( - config.account, - Account::default(), - "wrapped-token config already initialized" - ); + if config.account != Account::default() { + assert_eq!( + config.account.program_owner, self_program_id, + "wrapped-token config PDA is owned by another program" + ); + assert_eq!( + config.account.data.clone().into_inner(), + minter_bytes(minter).to_vec(), + "wrapped-token config already initialized with a different minter" + ); + } let mut config_account = config.account.clone(); config_account.data = minter_bytes(minter) diff --git a/test_fixtures/fixtures/prebuilt_sequencer_db.dump b/test_fixtures/fixtures/prebuilt_sequencer_db.dump index 8da212ad..f24d2f4f 100644 Binary files a/test_fixtures/fixtures/prebuilt_sequencer_db.dump and b/test_fixtures/fixtures/prebuilt_sequencer_db.dump differ