Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
2909eaa
SimpleAllocator contract adaptations
mgretzke Mar 27, 2025
e1c4cdd
updated Compact and fixed issues
mgretzke Jun 23, 2025
209b86b
fixed compile issues
mgretzke Jun 23, 2025
2ac00e2
Added HybridAllocator and HybridERC7683 allocator
mgretzke Jul 2, 2025
9af9257
Updated ERC7683Allocator to support coverage (wip)
mgretzke Jul 2, 2025
8b48afb
Started working on tests
mgretzke Jul 2, 2025
68e1831
Cleaned up HybridAllocators and tests
mgretzke Jul 10, 2025
a570f27
disabled IR for test contracts
mgretzke Jul 10, 2025
bb6206a
optimizations and fixes
mgretzke Jul 11, 2025
ee65c4d
added HybridAllocator Interface
mgretzke Jul 14, 2025
6b09356
added HybridERC7683 Interface
mgretzke Jul 14, 2025
a0263bb
fixed theCompact sizes
mgretzke Jul 15, 2025
fab5c11
HybridERC7683 claims slot fix
mgretzke Jul 17, 2025
bbee4d6
interface clean up
mgretzke Jul 18, 2025
c34683b
implemented feedback
mgretzke Jul 28, 2025
c466245
second registration snapshot
mgretzke Jul 29, 2025
dc40666
implemented PR feedback
mgretzke Jul 29, 2025
511d1a3
added missing files
mgretzke Aug 1, 2025
7262180
openFor function added to HybridERC7683 + tests
mgretzke Aug 4, 2025
442265c
PR comments and tests
mgretzke Aug 8, 2025
aabaf1d
progress to V1
mgretzke Jun 20, 2025
4d5d981
updated Compact and fixed issues
mgretzke Jun 23, 2025
309757b
fixed compile issues
mgretzke Jun 23, 2025
5df526c
removed local IAllocator
mgretzke Jun 23, 2025
e7a911d
Updated ERC7683Allocator to support coverage (wip)
mgretzke Jul 2, 2025
bec325a
Started working on tests
mgretzke Jul 2, 2025
faaa4b0
improved ERC7683Allocator and tests
mgretzke Jul 10, 2025
ae5b81d
removed logs in tests
mgretzke Jul 10, 2025
6024477
optimizations and fixes
mgretzke Jul 11, 2025
5baf3e6
nonce redesign
mgretzke Jul 14, 2025
8adc58c
cleanup + 64 bytes signature support
mgretzke Jul 18, 2025
dca36f4
interface clean up
mgretzke Jul 18, 2025
966805e
OnChainAllocator contract
mgretzke Jul 21, 2025
d01def0
nonces updated and registerAllocationFor added
mgretzke Jul 21, 2025
591b243
Added support for relaying via on chain registration
mgretzke Jul 21, 2025
1359945
Use commitments instead of idsAndAmounts
mgretzke Jul 23, 2025
f64074b
ERC7683Allocated using OnChainAllocator
mgretzke Jul 23, 2025
cdef204
optimization and fixing issues
mgretzke Jul 28, 2025
7802e1f
moved arbiter into Order struct
mgretzke Jul 29, 2025
329fe07
ERC7683Allocator full coverage
mgretzke Jul 30, 2025
a898385
added allocateAndRegister on OnChainAllocator
mgretzke Aug 1, 2025
254c4d1
remove fillerData input
mgretzke Aug 1, 2025
bae6cbc
removed unused input
mgretzke Aug 1, 2025
cad5102
tests, fixes, improvements
mgretzke Aug 7, 2025
891743c
sanitize and natspec
mgretzke Aug 8, 2025
09ca4db
small fixes
mgretzke Aug 8, 2025
a2ef834
added support for IOnChainAllocator
mgretzke Aug 8, 2025
c011063
improved contracts
mgretzke Aug 9, 2025
ad42c29
eliminate double logic + fixes + tests
mgretzke Aug 9, 2025
ce4fff2
fixed issues
mgretzke Aug 9, 2025
a1c74eb
improved signer management
mgretzke Aug 10, 2025
242fb55
use IOnChainAllocation directly from the-compact
mgretzke Aug 10, 2025
35a3a3e
Merge pull request #11 from Uniswap/IOnChainAllocation
mgretzke Aug 10, 2025
98ca8e9
Merge pull request #10 from Uniswap/on-chain-allocator
mgretzke Aug 10, 2025
1f54dfe
chore: remove unused imports
KumaCrypto Aug 18, 2025
94d1b02
chore: remove unused variable
KumaCrypto Aug 18, 2025
8484341
updated nonce setup
mgretzke Aug 19, 2025
d51cc9d
Reworked ERC7683 contracts
mgretzke Aug 19, 2025
ef8f741
Merge pull request #12 from KumaCrypto/clean-up-codebase
ccashwell Aug 19, 2025
4b647fb
fixes and updated tests
mgretzke Aug 22, 2025
37fb6bf
updated nonce setup
mgretzke Aug 19, 2025
20ead37
Reworked ERC7683 contracts
mgretzke Aug 19, 2025
1208bcb
fixes and updated tests
mgretzke Aug 22, 2025
de477e7
snapshot update
mgretzke Aug 22, 2025
c20f3f7
Merge branch 'new-mandate' of https://github.com/Uniswap/sc-allocator…
mgretzke Aug 22, 2025
72ef9bb
natspec, fixes and cleanup
mgretzke Aug 25, 2025
4c64d60
Merge pull request #13 from Uniswap/new-mandate
mgretzke Aug 25, 2025
e38e273
nonce fix
mgretzke Aug 25, 2025
b574683
continue deployment if the allocator was pre-registered
mgretzke Aug 26, 2025
3751a68
fixes and tests
mgretzke Aug 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
[submodule "lib/forge-gas-snapshot"]
path = lib/forge-gas-snapshot
url = https://github.com/marktoda/forge-gas-snapshot
[submodule "lib/the-compact"]
path = lib/the-compact
url = https://github.com/uniswap/the-compact
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/solady"]
path = lib/solady
url = https://github.com/vectorized/solady
[submodule "lib/the-compact"]
path = lib/the-compact
url = https://github.com/Uniswap/the-compact
branch = v1
[submodule "lib/tribunal"]
path = lib/tribunal
url = https://github.com/Uniswap/tribunal
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ remappings = [
"@openzeppelin/contracts=lib/openzeppelin-contracts/contracts",
"@openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts",
"@uniswap/the-compact=lib/the-compact/src",
"@uniswap/tribunal=lib/tribunal/src",
"@solady=lib/solady/src",
]

