From b574683758567b9a62a8327c39ec3d1c20166666 Mon Sep 17 00:00:00 2001 From: mgretzke Date: Tue, 26 Aug 2025 22:28:52 +0200 Subject: [PATCH 1/4] continue deployment if the allocator was pre-registered --- src/allocators/HybridAllocator.sol | 19 ++++++++++++++++++- src/allocators/OnChainAllocator.sol | 19 ++++++++++++++++++- src/interfaces/IHybridAllocator.sol | 1 + src/interfaces/IOnChainAllocator.sol | 3 +++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/allocators/HybridAllocator.sol b/src/allocators/HybridAllocator.sol index e59737c..a3338de 100644 --- a/src/allocators/HybridAllocator.sol +++ b/src/allocators/HybridAllocator.sol @@ -36,8 +36,25 @@ contract HybridAllocator is IHybridAllocator { revert InvalidSigner(); } _COMPACT = ITheCompact(compact_); - ALLOCATOR_ID = _COMPACT.__registerAllocator(address(this), ''); _COMPACT_DOMAIN_SEPARATOR = _COMPACT.DOMAIN_SEPARATOR(); + try _COMPACT.__registerAllocator(address(this), '') returns (uint96 allocatorId) { + ALLOCATOR_ID = allocatorId; + } catch (bytes memory lowLevelData) { + // Allocator is already registered. Check the registered allocator in the revert data + if (lowLevelData.length != 0x44) { + revert InvalidAllocatorRegistration(address(0)); + } + (bytes4 errorSelector, uint96 allocatorId, address registeredAllocator) = + abi.decode(lowLevelData, (bytes4, uint96, address)); + if (errorSelector != 0xc18b0e97) { + // Did not revert with 'ALLOCATOR_ALREADY_REGISTERED_ERROR' + revert InvalidAllocatorRegistration(address(0)); + } + if (registeredAllocator != address(this)) { + revert InvalidAllocatorRegistration(registeredAllocator); + } + ALLOCATOR_ID = allocatorId; + } signers[signer_] = true; signerCount++; diff --git a/src/allocators/OnChainAllocator.sol b/src/allocators/OnChainAllocator.sol index ac0fe19..a4b676f 100644 --- a/src/allocators/OnChainAllocator.sol +++ b/src/allocators/OnChainAllocator.sol @@ -35,7 +35,24 @@ contract OnChainAllocator is IOnChainAllocator { constructor(address compactContract_) { COMPACT_CONTRACT = compactContract_; COMPACT_DOMAIN_SEPARATOR = ITheCompact(COMPACT_CONTRACT).DOMAIN_SEPARATOR(); - ALLOCATOR_ID = ITheCompact(COMPACT_CONTRACT).__registerAllocator(address(this), ''); + try ITheCompact(COMPACT_CONTRACT).__registerAllocator(address(this), '') returns (uint96 allocatorId) { + ALLOCATOR_ID = allocatorId; + } catch (bytes memory lowLevelData) { + // Allocator is already registered. Check the registered allocator in the revert data + if (lowLevelData.length != 0x44) { + revert InvalidAllocatorRegistration(address(0)); + } + (bytes4 errorSelector, uint96 allocatorId, address registeredAllocator) = + abi.decode(lowLevelData, (bytes4, uint96, address)); + if (errorSelector != 0xc18b0e97) { + // Did not revert with 'ALLOCATOR_ALREADY_REGISTERED_ERROR' + revert InvalidAllocatorRegistration(address(0)); + } + if (registeredAllocator != address(this)) { + revert InvalidAllocatorRegistration(registeredAllocator); + } + ALLOCATOR_ID = allocatorId; + } } /// @inheritdoc IOnChainAllocator diff --git a/src/interfaces/IHybridAllocator.sol b/src/interfaces/IHybridAllocator.sol index 998e415..34053bd 100644 --- a/src/interfaces/IHybridAllocator.sol +++ b/src/interfaces/IHybridAllocator.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.27; import {IOnChainAllocation} from '@uniswap/the-compact/interfaces/IOnChainAllocation.sol'; interface IHybridAllocator is IOnChainAllocation { + error InvalidAllocatorRegistration(address alreadyRegisteredAllocator); error Unsupported(); error InvalidIds(); error InvalidAllocatorId(uint96 allocatorId, uint96 expectedAllocatorId); diff --git a/src/interfaces/IOnChainAllocator.sol b/src/interfaces/IOnChainAllocator.sol index a27ad39..2d43f60 100644 --- a/src/interfaces/IOnChainAllocator.sol +++ b/src/interfaces/IOnChainAllocator.sol @@ -12,6 +12,9 @@ interface IOnChainAllocator is IOnChainAllocation { bytes32 claimHash; } + /// @notice Thrown if the allocator is not successfully registered + error InvalidAllocatorRegistration(address alreadyRegisteredAllocator); + /// @notice Thrown if a claim is already active error ClaimActive(address sponsor); From 3751a6881d5d797545ccff887d7112b6fe7370ac Mon Sep 17 00:00:00 2001 From: mgretzke Date: Wed, 27 Aug 2025 15:28:55 +0200 Subject: [PATCH 2/4] fixes and tests --- src/allocators/HybridAllocator.sol | 9 +++++++-- src/allocators/OnChainAllocator.sol | 9 +++++++-- test/HybridAllocator.t.sol | 29 +++++++++++++++++++++++++++++ test/OnChainAllocator.t.sol | 28 ++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/allocators/HybridAllocator.sol b/src/allocators/HybridAllocator.sol index a3338de..8946ca7 100644 --- a/src/allocators/HybridAllocator.sol +++ b/src/allocators/HybridAllocator.sol @@ -44,12 +44,17 @@ contract HybridAllocator is IHybridAllocator { if (lowLevelData.length != 0x44) { revert InvalidAllocatorRegistration(address(0)); } - (bytes4 errorSelector, uint96 allocatorId, address registeredAllocator) = - abi.decode(lowLevelData, (bytes4, uint96, address)); + bytes4 errorSelector = bytes4(lowLevelData); if (errorSelector != 0xc18b0e97) { // Did not revert with 'ALLOCATOR_ALREADY_REGISTERED_ERROR' revert InvalidAllocatorRegistration(address(0)); } + uint96 allocatorId; + address registeredAllocator; + assembly { + allocatorId := mload(add(lowLevelData, 0x24)) + registeredAllocator := mload(add(lowLevelData, 0x44)) + } if (registeredAllocator != address(this)) { revert InvalidAllocatorRegistration(registeredAllocator); } diff --git a/src/allocators/OnChainAllocator.sol b/src/allocators/OnChainAllocator.sol index a4b676f..f28b22b 100644 --- a/src/allocators/OnChainAllocator.sol +++ b/src/allocators/OnChainAllocator.sol @@ -42,12 +42,17 @@ contract OnChainAllocator is IOnChainAllocator { if (lowLevelData.length != 0x44) { revert InvalidAllocatorRegistration(address(0)); } - (bytes4 errorSelector, uint96 allocatorId, address registeredAllocator) = - abi.decode(lowLevelData, (bytes4, uint96, address)); + bytes4 errorSelector = bytes4(lowLevelData); if (errorSelector != 0xc18b0e97) { // Did not revert with 'ALLOCATOR_ALREADY_REGISTERED_ERROR' revert InvalidAllocatorRegistration(address(0)); } + uint96 allocatorId; + address registeredAllocator; + assembly { + allocatorId := mload(add(lowLevelData, 0x24)) + registeredAllocator := mload(add(lowLevelData, 0x44)) + } if (registeredAllocator != address(this)) { revert InvalidAllocatorRegistration(registeredAllocator); } diff --git a/test/HybridAllocator.t.sol b/test/HybridAllocator.t.sol index 52b35c4..a6aa6f5 100644 --- a/test/HybridAllocator.t.sol +++ b/test/HybridAllocator.t.sol @@ -21,6 +21,12 @@ import {IHybridAllocator} from 'src/interfaces/IHybridAllocator.sol'; import {ERC20Mock} from 'src/test/ERC20Mock.sol'; import {OnChainAllocationCaller} from 'src/test/OnChainAllocationCaller.sol'; +contract HybridAllocatorFactory { + function deploy(bytes32 salt, address compact, address signer) external returns (address) { + return address(new HybridAllocator{salt: salt}(compact, signer)); + } +} + contract HybridAllocatorTest is Test, TestHelper { TheCompact compact; address arbiter; @@ -1047,4 +1053,27 @@ contract HybridAllocatorTest is Test, TestHelper { assertFalse(allocator.signers(signer)); assertTrue(allocator.signers(newSigner)); } + + function test_constructor_allowsPreRegisteredAllocator_create2() public { + HybridAllocatorFactory factory = new HybridAllocatorFactory(); + + bytes32 salt = keccak256('hybrid-allocator-pre-registered'); + bytes memory initCode = + abi.encodePacked(type(HybridAllocator).creationCode, abi.encode(address(compact), signer)); + bytes32 initCodeHash = keccak256(initCode); + + address expected = + address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(factory), salt, initCodeHash))))); + + bytes memory proof = abi.encodePacked(bytes1(0xff), address(factory), salt, initCodeHash); + + uint96 preId = compact.__registerAllocator(expected, proof); + assertEq(_toAllocatorId(expected), preId); + + address deployed = HybridAllocatorFactory(address(factory)).deploy(salt, address(compact), signer); + assertEq(deployed, expected); + + HybridAllocator newAllocator = HybridAllocator(deployed); + assertEq(newAllocator.ALLOCATOR_ID(), _toAllocatorId(deployed)); + } } diff --git a/test/OnChainAllocator.t.sol b/test/OnChainAllocator.t.sol index 0314499..419fa88 100644 --- a/test/OnChainAllocator.t.sol +++ b/test/OnChainAllocator.t.sol @@ -31,6 +31,12 @@ import {AllocatorLib} from 'src/allocators/lib/AllocatorLib.sol'; import {OnChainAllocationCaller} from 'src/test/OnChainAllocationCaller.sol'; import {TestHelper} from 'test/util/TestHelper.sol'; +contract OnChainAllocatorFactory { + function deploy(bytes32 salt, address compact) external returns (address) { + return address(new OnChainAllocator{salt: salt}(compact)); + } +} + contract OnChainAllocatorTest is Test, TestHelper { TheCompact internal compact; OnChainAllocator internal allocator; @@ -1274,6 +1280,28 @@ contract OnChainAllocatorTest is Test, TestHelper { ); } + function test_constructor_allowsPreRegisteredAllocator_create2() public { + OnChainAllocatorFactory factory = new OnChainAllocatorFactory(); + + bytes32 salt = keccak256('onchain-allocator-pre-registered'); + bytes memory initCode = abi.encodePacked(type(OnChainAllocator).creationCode, abi.encode(address(compact))); + bytes32 initCodeHash = keccak256(initCode); + + address expected = + address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(factory), salt, initCodeHash))))); + + bytes memory proof = abi.encodePacked(bytes1(0xff), address(factory), salt, initCodeHash); + + uint96 preId = compact.__registerAllocator(expected, proof); + assertEq(_toAllocatorId(expected), preId); + + address deployed = OnChainAllocatorFactory(address(factory)).deploy(salt, address(compact)); + assertEq(deployed, expected); + + OnChainAllocator newAllocator = OnChainAllocator(deployed); + assertEq(newAllocator.ALLOCATOR_ID(), _toAllocatorId(deployed)); + } + function test_allocateAndRegister_tokensImmediatelyAllocated() public { uint256 amount1 = 1 ether; uint256 amount2 = 2 ether; From 94116a7e8dc9c986be028af347da0b28f06d4171 Mon Sep 17 00:00:00 2001 From: mgretzke Date: Wed, 27 Aug 2025 15:45:59 +0200 Subject: [PATCH 3/4] lint --- snapshots/ERC7683Allocator_open.json | 4 ++-- snapshots/ERC7683Allocator_openFor.json | 4 ++-- snapshots/HybridAllocatorTest.json | 18 +++++++++--------- snapshots/OnChainAllocatorTest.json | 16 ++++++++-------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/snapshots/ERC7683Allocator_open.json b/snapshots/ERC7683Allocator_open.json index 9c7f3d9..341ce5b 100644 --- a/snapshots/ERC7683Allocator_open.json +++ b/snapshots/ERC7683Allocator_open.json @@ -1,3 +1,3 @@ { - "open_simpleOrder": "168301" -} \ No newline at end of file + "open_simpleOrder": "168301" +} diff --git a/snapshots/ERC7683Allocator_openFor.json b/snapshots/ERC7683Allocator_openFor.json index c719551..cb347bd 100644 --- a/snapshots/ERC7683Allocator_openFor.json +++ b/snapshots/ERC7683Allocator_openFor.json @@ -1,3 +1,3 @@ { - "openFor_simpleOrder_userHimself": "171750" -} \ No newline at end of file + "openFor_simpleOrder_userHimself": "171750" +} diff --git a/snapshots/HybridAllocatorTest.json b/snapshots/HybridAllocatorTest.json index c5840e6..e41b300 100644 --- a/snapshots/HybridAllocatorTest.json +++ b/snapshots/HybridAllocatorTest.json @@ -1,10 +1,10 @@ { - "allocateAndRegister_erc20Token": "187668", - "allocateAndRegister_erc20Token_emptyAmountInput": "188578", - "allocateAndRegister_multipleTokens": "223574", - "allocateAndRegister_nativeToken": "139204", - "allocateAndRegister_nativeToken_emptyAmountInput": "139040", - "allocateAndRegister_second_erc20Token": "114874", - "allocateAndRegister_second_nativeToken": "104840", - "hybrid_execute_single": "174395" -} \ No newline at end of file + "allocateAndRegister_erc20Token": "187668", + "allocateAndRegister_erc20Token_emptyAmountInput": "188578", + "allocateAndRegister_multipleTokens": "223574", + "allocateAndRegister_nativeToken": "139204", + "allocateAndRegister_nativeToken_emptyAmountInput": "139040", + "allocateAndRegister_second_erc20Token": "114874", + "allocateAndRegister_second_nativeToken": "104840", + "hybrid_execute_single": "174395" +} diff --git a/snapshots/OnChainAllocatorTest.json b/snapshots/OnChainAllocatorTest.json index ec5af8f..bdaf0ea 100644 --- a/snapshots/OnChainAllocatorTest.json +++ b/snapshots/OnChainAllocatorTest.json @@ -1,9 +1,9 @@ { - "allocateFor_success_withRegistration": "133753", - "allocate_and_delete_expired_allocation": "65921", - "allocate_erc20": "129192", - "allocate_native": "128952", - "allocate_second_erc20": "97204", - "onchain_execute_double": "347707", - "onchain_execute_single": "219699" -} \ No newline at end of file + "allocateFor_success_withRegistration": "133753", + "allocate_and_delete_expired_allocation": "65921", + "allocate_erc20": "129192", + "allocate_native": "128952", + "allocate_second_erc20": "97204", + "onchain_execute_double": "347707", + "onchain_execute_single": "219699" +} From 736b7af446c93aa0648c9cd09b31c10ac89991cc Mon Sep 17 00:00:00 2001 From: KumaCrypto Date: Thu, 28 Aug 2025 17:38:07 +0100 Subject: [PATCH 4/4] feat: simplify fix for M01 --- src/allocators/HybridAllocator.sol | 40 +++++++++++++++++------------ src/allocators/OnChainAllocator.sol | 39 ++++++++++++++++------------ test/OnChainAllocator.t.sol | 37 +++++++++++++++++++++++--- 3 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/allocators/HybridAllocator.sol b/src/allocators/HybridAllocator.sol index 8946ca7..e2f04ec 100644 --- a/src/allocators/HybridAllocator.sol +++ b/src/allocators/HybridAllocator.sol @@ -10,6 +10,9 @@ import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {AllocatorLib as AL} from './lib/AllocatorLib.sol'; import {IAllocator} from '@uniswap/the-compact/interfaces/IAllocator.sol'; import {ITheCompact} from '@uniswap/the-compact/interfaces/ITheCompact.sol'; + +import {Extsload} from '@uniswap/the-compact/lib/Extsload.sol'; +import {IdLib} from '@uniswap/the-compact/lib/IdLib.sol'; import {IHybridAllocator} from 'src/interfaces/IHybridAllocator.sol'; contract HybridAllocator is IHybridAllocator { @@ -39,25 +42,28 @@ contract HybridAllocator is IHybridAllocator { _COMPACT_DOMAIN_SEPARATOR = _COMPACT.DOMAIN_SEPARATOR(); try _COMPACT.__registerAllocator(address(this), '') returns (uint96 allocatorId) { ALLOCATOR_ID = allocatorId; - } catch (bytes memory lowLevelData) { - // Allocator is already registered. Check the registered allocator in the revert data - if (lowLevelData.length != 0x44) { - revert InvalidAllocatorRegistration(address(0)); - } - bytes4 errorSelector = bytes4(lowLevelData); - if (errorSelector != 0xc18b0e97) { - // Did not revert with 'ALLOCATOR_ALREADY_REGISTERED_ERROR' - revert InvalidAllocatorRegistration(address(0)); - } - uint96 allocatorId; - address registeredAllocator; - assembly { - allocatorId := mload(add(lowLevelData, 0x24)) - registeredAllocator := mload(add(lowLevelData, 0x44)) + } catch { + // The Compact does not have a getter function for retrieving the status of allocator registration, + // so we need to calculate it manually. + uint96 allocatorId = IdLib.toAllocatorId(address(this)); + bytes32 allocatorSlot; + assembly ("memory-safe") { + // Identical to the registration logic slot calculation in The Compact: + // let allocatorSlot := or(_ALLOCATOR_BY_ALLOCATOR_ID_SLOT_SEED, allocatorId) + allocatorSlot := or(0x000044036fc77deaed2300000000000000000000000, allocatorId) } - if (registeredAllocator != address(this)) { - revert InvalidAllocatorRegistration(registeredAllocator); + + bytes32 registeredAllocator = Extsload(compact_).extsload(allocatorSlot); + + assembly ("memory-safe") { + if iszero(eq(registeredAllocator, address())) { + // revert InvalidAllocatorRegistration(registeredAllocator) + mstore(0x00, 0x161ab6ea) + mstore(0x20, registeredAllocator) + revert(0x1c, 0x24) + } } + ALLOCATOR_ID = allocatorId; } diff --git a/src/allocators/OnChainAllocator.sol b/src/allocators/OnChainAllocator.sol index f28b22b..a754b1b 100644 --- a/src/allocators/OnChainAllocator.sol +++ b/src/allocators/OnChainAllocator.sol @@ -10,6 +10,8 @@ import {ERC6909} from '@solady/tokens/ERC6909.sol'; import {SafeTransferLib} from '@solady/utils/SafeTransferLib.sol'; import {IAllocator} from '@uniswap/the-compact/interfaces/IAllocator.sol'; import {ITheCompact} from '@uniswap/the-compact/interfaces/ITheCompact.sol'; +import {Extsload} from '@uniswap/the-compact/lib/Extsload.sol'; +import {IdLib} from '@uniswap/the-compact/lib/IdLib.sol'; import {Lock} from '@uniswap/the-compact/types/EIP712Types.sol'; /// @title OnChainAllocator @@ -37,25 +39,28 @@ contract OnChainAllocator is IOnChainAllocator { COMPACT_DOMAIN_SEPARATOR = ITheCompact(COMPACT_CONTRACT).DOMAIN_SEPARATOR(); try ITheCompact(COMPACT_CONTRACT).__registerAllocator(address(this), '') returns (uint96 allocatorId) { ALLOCATOR_ID = allocatorId; - } catch (bytes memory lowLevelData) { - // Allocator is already registered. Check the registered allocator in the revert data - if (lowLevelData.length != 0x44) { - revert InvalidAllocatorRegistration(address(0)); + } catch { + // The Compact does not have a getter function for retrieving the status of allocator registration, + // so we need to calculate it manually. + uint96 allocatorId = IdLib.toAllocatorId(address(this)); + bytes32 allocatorSlot; + assembly ("memory-safe") { + // Identical to the registration logic slot calculation in The Compact: + // let allocatorSlot := or(_ALLOCATOR_BY_ALLOCATOR_ID_SLOT_SEED, allocatorId) + allocatorSlot := or(0x000044036fc77deaed2300000000000000000000000, allocatorId) } - bytes4 errorSelector = bytes4(lowLevelData); - if (errorSelector != 0xc18b0e97) { - // Did not revert with 'ALLOCATOR_ALREADY_REGISTERED_ERROR' - revert InvalidAllocatorRegistration(address(0)); - } - uint96 allocatorId; - address registeredAllocator; - assembly { - allocatorId := mload(add(lowLevelData, 0x24)) - registeredAllocator := mload(add(lowLevelData, 0x44)) - } - if (registeredAllocator != address(this)) { - revert InvalidAllocatorRegistration(registeredAllocator); + + bytes32 registeredAllocator = Extsload(COMPACT_CONTRACT).extsload(allocatorSlot); + + assembly ("memory-safe") { + if iszero(eq(registeredAllocator, address())) { + // revert InvalidAllocatorRegistration(registeredAllocator) + mstore(0x00, 0x161ab6ea) + mstore(0x20, registeredAllocator) + revert(0x1c, 0x24) + } } + ALLOCATOR_ID = allocatorId; } } diff --git a/test/OnChainAllocator.t.sol b/test/OnChainAllocator.t.sol index 419fa88..0a0f17a 100644 --- a/test/OnChainAllocator.t.sol +++ b/test/OnChainAllocator.t.sol @@ -15,7 +15,6 @@ import {ERC20Mock} from 'src/test/ERC20Mock.sol'; import {TheCompact} from '@uniswap/the-compact/TheCompact.sol'; import {IAllocator} from '@uniswap/the-compact/interfaces/IAllocator.sol'; -import {ITheCompact} from '@uniswap/the-compact/interfaces/ITheCompact.sol'; import {IOnChainAllocation} from '@uniswap/the-compact/interfaces/IOnChainAllocation.sol'; import {OnChainAllocator} from 'src/allocators/OnChainAllocator.sol'; @@ -27,6 +26,7 @@ import {ERC6909} from '@solady/tokens/ERC6909.sol'; import {ResetPeriod} from '@uniswap/the-compact/types/ResetPeriod.sol'; import {Scope} from '@uniswap/the-compact/types/Scope.sol'; +import {IdLib} from '@uniswap/the-compact/lib/IdLib.sol'; import {AllocatorLib} from 'src/allocators/lib/AllocatorLib.sol'; import {OnChainAllocationCaller} from 'src/test/OnChainAllocationCaller.sol'; import {TestHelper} from 'test/util/TestHelper.sol'; @@ -1287,8 +1287,7 @@ contract OnChainAllocatorTest is Test, TestHelper { bytes memory initCode = abi.encodePacked(type(OnChainAllocator).creationCode, abi.encode(address(compact))); bytes32 initCodeHash = keccak256(initCode); - address expected = - address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(factory), salt, initCodeHash))))); + address expected = vm.computeCreate2Address(salt, initCodeHash, address(factory)); bytes memory proof = abi.encodePacked(bytes1(0xff), address(factory), salt, initCodeHash); @@ -1302,6 +1301,38 @@ contract OnChainAllocatorTest is Test, TestHelper { assertEq(newAllocator.ALLOCATOR_ID(), _toAllocatorId(deployed)); } + function test_constructor_reverts_with_already_registered_allocator_in_case_of_address_collision() public { + // Deploy Create2 factory + OnChainAllocatorFactory factory = new OnChainAllocatorFactory(); + + // Precalculate the allocator's address + bytes32 salt = keccak256('onchain-allocator-pre-registered'); + bytes memory initCode = abi.encodePacked(type(OnChainAllocator).creationCode, abi.encode(address(compact))); + bytes32 initCodeHash = keccak256(initCode); + + address expected = vm.computeCreate2Address(salt, initCodeHash, address(factory)); + + // Store a different registered allocator address (simulate an address collision) + address differentRegisteredAllocator = address(1); + + uint96 allocatorId = IdLib.toAllocatorId(expected); + bytes32 allocatorSlot; + assembly ("memory-safe") { + allocatorSlot := or(0x000044036fc77deaed2300000000000000000000000, allocatorId) + } + + vm.store(address(compact), allocatorSlot, bytes32(uint256(uint160(differentRegisteredAllocator)))); + + // Try to deploy the allocator + // Should revert with the InvalidAllocatorRegistration error, since The Compact has a different address stored in the allocator's slot + vm.expectRevert( + abi.encodeWithSelector( + IOnChainAllocator.InvalidAllocatorRegistration.selector, differentRegisteredAllocator + ) + ); + OnChainAllocatorFactory(address(factory)).deploy(salt, address(compact)); + } + function test_allocateAndRegister_tokensImmediatelyAllocated() public { uint256 amount1 = 1 ether; uint256 amount2 = 2 ether;