@@ -168,6 +168,22 @@ def _raw_event_values(raw_event: dict) -> dict:
168168 return {item ["name" ]: item ["value" ] for item in raw_event ["data" ]}
169169
170170
171+ def _locator_addresses (locator ) -> dict :
172+ """Snapshot every zero-arg address getter the current locator implementation responds to."""
173+ addresses = {}
174+ for entry in locator .abi :
175+ if entry .get ("type" ) != "function" or entry .get ("inputs" ) or entry .get ("stateMutability" ) != "view" :
176+ continue
177+ outputs = entry .get ("outputs" ) or []
178+ if len (outputs ) != 1 or outputs [0 ].get ("type" ) != "address" :
179+ continue
180+ try :
181+ addresses [entry ["name" ]] = str (getattr (locator , entry ["name" ])())
182+ except Exception :
183+ continue
184+ return addresses
185+
186+
171187def _group_agent_dg_events_from_receipt (receipt : TransactionReceipt , timelock : str , agent : str ) -> list [EventDict ]:
172188 """Group DG proposal events by the Agent's inner call script items (single Agent.forward)."""
173189 events = tx_events_from_receipt (receipt )
@@ -386,6 +402,7 @@ def test_vote(
386402 expected_dg_proposal_id = timelock .getProposalsCount ()
387403
388404 details = timelock .getProposalDetails (expected_dg_proposal_id )
405+ locator_addresses_before = None
389406 if details ["status" ] != PROPOSAL_STATUS ["executed" ]:
390407 # =======================================================================
391408 # ==================== Before DG enactment checks =======================
@@ -405,6 +422,11 @@ def test_vote(
405422
406423 assert str (locator_proxy .proxy__getImplementation ()).lower () != NEW_LIDO_LOCATOR_IMPLEMENTATION .lower ()
407424
425+ # Snapshot the full locator address registry - the upgrade must change
426+ # only the depositSecurityModule entry
427+ locator_addresses_before = _locator_addresses (interface .LidoLocator (LIDO_LOCATOR ))
428+ assert locator_addresses_before ["depositSecurityModule" ].lower () == OLD_DEPOSIT_SECURITY_MODULE .lower ()
429+
408430 # Old DSM v4 holds the EOA guardian set (7 guardians: 6 mapped + 1 extra Lido dev team)
409431 old_dsm_guardians = {str (g ).lower () for g in old_dsm .getGuardians ()}
410432 assert old_dsm_guardians == {g .lower () for g in OLD_DSM_GUARDIANS }
@@ -530,6 +552,16 @@ def test_vote(
530552 == NEW_DEPOSIT_SECURITY_MODULE .lower ()
531553 )
532554
555+ # Every locator entry except depositSecurityModule must stay unchanged
556+ if locator_addresses_before is not None :
557+ locator = interface .LidoLocator (LIDO_LOCATOR )
558+ for name , before_value in locator_addresses_before .items ():
559+ after_value = str (getattr (locator , name )())
560+ if name == "depositSecurityModule" :
561+ assert after_value .lower () == NEW_DEPOSIT_SECURITY_MODULE .lower ()
562+ else :
563+ assert after_value == before_value , f"Locator entry { name } changed unexpectedly"
564+
533565 assert not staking_router .hasRole (STAKING_MODULE_UNVETTING_ROLE , OLD_DEPOSIT_SECURITY_MODULE )
534566 assert staking_router .hasRole (STAKING_MODULE_UNVETTING_ROLE , NEW_DEPOSIT_SECURITY_MODULE )
535567 assert top_up_gateway .hasRole (TOP_UP_ROLE , DEPOSITOR_BOT_DELEGATION_CONTRACT )
0 commit comments