Expand Down
2 changes: 1 addition & 1 deletion lib/forge-chronicles
Submodule forge-chronicles updated 2 files
+8 −8 extractor.js
+28 −5 index.js
2 changes: 1 addition & 1 deletion lib/forge-std
Submodule forge-std updated 51 files
+1 −0 .github/CODEOWNERS
+54 −100 .github/workflows/ci.yml
+193 −0 CONTRIBUTING.md
+20 −4 README.md
+12 −0 RELEASE_CHECKLIST.md
+3 −1 foundry.toml
+1 −1 package.json
+12 −1 scripts/vm.py
+16 −9 src/Base.sol
+1 −0 src/Script.sol
+142 −47 src/StdAssertions.sol
+40 −4 src/StdChains.sol
+17 −5 src/StdCheats.sol
+30 −0 src/StdConstants.sol
+18 −3 src/StdInvariant.sol
+104 −0 src/StdJson.sol
+3 −3 src/StdStorage.sol
+104 −0 src/StdToml.sol
+0 −18 src/StdUtils.sol
+1 −0 src/Test.sol
+802 −82 src/Vm.sol
+635 −608 src/console.sol
+1 −1,555 src/console2.sol
+1 −1 src/interfaces/IERC1155.sol
+3 −3 src/interfaces/IERC4626.sol
+72 −0 src/interfaces/IERC6909.sol
+1 −1 src/interfaces/IERC721.sol
+150 −0 src/interfaces/IERC7540.sol
+241 −0 src/interfaces/IERC7575.sol
+0 −234 src/mocks/MockERC20.sol
+0 −235 src/mocks/MockERC721.sol
+693 −4 src/safeconsole.sol
+44 −0 test/CommonBase.t.sol
+1 −5 test/StdAssertions.t.sol
+26 −20 test/StdChains.t.sol
+55 −34 test/StdCheats.t.sol
+38 −0 test/StdConstants.t.sol
+12 −12 test/StdError.t.sol
+1 −1 test/StdJson.t.sol
+4 −14 test/StdMath.t.sol
+33 −8 test/StdStorage.t.sol
+1 −1 test/StdStyle.t.sol
+1 −1 test/StdToml.t.sol
+12 −12 test/StdUtils.t.sol
+9 −6 test/Vm.t.sol
+1 −1 test/compilation/CompilationScript.sol
+1 −1 test/compilation/CompilationScriptBase.sol
+1 −1 test/compilation/CompilationTest.sol
+1 −1 test/compilation/CompilationTestBase.sol
+0 −441 test/mocks/MockERC20.t.sol
+0 −721 test/mocks/MockERC721.t.sol
2 changes: 1 addition & 1 deletion lib/openzeppelin-contracts
2 changes: 1 addition & 1 deletion lib/solady
Submodule solady updated 184 files
2 changes: 1 addition & 1 deletion lib/the-compact
Submodule the-compact updated 148 files
1 change: 1 addition & 0 deletions lib/tribunal
Submodule tribunal added at 21b6e8
3 changes: 3 additions & 0 deletions snapshots/ERC7683Allocator_open.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"open_simpleOrder": "168301"
}
3 changes: 3 additions & 0 deletions snapshots/ERC7683Allocator_openFor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"openFor_simpleOrder_userHimself": "171750"
}
10 changes: 10 additions & 0 deletions snapshots/HybridAllocatorTest.json
Original file line number Diff line number Diff line change
@@ -0,0 +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"
}
9 changes: 9 additions & 0 deletions snapshots/OnChainAllocatorTest.json
Original file line number Diff line number Diff line change
@@ -0,0 +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"
}
156 changes: 156 additions & 0 deletions src/allocators/ERC7683Allocator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.27;

