Skip to content

Commit bc776a6

Browse files
authored
fix(contract_deployer): ensure hardfork configuration is respected with multiple chains (#360)
Closes #357 There was a bug in the logic that prepares the hardfork_schedule, which was causing all the chains to have the same as the last schedule. Now, we only apply the relevant hardfork_schedule according to each chain. --------- Co-authored-by: josepmc <5087962+josepmc@users.noreply.github.com>
1 parent c92ebbe commit bc776a6

2 files changed

Lines changed: 653 additions & 109 deletions

File tree

src/contracts/contract_deployer.star

Lines changed: 192 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,195 @@ def _normalize_artifacts_locators(plan, l1_locator, l2_locator):
7171
return l1_artifacts_locator, l2_artifacts_locator, extra_files
7272

7373

74+
def _build_hardfork_schedule(chain):
75+
"""Build hardfork schedule from chain configuration.
76+
77+
Args:
78+
chain: Chain configuration with network_params containing hardfork times
79+
80+
Returns:
81+
List of tuples (fork_key, activation_timestamp) for all activated hardforks
82+
"""
83+
np = chain.network_params
84+
85+
# rename each hardfork to the name the override expects
86+
renames = (
87+
("l2GenesisFjordTimeOffset", np.fjord_time_offset),
88+
("l2GenesisGraniteTimeOffset", np.granite_time_offset),
89+
("l2GenesisHoloceneTimeOffset", np.holocene_time_offset),
90+
("l2GenesisIsthmusTimeOffset", np.isthmus_time_offset),
91+
("l2GenesisInteropTimeOffset", np.interop_time_offset),
92+
)
93+
94+
# only include the hardforks that have been activated since
95+
# toml does not support null values
96+
hardfork_schedule = []
97+
for fork_key, activation_timestamp in renames:
98+
if activation_timestamp != None:
99+
hardfork_schedule.append((fork_key, activation_timestamp))
100+
101+
return hardfork_schedule
102+
103+
104+
def _build_superchain_roles(primary_chain_id):
105+
"""Build superchain roles configuration.
106+
107+
Args:
108+
primary_chain_id: Primary L2 chain ID to use for superchain roles
109+
110+
Returns:
111+
Dictionary containing superchain roles configuration
112+
"""
113+
return {
114+
"superchainGuardian": read_chain_cmd("l1ProxyAdmin", primary_chain_id),
115+
"protocolVersionsOwner": read_chain_cmd("l1ProxyAdmin", primary_chain_id),
116+
"superchainProxyAdminOwner": read_chain_cmd("l1ProxyAdmin", primary_chain_id),
117+
"challenger": read_chain_cmd("challenger", primary_chain_id),
118+
}
119+
120+
121+
def _build_global_deploy_overrides(optimism_args):
122+
"""Build global deploy overrides if fault game absolute prestate is configured.
123+
124+
Args:
125+
optimism_args: Optimism configuration arguments
126+
127+
Returns:
128+
Tuple of (absolute_prestate, global_deploy_overrides_dict or None)
129+
"""
130+
absolute_prestate = ""
131+
global_overrides = None
132+
133+
if (
134+
"faultGameAbsolutePrestate"
135+
in optimism_args.op_contract_deployer_params.overrides
136+
):
137+
absolute_prestate = optimism_args.op_contract_deployer_params.overrides[
138+
"faultGameAbsolutePrestate"
139+
]
140+
global_overrides = {
141+
"dangerouslyAllowCustomDisputeParameters": True,
142+
"faultGameAbsolutePrestate": absolute_prestate,
143+
}
144+
145+
return absolute_prestate, global_overrides
146+
147+
148+
def _build_chain_intent(
149+
chain, absolute_prestate, vm_type, altda_args, hardfork_schedule
150+
):
151+
"""Build intent configuration for a single chain.
152+
153+
Args:
154+
chain: Chain configuration
155+
absolute_prestate: Fault game absolute prestate value
156+
vm_type: VM type for dispute games
157+
altda_args: Alternative DA configuration
158+
hardfork_schedule: List of hardfork activation schedules
159+
160+
Returns:
161+
Dictionary containing chain intent configuration
162+
"""
163+
chain_id = str(chain.network_params.network_id)
164+
intent_chain = dict(CANNED_VALUES)
165+
intent_chain.update(
166+
{
167+
"deployOverrides": {
168+
"l2BlockTime": chain.network_params.seconds_per_slot,
169+
"fundDevAccounts": (
170+
True if chain.network_params.fund_dev_accounts else False
171+
),
172+
},
173+
"baseFeeVaultRecipient": read_chain_cmd("baseFeeVaultRecipient", chain_id),
174+
"l1FeeVaultRecipient": read_chain_cmd("l1FeeVaultRecipient", chain_id),
175+
"sequencerFeeVaultRecipient": read_chain_cmd(
176+
"sequencerFeeVaultRecipient", chain_id
177+
),
178+
"roles": {
179+
"batcher": read_chain_cmd("batcher", chain_id),
180+
"challenger": read_chain_cmd("challenger", chain_id),
181+
"l1ProxyAdminOwner": read_chain_cmd("l1ProxyAdmin", chain_id),
182+
"l2ProxyAdminOwner": read_chain_cmd("l2ProxyAdmin", chain_id),
183+
"proposer": read_chain_cmd("proposer", chain_id),
184+
"systemConfigOwner": read_chain_cmd("systemConfigOwner", chain_id),
185+
"unsafeBlockSigner": read_chain_cmd("sequencer", chain_id),
186+
},
187+
"dangerousAdditionalDisputeGames": [
188+
{
189+
"respectedGameType": 0,
190+
"faultGameAbsolutePrestate": absolute_prestate,
191+
"faultGameMaxDepth": 73,
192+
"faultGameSplitDepth": 30,
193+
"faultGameClockExtension": 10800,
194+
"faultGameMaxClockDuration": 302400,
195+
"dangerouslyAllowCustomDisputeParameters": True,
196+
"vmType": vm_type,
197+
"useCustomOracle": False,
198+
"oracleMinProposalSize": 0,
199+
"oracleChallengePeriodSeconds": 0,
200+
"makeRespected": False,
201+
}
202+
],
203+
"dangerousAltDAConfig": {
204+
"useAltDA": altda_args.use_altda,
205+
"daCommitmentType": altda_args.da_commitment_type,
206+
"daChallengeWindow": altda_args.da_challenge_window,
207+
"daResolveWindow": altda_args.da_resolve_window,
208+
"daBondSize": altda_args.da_bond_size,
209+
},
210+
}
211+
)
212+
213+
# Apply hardfork schedule overrides for this chain
214+
for fork_key, activation_timestamp in hardfork_schedule:
215+
intent_chain["deployOverrides"][fork_key] = "0x%x" % activation_timestamp
216+
217+
return intent_chain
218+
219+
220+
def _build_deployment_intent(
221+
optimism_args, l1_artifacts_locator, l2_artifacts_locator, altda_args
222+
):
223+
"""Build the complete deployment intent configuration.
224+
225+
Args:
226+
optimism_args: Optimism configuration arguments
227+
l1_artifacts_locator: L1 contracts artifact locator
228+
l2_artifacts_locator: L2 contracts artifact locator
229+
altda_args: Alternative DA configuration
230+
231+
Returns:
232+
Dictionary containing the complete deployment intent
233+
"""
234+
l2_chain_ids_list = [
235+
str(chain.network_params.network_id) for chain in optimism_args.chains
236+
]
237+
238+
intent = {
239+
"useInterop": len(optimism_args.superchains) > 0,
240+
"l1ContractsLocator": l1_artifacts_locator,
241+
"l2ContractsLocator": l2_artifacts_locator,
242+
"superchainRoles": _build_superchain_roles(l2_chain_ids_list[0]),
243+
"chains": [],
244+
}
245+
246+
absolute_prestate, global_overrides = _build_global_deploy_overrides(optimism_args)
247+
if global_overrides:
248+
intent["globalDeployOverrides"] = global_overrides
249+
250+
overrides = _filter.remove_none(optimism_args.op_contract_deployer_params.overrides)
251+
vm_type = overrides.get("vmType", "CANNON")
252+
253+
for _, chain in enumerate(optimism_args.chains):
254+
hardfork_schedule = _build_hardfork_schedule(chain)
255+
chain_intent = _build_chain_intent(
256+
chain, absolute_prestate, vm_type, altda_args, hardfork_schedule
257+
)
258+
intent["chains"].append(chain_intent)
259+
260+
return intent
261+
262+
74263
def deploy_contracts(
75264
plan, priv_key, l1_config_env_vars, optimism_args, l1_network, altda_args
76265
):
@@ -142,115 +331,9 @@ def deploy_contracts(
142331
run='bash /fund-script/fund.sh "{0}"'.format(l2_chain_ids),
143332
)
144333

145-
hardfork_schedule = []
146-
for index, chain in enumerate(optimism_args.chains):
147-
np = chain.network_params
148-
149-
# rename each hardfork to the name the override expects
150-
renames = (
151-
("l2GenesisFjordTimeOffset", np.fjord_time_offset),
152-
("l2GenesisGraniteTimeOffset", np.granite_time_offset),
153-
("l2GenesisHoloceneTimeOffset", np.holocene_time_offset),
154-
("l2GenesisIsthmusTimeOffset", np.isthmus_time_offset),
155-
("l2GenesisInteropTimeOffset", np.interop_time_offset),
156-
)
157-
158-
# only include the hardforks that have been activated since
159-
# toml does not support null values
160-
for fork_key, activation_timestamp in renames:
161-
if activation_timestamp != None:
162-
hardfork_schedule.append((index, fork_key, activation_timestamp))
163-
164-
intent = {
165-
# TODO At the moment, we assume that if there are any superchains defined, we'll need to deploy interop contracts
166-
# We'll need to update the op-deployer logic to better suit the interop scenario
167-
"useInterop": len(optimism_args.superchains) > 0,
168-
"l1ContractsLocator": l1_artifacts_locator,
169-
"l2ContractsLocator": l2_artifacts_locator,
170-
"superchainRoles": {
171-
"superchainGuardian": read_chain_cmd("l1ProxyAdmin", l2_chain_ids_list[0]),
172-
"protocolVersionsOwner": read_chain_cmd(
173-
"l1ProxyAdmin", l2_chain_ids_list[0]
174-
),
175-
"superchainProxyAdminOwner": read_chain_cmd(
176-
"l1ProxyAdmin", l2_chain_ids_list[0]
177-
),
178-
"challenger": read_chain_cmd("challenger", l2_chain_ids_list[0]),
179-
},
180-
"chains": [],
181-
}
182-
183-
absolute_prestate = ""
184-
if (
185-
"faultGameAbsolutePrestate"
186-
in optimism_args.op_contract_deployer_params.overrides
187-
):
188-
absolute_prestate = optimism_args.op_contract_deployer_params.overrides[
189-
"faultGameAbsolutePrestate"
190-
]
191-
intent["globalDeployOverrides"] = {
192-
"dangerouslyAllowCustomDisputeParameters": True,
193-
"faultGameAbsolutePrestate": absolute_prestate,
194-
}
195-
196-
overrides = _filter.remove_none(optimism_args.op_contract_deployer_params.overrides)
197-
vm_type = overrides.get("vmType", "CANNON")
198-
199-
for i, chain in enumerate(optimism_args.chains):
200-
chain_id = str(chain.network_params.network_id)
201-
intent_chain = dict(CANNED_VALUES)
202-
intent_chain.update(
203-
{
204-
"deployOverrides": {
205-
"l2BlockTime": chain.network_params.seconds_per_slot,
206-
"fundDevAccounts": (
207-
True if chain.network_params.fund_dev_accounts else False
208-
),
209-
},
210-
"baseFeeVaultRecipient": read_chain_cmd(
211-
"baseFeeVaultRecipient", chain_id
212-
),
213-
"l1FeeVaultRecipient": read_chain_cmd("l1FeeVaultRecipient", chain_id),
214-
"sequencerFeeVaultRecipient": read_chain_cmd(
215-
"sequencerFeeVaultRecipient", chain_id
216-
),
217-
"roles": {
218-
"batcher": read_chain_cmd("batcher", chain_id),
219-
"challenger": read_chain_cmd("challenger", chain_id),
220-
"l1ProxyAdminOwner": read_chain_cmd("l1ProxyAdmin", chain_id),
221-
"l2ProxyAdminOwner": read_chain_cmd("l2ProxyAdmin", chain_id),
222-
"proposer": read_chain_cmd("proposer", chain_id),
223-
"systemConfigOwner": read_chain_cmd("systemConfigOwner", chain_id),
224-
"unsafeBlockSigner": read_chain_cmd("sequencer", chain_id),
225-
},
226-
"dangerousAdditionalDisputeGames": [
227-
{
228-
"respectedGameType": 0,
229-
"faultGameAbsolutePrestate": absolute_prestate,
230-
"faultGameMaxDepth": 73,
231-
"faultGameSplitDepth": 30,
232-
"faultGameClockExtension": 10800,
233-
"faultGameMaxClockDuration": 302400,
234-
"dangerouslyAllowCustomDisputeParameters": True,
235-
"vmType": vm_type,
236-
"useCustomOracle": False,
237-
"oracleMinProposalSize": 0,
238-
"oracleChallengePeriodSeconds": 0,
239-
"makeRespected": False,
240-
}
241-
],
242-
"dangerousAltDAConfig": {
243-
"useAltDA": altda_args.use_altda,
244-
"daCommitmentType": altda_args.da_commitment_type,
245-
"daChallengeWindow": altda_args.da_challenge_window,
246-
"daResolveWindow": altda_args.da_resolve_window,
247-
"daBondSize": altda_args.da_bond_size,
248-
},
249-
}
250-
)
251-
for index, fork_key, activation_timestamp in hardfork_schedule:
252-
intent_chain["deployOverrides"][fork_key] = "0x%x" % activation_timestamp
253-
intent["chains"].append(intent_chain)
334+
intent = _build_deployment_intent(
335+
optimism_args, l1_artifacts_locator, l2_artifacts_locator, altda_args
336+
)
254337

255338
intent_json = json.encode(intent)
256339
intent_json_artifact = utils.write_to_file(plan, intent_json, "/tmp", "intent.json")

0 commit comments

Comments
 (0)