From 788e6b637e15cb4fc54694c4cf1dc81016a9d254 Mon Sep 17 00:00:00 2001 From: mgretzke Date: Wed, 27 Aug 2025 11:59:02 +0200 Subject: [PATCH 1/2] check allocator id in prepareAllocation --- src/allocators/HybridAllocator.sol | 4 +++- src/allocators/OnChainAllocator.sol | 4 +++- src/allocators/lib/AllocatorLib.sol | 4 +++- test/HybridAllocator.t.sol | 15 +++++++++++++++ test/OnChainAllocator.t.sol | 15 +++++++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/allocators/HybridAllocator.sol b/src/allocators/HybridAllocator.sol index 8ece613..d7fc4ee 100644 --- a/src/allocators/HybridAllocator.sol +++ b/src/allocators/HybridAllocator.sol @@ -194,7 +194,9 @@ contract HybridAllocator is IHybridAllocator { bytes calldata /* orderData */ ) external returns (uint256 nonce) { nonce = nonces + 1; - AL.prepareAllocation(address(_COMPACT), nonce, recipient, idsAndAmounts, arbiter, expires, typehash, witness); + AL.prepareAllocation( + address(_COMPACT), nonce, recipient, idsAndAmounts, arbiter, expires, typehash, witness, ALLOCATOR_ID + ); } /// @inheritdoc IOnChainAllocation diff --git a/src/allocators/OnChainAllocator.sol b/src/allocators/OnChainAllocator.sol index 66746eb..6fb10b1 100644 --- a/src/allocators/OnChainAllocator.sol +++ b/src/allocators/OnChainAllocator.sol @@ -257,7 +257,9 @@ contract OnChainAllocator is IOnChainAllocator { } uint32 expiration = uint32(expires); nonce = _getNonce(msg.sender, recipient); - AL.prepareAllocation(COMPACT_CONTRACT, nonce, recipient, idsAndAmounts, arbiter, expiration, typehash, witness); + AL.prepareAllocation( + COMPACT_CONTRACT, nonce, recipient, idsAndAmounts, arbiter, expiration, typehash, witness, ALLOCATOR_ID + ); return nonce; } diff --git a/src/allocators/lib/AllocatorLib.sol b/src/allocators/lib/AllocatorLib.sol index a68d796..2ba90d5 100644 --- a/src/allocators/lib/AllocatorLib.sol +++ b/src/allocators/lib/AllocatorLib.sol @@ -17,6 +17,7 @@ library AllocatorLib { error InvalidBalanceChange(uint256 newBalance, uint256 oldBalance); error InvalidPreparation(); + error InvalidAllocatorId(uint96 providedId, uint96 allocatorId); error InvalidRegistration(address recipient, bytes32 claimHash, bytes32 typehash); function prepareAllocation( @@ -27,7 +28,8 @@ library AllocatorLib { address arbiter, uint256 expires, bytes32 typehash, - bytes32 witness + bytes32 witness, + uint96 allocatorId ) internal { assembly ("memory-safe") { // identifier = keccak256(abi.encode(PREPARE_ALLOCATION_SELECTOR, recipient, ids, arbiter, expires, typehash, witness)); diff --git a/test/HybridAllocator.t.sol b/test/HybridAllocator.t.sol index 52f0c72..a1a29fa 100644 --- a/test/HybridAllocator.t.sol +++ b/test/HybridAllocator.t.sol @@ -105,6 +105,21 @@ contract HybridAllocatorTest is Test, TestHelper { assertFalse(allocator.signers(attacker)); } + function test_prepareAllocation_revert_InvalidAllocatorId() public { + uint256[2][] memory idsAndAmounts = new uint256[2][](1); + idsAndAmounts[0][0] = _toId(Scope.Multichain, ResetPeriod.TenMinutes, address(this), address(usdc)); + idsAndAmounts[0][1] = defaultAmount; + + uint96 allocatorId = _toAllocatorId(address(this)); + + vm.expectRevert( + abi.encodeWithSelector(AllocatorLib.InvalidAllocatorId.selector, allocatorId, allocator.ALLOCATOR_ID()) + ); + allocator.prepareAllocation( + user, idsAndAmounts, arbiter, defaultExpiration, BATCH_COMPACT_TYPEHASH, bytes32(0), '' + ); + } + function test_prepareAllocation_returnsNonce_andDoesNotIncrement() public { uint256[2][] memory idsAndAmounts = _idsAndAmounts(address(usdc), defaultAmount); uint96 beforeNonces = allocator.nonces(); diff --git a/test/OnChainAllocator.t.sol b/test/OnChainAllocator.t.sol index da9c2bd..bf4b939 100644 --- a/test/OnChainAllocator.t.sol +++ b/test/OnChainAllocator.t.sol @@ -967,6 +967,21 @@ contract OnChainAllocatorTest is Test, TestHelper { idsAndAmounts[1][1] = amountB; } + function test_prepareAllocation_revert_InvalidAllocatorId() public { + uint256[2][] memory idsAndAmounts = new uint256[2][](1); + idsAndAmounts[0][0] = _toId(Scope.Multichain, ResetPeriod.TenMinutes, address(this), address(usdc)); + idsAndAmounts[0][1] = defaultAmount; + + uint96 allocatorId = _toAllocatorId(address(this)); + + vm.expectRevert( + abi.encodeWithSelector(AllocatorLib.InvalidAllocatorId.selector, allocatorId, allocator.ALLOCATOR_ID()) + ); + allocator.prepareAllocation( + recipient, idsAndAmounts, arbiter, defaultExpiration, BATCH_COMPACT_TYPEHASH, bytes32(0), '' + ); + } + function test_prepareAllocation_returnsNonce_and_doesNotIncrementStorage() public { uint256[2][] memory idsAndAmounts = _idsAndAmountsFor(address(usdc), defaultAmount); From d38a10a555f1247a8a837adf9c06f970ea00f400 Mon Sep 17 00:00:00 2001 From: mgretzke Date: Wed, 10 Dec 2025 16:54:37 +0100 Subject: [PATCH 2/2] updated allocator id check in prepareAllocation --- snapshots/HybridAllocatorTest.json | 2 +- snapshots/OnChainAllocatorTest.json | 4 ++-- src/allocators/lib/AllocatorLib.sol | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/snapshots/HybridAllocatorTest.json b/snapshots/HybridAllocatorTest.json index cb458fb..5a2400c 100644 --- a/snapshots/HybridAllocatorTest.json +++ b/snapshots/HybridAllocatorTest.json @@ -6,5 +6,5 @@ "allocateAndRegister_nativeToken_emptyAmountInput": "139067", "allocateAndRegister_second_erc20Token": "114886", "allocateAndRegister_second_nativeToken": "104867", - "hybrid_execute_single": "171479" + "hybrid_execute_single": "171524" } \ No newline at end of file diff --git a/snapshots/OnChainAllocatorTest.json b/snapshots/OnChainAllocatorTest.json index bf40e7c..81c3f81 100644 --- a/snapshots/OnChainAllocatorTest.json +++ b/snapshots/OnChainAllocatorTest.json @@ -4,6 +4,6 @@ "allocate_erc20": "127841", "allocate_native": "127601", "allocate_second_erc20": "95853", - "onchain_execute_double": "343074", - "onchain_execute_single": "216727" + "onchain_execute_double": "343161", + "onchain_execute_single": "216772" } \ No newline at end of file diff --git a/src/allocators/lib/AllocatorLib.sol b/src/allocators/lib/AllocatorLib.sol index 2ba90d5..093ae87 100644 --- a/src/allocators/lib/AllocatorLib.sol +++ b/src/allocators/lib/AllocatorLib.sol @@ -47,6 +47,14 @@ library AllocatorLib { for { let i := 0 } lt(i, idsAndAmounts.length) { i := add(i, 1) } { let id := calldataload(add(idsAndAmounts.offset, mul(i, 0x40))) + // Verify the id fits the allocator + if iszero(eq(shr(164, shl(4, id)), allocatorId)) { + mstore(0x00, 0x8bbfd798) // InvalidAllocatorId() + mstore(0x20, shr(164, shl(4, id))) + mstore(0x40, allocatorId) + revert(0x1c, 0x44) + } + // Retrieve and store the current balance of the recipient in transient storage mstore(0x14, recipient) // Store the `owner` argument. mstore(0x34, id)