import {IOriginSettler} from '../interfaces/ERC7683/IOriginSettler.sol';
import {IERC7683Allocator} from '../interfaces/IERC7683Allocator.sol';
import {OnChainAllocator} from './OnChainAllocator.sol';
import {AllocatorLib as AL} from './lib/AllocatorLib.sol';
import {ERC7683AllocatorLib as ERC7683AL} from './lib/ERC7683AllocatorLib.sol';

import {Tribunal} from '@uniswap/tribunal/Tribunal.sol';
import {Fill, Mandate, RecipientCallback} from '@uniswap/tribunal/types/TribunalStructs.sol';

import {IAllocator} from '@uniswap/the-compact/interfaces/IAllocator.sol';
import {ITheCompact} from '@uniswap/the-compact/interfaces/ITheCompact.sol';
import {
COMPACT_TYPEHASH_WITH_MANDATE,
COMPACT_WITH_MANDATE_TYPESTRING,
MANDATE_BATCH_COMPACT_TYPEHASH,
MANDATE_FILL_TYPEHASH,
MANDATE_RECIPIENT_CALLBACK_TYPEHASH,
MANDATE_TYPEHASH
} from '@uniswap/tribunal/types/TribunalTypeHashes.sol';

import {LibBytes} from '@solady/utils/LibBytes.sol';
import {BatchCompact, Lock} from '@uniswap/the-compact/types/EIP712Types.sol';

