From a625931e2d0e17524b37f71b8bb8fa3ae269cfd9 Mon Sep 17 00:00:00 2001 From: Quintus <47097067+quintuskilbourn@users.noreply.github.com> Date: Tue, 15 Sep 2026 11:17:58 -0400 Subject: [PATCH 1/2] docs: point mainnet deployment to the current registry instance (#4) --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 7269e22..86bf6ed 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,5 @@ just test ### Ethereum mainnet -- Address: `0xda7afeed01fe625cf15d187a19f94b45f00b8c5f` +- Address: `0xDa7AfEeD021EAFC1c1Af9C362dE477DaD0396B81` - Constructor: `MAX_UPDATE_AGE = 0`, `MAX_UPDATE_LEAD_TIME = 0` -- CREATE2 factory: `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` -- Salt: `0x0000000000000000000000000000000000000000000000000000012809051083` From fedc8bda0ae95f3fb722e99bccee06bc43bf8e06 Mon Sep 17 00:00:00 2001 From: Quintus Date: Tue, 15 Sep 2026 20:37:07 +0000 Subject: [PATCH 2/2] fix: namespace lane storage to prevent aliasing with the updater mapping Lane slot 0 was derived as keccak256(abi.encode(target, laneIndex)) with a caller-supplied laneIndex. The updater authorization mapping isUpdater lives at slot 0, so isUpdater[target][updater] resolves to keccak256(abi.encode(updater, keccak256(abi.encode(target, 0)))) -- the same shape as a lane slot for target=updater, laneIndex=keccak256(abi.encode(target, 0)). A caller could therefore pick a laneIndex whose lane write lands on an authorization entry, granting itself updater rights for any target (or corrupting existing authorizations). Namespace the lane derivation with LANE_STORAGE_NAMESPACE so lane preimages are 96 bytes and can no longer coincide with the 64-byte authorization preimage. Based on the fix by @dvush. Co-Authored-By: Claude Opus 4.8 --- src/PrioUpdateRegistry.sol | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/PrioUpdateRegistry.sol b/src/PrioUpdateRegistry.sol index cdf51ad..0c649aa 100644 --- a/src/PrioUpdateRegistry.sol +++ b/src/PrioUpdateRegistry.sol @@ -31,6 +31,11 @@ contract PrioUpdateRegistry is EIP712 { /// @dev Each target manages its own set of updaters via `addUpdater` / `removeUpdater`. mapping(address target => mapping(address updater => bool)) public isUpdater; + /// @notice Domain separator used when deriving the storage base for a lane. + /// @dev Prevents lane 0 from sharing the `keccak256(abi.encode(target, 0))` derivation + /// used as the intermediate storage root of `isUpdater[target]`. + bytes32 public constant LANE_STORAGE_NAMESPACE = keccak256("PrioUpdateRegistry.lane"); + /// @notice Maximum age (in seconds) by which `updateTimestamp` may lag `block.timestamp` on writes. /// @dev A write is accepted iff /// `block.timestamp - MAX_UPDATE_AGE <= updateTimestamp <= block.timestamp + MAX_UPDATE_LEAD_TIME`. @@ -111,7 +116,7 @@ contract PrioUpdateRegistry is EIP712 { } function _laneSlot0Index(address target, uint256 laneIndex) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(target, laneIndex))); + return uint256(keccak256(abi.encode(LANE_STORAGE_NAMESPACE, target, laneIndex))); } /// @notice Validates and writes a state update for `target` at `laneIndex`.