-
Notifications
You must be signed in to change notification settings - Fork 3
Erc7683 allocator #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0age
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! Left a few comments
src/allocators/ERC7683Allocator.sol
Outdated
| /// @inheritdoc IERC7683Allocator | ||
| function getCompactWitnessTypeString() external pure returns (string memory) { | ||
| return | ||
| 'Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount,Mandate mandate)Mandate(uint256 chainId,address tribunal,address recipient,uint256 expires,address token,uint256 minimumAmount,uint256 baselinePriorityFee,uint256 scalingFactor,bytes32 salt))'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we might just want this to be the fragment, so Mandate mandate)Mandate(uint256 chainId,address tribunal,address recipient,uint256 expires,address token,uint256 minimumAmount,uint256 baselinePriorityFee,uint256 scalingFactor,bytes32 salt)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like both can be useful, since this will be the full type string required for the sponsors signature... should I just implement the fragmented return in an additional function, or really replace this one?
| amount: orderData.amount | ||
| }), | ||
| sponsorSignature: sponsorSignature, | ||
| allocatorSignature: '' // No signature required from this allocator, it will verify the claim on chain via ERC1271. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the HyperlaneTribunal requires that a 64-byte signature be provided in the calldata on the cross-chain message, even if it's not needed; we should probably provide a 64-byte string of 00's just so that fillers can use this directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have an issue with this:
The sponsors signature might also be empty, for example if the user has registered a claim previously and is using the open function to open the order without a signature. So that would also need to be an empty 64-bytes.
While implementing this change and writing the tests (ensuring both allocator and sponsor signature are an empty 64-bytes, instead of just an empty bytes), I realized that the Compact claim function will fail, if you provide an empty 64-byte string for the sponsors signature. This is because the Compact will check for the length of the sponsors signature, and if it is bigger then 0, it will ignore potential registered claims. It will instead rely on the signature verification / ERC1271 (which will both fail for an empty 64-bates signatures). This is the relevant line:
https://github.com/Uniswap/the-compact/blob/c4776fa3264f7c64b26b5800b5f8d8e651089b0a/src/lib/ClaimProcessorLib.sol#L92
So it seems the correct way with the Compact is to actually provide an empty bytes, instead of an empty 64-byte signature. Should we therefor not rather change this in the HyperlaneTribunal contract?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HyperlaneTribunal just expects 64 bytes, but if it's all zeroes it uses an empty string (we could change it there but encoding even an empty dynamic string in solidity is the same amount of calldata!)
| if (orderData.sponsor != msg.sender) { | ||
| revert InvalidSponsor(orderData.sponsor, msg.sender); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we be checking that the token on the minReceived Output matches the token in the ID of the Compact in orderData? just need to strip out the most significant 96 bytes and compare the values
| recipient: _addressToBytes32(orderData.recipient), | ||
| chainId: orderData.chainId | ||
| }); | ||
| Output memory received = Output({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah it looks like we derive it here, makes sense
snreynolds
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i have a lot of questions as this is my first review on this code base :P will follow up with u @vimageDE
src/allocators/ERC7683Allocator.sol
Outdated
| _checkNonce(sponsor_, orderData_.nonce); | ||
|
|
||
| // Check the nonce | ||
| if (_userNonce[orderData_.nonce]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whats the reason to enforce sponsors using certain nonces if the nonces are unordered anyways?
in any case it seems like you could use a bitmap here per sponsor so that its not a clean sstore with every single nonce useage if you wanted to optimize?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To answer the question about using certain nonces:
The reason a specific nonce is enforced in _checkNonce is to ensure the scope of the nonce matches the sponsor. If a user / sponsor could just use any nonce, it would be possible to block orders / signatures by front-running the nonce.
With this design, the user is able to create and select a random unit96 nonce (still incredibly low chances to hit a nonce previously used by him), without having to call a view function to get the next nonce that is scoped to him.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, maybe to provide a crucial piece of information:
The nonce is scoped to the allocator inside of the Compact, not the sponsor. The compact will consume the nonce during the claim process. This ensures replay protection is not dependent on the allocator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented an optimized nonce usage by using a bitmap as suggested!
commit 66fd55f Author: mgretzke <m.gretzke@vimage.de> Date: Fri Aug 1 15:01:56 2025 +0200 cleanup commit fb8f8e5 Merge: 324782a 0ac955d Author: Mark Gretzke <65617397+mgretzke@users.noreply.github.com> Date: Tue Apr 1 14:11:04 2025 +0200 Merge pull request #5 from Uniswap/SimpleAllocator Simple allocator commit 0ac955d Merge: a2fb41b 273e632 Author: Mark Gretzke <65617397+mgretzke@users.noreply.github.com> Date: Tue Apr 1 09:45:16 2025 +0200 Merge pull request #6 from Uniswap/ERC7683Allocator Erc7683 allocator commit 273e632 Merge: 4bed9de 10162ae Author: 0age <37939117+0age@users.noreply.github.com> Date: Thu Mar 27 12:36:19 2025 -0400 Merge pull request #7 from Uniswap/mandate-reverse-dutch-auction Updates to support reversed dutch auction commit a2fb41b Author: vimageDE <m.wierzimok@vimage.de> Date: Thu Mar 6 18:51:00 2025 +0100 enable relayed locks in child contracts commit 32dafd3 Author: vimageDE <m.wierzimok@vimage.de> Date: Wed Mar 5 11:34:37 2025 +0100 use this.attest.selector commit f91a8cc Author: vimageDE <m.wierzimok@vimage.de> Date: Wed Mar 5 11:05:53 2025 +0100 Removed sponsor == operator requirement
Pull Request
Description
Introducing the ERC7683Allocator contract, a fully decentralized on chain allocator that follows ERC7683 as an origin settler.
It is build on top of the SimpleAllocator contract and extends it to follow the IOriginSettler interface.
The contract allows users to distribute their order via an
openevent during the lock process. There are two ways to distribute the order:openfunction is only callable by the sponsor directly and it requires them to have previously registered the claim hash in the CompactopenFor´ function can be called by anyone. The caller must provide a signature proving the users intents, together with theGaslessCrossChainOrder`. This function can also be called without providing a signature, if the user has previously registered a claim hash in the Compact.The token allocation is following the SimpleAllocator design, where all the tokens of a specific ID get locked, no matter how big the amount of the claim is. This makes it easier and more efficient to manage the expiration dates.
A topic still in discussion is the
resolveForfunction. In the current ERC7683 interface, it does not support the signature as an input. This leads to a returnedResolvedCrossChainOrderstruct which does not contain the signature. While this can still be used to simulate the outcome on the destination chain, actually using the returned data would mean a filler would lose their reward, since the signature is required to prove the users intents during the claim. While fillers typically would use the correctResolvedCrossChainOrderstruct that was emitted in theopenevent, it still seems problematic to include a function that potentially returns invalid data.It also includes changes to the foundry.toml, which are required to successfully compile
TheCompactcontract which is used for testing.How Has This Been Tested?
The contract is still in development and neither audited, nor has it been fully tested.