/// @title ERC7683Allocator
/// @notice Allocates tokens deposited into the compact and broadcasts orders following the ERC7683 standard.
/// @dev The contract ensures tokens can not be double spent by a user in a fully decentralized manner.
/// @dev Users can open orders for themselves or for others by providing a signature or the tokens directly.
/// @custom:security-contact security@uniswap.org
contract ERC7683Allocator is OnChainAllocator, IERC7683Allocator {
constructor(address compact) OnChainAllocator(compact) {}

/// @inheritdoc IOriginSettler
function openFor(GaslessCrossChainOrder calldata order, bytes calldata sponsorSignature, bytes calldata) external {
(
IERC7683Allocator.Order calldata orderData,
uint32 deposit,
bytes32 mandateHash,
IOriginSettler.ResolvedCrossChainOrder memory resolvedOrder
) = ERC7683AL.openForPreparation(order, sponsorSignature);

// Early revert if the expected nonce is not the next nonce and the order does not include a deposit
if (deposit == 0 && order.nonce != _getNonce(address(0), order.user)) {
revert InvalidNonce(order.nonce, _getNonce(address(0), order.user));
}

uint256 nonce;
if (deposit == 0) {
// Register the allocation on chain
(, nonce) = allocateFor(
order.user,
orderData.commitments,
orderData.arbiter,
order.openDeadline,
COMPACT_TYPEHASH_WITH_MANDATE,
mandateHash,
sponsorSignature
);
} else {
// Register the allocation on chain by using a deposit
uint256[] memory registeredAmounts;
(, registeredAmounts, nonce) = allocateAndRegister(
order.user,
orderData.commitments,
orderData.arbiter,
order.openDeadline,
COMPACT_TYPEHASH_WITH_MANDATE,
mandateHash
);

// We ignore order.nonce and use the one assigned by the allocator
resolvedOrder.orderId = bytes32(nonce);

// Update the resolved order with the registered amounts
for (uint256 i = 0; i < orderData.commitments.length; i++) {
resolvedOrder.minReceived[i].amount = registeredAmounts[i];
}
}
// Emit an open event
emit Open(bytes32(nonce), resolvedOrder);
}

/// @inheritdoc IOriginSettler
function open(OnchainCrossChainOrder calldata order) external {
(IERC7683Allocator.Order calldata orderData, uint32 expires, bytes32 mandateHash, bytes32[] memory fillHashes) =
ERC7683AL.openPreparation(order);

// Register the allocation on chain
(bytes32 claimHash, uint256 nonce) =
allocate(orderData.commitments, orderData.arbiter, expires, COMPACT_TYPEHASH_WITH_MANDATE, mandateHash);

// Ensure a registration exists before opening the order
if (!ITheCompact(COMPACT_CONTRACT).isRegistered(msg.sender, claimHash, COMPACT_TYPEHASH_WITH_MANDATE)) {
revert InvalidRegistration(msg.sender, claimHash);
}

ResolvedCrossChainOrder memory resolvedOrder =
ERC7683AL.resolveOrder(msg.sender, nonce, expires, fillHashes, orderData, LibBytes.emptyCalldata());

// Emit an open event
emit Open(bytes32(nonce), resolvedOrder);
}

/// @inheritdoc IOriginSettler
function resolveFor(GaslessCrossChainOrder calldata order, bytes calldata)
external
view
returns (ResolvedCrossChainOrder memory)
{
(, uint32 deposit,, IOriginSettler.ResolvedCrossChainOrder memory resolvedOrder) =
ERC7683AL.openForPreparation(order, LibBytes.emptyCalldata());

// Revert if the expected nonce is not the next nonce and the order does not include a deposit
if (deposit == 0 && order.nonce != _getNonce(address(0), order.user)) {
revert InvalidNonce(order.nonce, _getNonce(address(0), order.user));
} else if (deposit == 1) {
// We ignore the order.nonce and use the one assigned by the allocator
resolvedOrder.orderId = bytes32(_getNonce(msg.sender, order.user));
}

return resolvedOrder;
}

/// @inheritdoc IOriginSettler
function resolve(OnchainCrossChainOrder calldata order) external view returns (ResolvedCrossChainOrder memory) {
(IERC7683Allocator.Order calldata orderData, uint32 expires,, bytes32[] memory fillHashes) =
ERC7683AL.openPreparation(order);

return ERC7683AL.resolveOrder(
msg.sender, _getNonce(address(0), msg.sender), expires, fillHashes, orderData, LibBytes.emptyCalldata()
);
}

/// @inheritdoc IERC7683Allocator
function getCompactWitnessTypeString() external pure returns (string memory) {
return COMPACT_WITH_MANDATE_TYPESTRING;
}

/// @inheritdoc IERC7683Allocator
function getNonce(GaslessCrossChainOrder calldata order, address caller) external view returns (uint256 nonce) {
(, uint32 deposit) = ERC7683AL.decodeOrderData(order.orderData);
deposit = ERC7683AL.sanitizeBool(deposit);

caller = address(uint160(deposit * uint160(caller))); // for a deposit, the nonce will be scoped to the caller + user

return _getNonce(address(caller), order.user);
}

/// @inheritdoc IERC7683Allocator
function createFillerData(address claimant) external pure returns (bytes memory fillerData) {
return abi.encode(claimant);
}
}
Loading
Loading