Skip to content

Commit 10162ae

Browse files
committed
Moved RDA params into qualification data
1 parent af49b8b commit 10162ae

File tree

3 files changed

+99
-24
lines changed

3 files changed

+99
-24
lines changed

src/allocators/ERC7683Allocator.sol

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ pragma solidity ^0.8.27;
55
import {IERC7683Allocator} from '../interfaces/IERC7683Allocator.sol';
66
import {SimpleAllocator} from './SimpleAllocator.sol';
77
import {Claim, Mandate} from './types/TribunalStructs.sol';
8+
9+
import {IERC1271} from '@openzeppelin/contracts/interfaces/IERC1271.sol';
810
import {ECDSA} from '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
911
import {ITheCompact} from '@uniswap/the-compact/interfaces/ITheCompact.sol';
1012
import {Compact} from '@uniswap/the-compact/types/EIP712Types.sol';
@@ -17,9 +19,12 @@ contract ERC7683Allocator is SimpleAllocator, IERC7683Allocator {
1719

1820
/// @notice The typehash of the OrderDataGasless struct
1921
// keccak256("OrderDataGasless(address arbiter,uint256 id,uint256 amount,
20-
// uint256 chainId,address tribunal,address recipient,address token,uint256 minimumAmount,uint256 baselinePriorityFee,uint256 scalingFactor,uint256[] decayCurve,bytes32 salt,uint256 targetBlock,uint256 maximumBlocksAfterTarget)")
22+
// uint256 chainId,address tribunal,address recipient,address token,uint256 minimumAmount,uint256 baselinePriorityFee,uint256 scalingFactor,uint256[] decayCurve,bytes32 salt)")
2123
bytes32 public constant ORDERDATA_GASLESS_TYPEHASH =
22-
0xe6c40de3837db693910c63e423da4d9f6157257aaad00a0786775e629249ee73;
24+
0xe9b624fa654c7f07ce16d31bf0165a4030d4022f62987afad8ef9d30fc8a0b88;
25+
26+
/// @notice keccak256("QualifiedClaim(bytes32 claimHash,uint256 targetBlock,uint256 maximumBlocksAfterTarget)")
27+
bytes32 public constant QUALIFICATION_TYPEHASH = 0x59866b84bd1f6c909cf2a31efd20c59e6c902e50f2c196994e5aa85cdc7d7ce0;
2328

2429
/// @notice keccak256("Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount,Mandate mandate)
2530
// Mandate(uint256 chainId,address tribunal,address recipient,uint256 expires,address token,uint256 minimumAmount,uint256 baselinePriorityFee,uint256 scalingFactor,uint256[] decayCurve,bytes32 salt)")
@@ -163,10 +168,10 @@ contract ERC7683Allocator is SimpleAllocator, IERC7683Allocator {
163168
)
164169
)
165170
);
166-
bytes32 digest = keccak256(abi.encodePacked(bytes2(0x1901), _COMPACT_DOMAIN_SEPARATOR, claimHash));
167171

168172
// We check for the length, which means this could also be triggered by a zero length signature provided in the openFor function. This enables relaying of orders if the claim was registered on the compact.
169173
if (sponsorSignature_.length > 0) {
174+
bytes32 digest = keccak256(abi.encodePacked(bytes2(0x1901), _COMPACT_DOMAIN_SEPARATOR, claimHash));
170175
// confirm the signature matches the digest
171176
address signer = ECDSA.recover(digest, sponsorSignature_);
172177
if (sponsor_ != signer) {
@@ -181,7 +186,13 @@ contract ERC7683Allocator is SimpleAllocator, IERC7683Allocator {
181186
}
182187
}
183188

184-
_sponsor[digest] = tokenHash;
189+
bytes32 qualifiedClaimHash = keccak256(
190+
abi.encode(QUALIFICATION_TYPEHASH, claimHash, orderData_.targetBlock, orderData_.maximumBlocksAfterTarget)
191+
);
192+
bytes32 qualifiedDigest =
193+
keccak256(abi.encodePacked(bytes2(0x1901), _COMPACT_DOMAIN_SEPARATOR, qualifiedClaimHash));
194+
195+
_sponsor[qualifiedDigest] = tokenHash;
185196

186197
// Emit an open event
187198
emit Open(
@@ -207,7 +218,6 @@ contract ERC7683Allocator is SimpleAllocator, IERC7683Allocator {
207218
_claim[tokenHash_] = expires;
208219
_amount[tokenHash_] = amount;
209220
_nonce[tokenHash_] = nonce;
210-
211221
return tokenHash_;
212222
}
213223

@@ -347,8 +357,8 @@ contract ERC7683Allocator is SimpleAllocator, IERC7683Allocator {
347357
scalingFactor: orderDataGasless_.scalingFactor,
348358
decayCurve: orderDataGasless_.decayCurve,
349359
salt: orderDataGasless_.salt,
350-
targetBlock: orderDataGasless_.targetBlock,
351-
maximumBlocksAfterTarget: orderDataGasless_.maximumBlocksAfterTarget
360+
targetBlock: 0,
361+
maximumBlocksAfterTarget: 0
352362
});
353363
return orderData_;
354364
}

src/interfaces/IERC7683Allocator.sol

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ interface IERC7683Allocator is IOriginSettler {
4848
uint256 scalingFactor; // Fee scaling multiplier (1e18 baseline)
4949
uint256[] decayCurve; // Block durations, fill increases, & claim decreases.
5050
bytes32 salt; // Replay protection parameter
51-
// ADDITIONAL INPUT
52-
uint256 targetBlock; // The block number at the target chain on which the PGA is executed / the reverse dutch auction starts.
53-
uint256 maximumBlocksAfterTarget; // Blocks after target block that are still fillable.
5451
}
5552

5653
error InvalidOriginSettler(address originSettler, address expectedOriginSettler);

test/ERC7683Allocator.t.sol

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {TheCompact} from '@uniswap/the-compact/TheCompact.sol';
88
import {ITheCompact} from '@uniswap/the-compact/interfaces/ITheCompact.sol';
99

1010
import {IdLib} from '@uniswap/the-compact/lib/IdLib.sol';
11-
import {ClaimWithWitness} from '@uniswap/the-compact/types/Claims.sol';
11+
import {QualifiedClaimWithWitness} from '@uniswap/the-compact/types/Claims.sol';
1212

1313
import {COMPACT_TYPEHASH, Compact} from '@uniswap/the-compact/types/EIP712Types.sol';
1414
import {ForcedWithdrawalStatus} from '@uniswap/the-compact/types/ForcedWithdrawalStatus.sol';
@@ -251,9 +251,7 @@ abstract contract GaslessCrossChainOrderData is CompactData {
251251
baselinePriorityFee: mandate_.baselinePriorityFee,
252252
scalingFactor: mandate_.scalingFactor,
253253
decayCurve: mandate_.decayCurve,
254-
salt: mandate_.salt,
255-
targetBlock: defaultTargetBlock,
256-
maximumBlocksAfterTarget: defaultMaximumBlocksAfterTarget
254+
salt: mandate_.salt
257255
})
258256
)
259257
});
@@ -289,9 +287,7 @@ abstract contract GaslessCrossChainOrderData is CompactData {
289287
baselinePriorityFee: mandate_.baselinePriorityFee,
290288
scalingFactor: mandate_.scalingFactor,
291289
decayCurve: mandate_.decayCurve,
292-
salt: mandate_.salt,
293-
targetBlock: defaultTargetBlock,
294-
maximumBlocksAfterTarget: defaultMaximumBlocksAfterTarget
290+
salt: mandate_.salt
295291
})
296292
)
297293
});
@@ -533,7 +529,7 @@ contract ERC7683Allocator_openFor is GaslessCrossChainOrderData {
533529
fillInstructions[0] = IOriginSettler.FillInstruction({
534530
destinationChainId: defaultOutputChainId,
535531
destinationSettler: bytes32(uint256(uint160(tribunal))),
536-
originData: abi.encode(claim, _getMandate(), defaultTargetBlock, defaultMaximumBlocksAfterTarget)
532+
originData: abi.encode(claim, _getMandate(), uint256(0), uint256(0))
537533
});
538534

539535
IOriginSettler.ResolvedCrossChainOrder memory resolvedCrossChainOrder = IOriginSettler.ResolvedCrossChainOrder({
@@ -588,7 +584,7 @@ contract ERC7683Allocator_openFor is GaslessCrossChainOrderData {
588584
fillInstructions[0] = IOriginSettler.FillInstruction({
589585
destinationChainId: defaultOutputChainId,
590586
destinationSettler: bytes32(uint256(uint160(tribunal))),
591-
originData: abi.encode(claim, _getMandate(), defaultTargetBlock, defaultMaximumBlocksAfterTarget)
587+
originData: abi.encode(claim, _getMandate(), uint256(0), uint256(0))
592588
});
593589

594590
IOriginSettler.ResolvedCrossChainOrder memory resolvedCrossChainOrder = IOriginSettler.ResolvedCrossChainOrder({
@@ -769,7 +765,11 @@ contract ERC7683Allocator_open is OnChainCrossChainOrderData {
769765
}
770766
}
771767

772-
contract ERC7683Allocator_isValidSignature is OnChainCrossChainOrderData {
768+
contract ERC7683Allocator_isValidSignature is OnChainCrossChainOrderData, GaslessCrossChainOrderData {
769+
function setUp() public override(OnChainCrossChainOrderData, GaslessCrossChainOrderData) {
770+
super.setUp();
771+
}
772+
773773
function test_revert_InvalidLock() public {
774774
// Deposit tokens
775775
vm.startPrank(user);
@@ -796,14 +796,16 @@ contract ERC7683Allocator_isValidSignature is OnChainCrossChainOrderData {
796796
// we do NOT open the order or lock the tokens
797797

798798
// claim should be fail, because we mess with the nonce
799-
ClaimWithWitness memory claim = ClaimWithWitness({
799+
QualifiedClaimWithWitness memory claim = QualifiedClaimWithWitness({
800800
allocatorSignature: '',
801801
sponsorSignature: '',
802802
sponsor: user,
803803
nonce: defaultNonce,
804804
expires: compact_.expires,
805805
witness: keccak256(abi.encode(keccak256(bytes(mandateTypeString)), mandate_)),
806806
witnessTypestring: witnessTypeString,
807+
qualificationTypehash: erc7683Allocator.QUALIFICATION_TYPEHASH(),
808+
qualificationPayload: abi.encode(defaultTargetBlock, defaultMaximumBlocksAfterTarget),
807809
id: usdcId,
808810
allocatedAmount: defaultAmount,
809811
claimant: filler,
@@ -817,7 +819,7 @@ contract ERC7683Allocator_isValidSignature is OnChainCrossChainOrderData {
817819
vm.assertEq(compactContract.balanceOf(filler, usdcId), 0);
818820
}
819821

820-
function test_isValidSignature_successful() public {
822+
function test_isValidSignature_successful_open() public {
821823
// Deposit tokens
822824
vm.startPrank(user);
823825
usdc.mint(user, defaultAmount);
@@ -844,7 +846,71 @@ contract ERC7683Allocator_isValidSignature is OnChainCrossChainOrderData {
844846
vm.stopPrank();
845847

846848
// claim should be successful
847-
ClaimWithWitness memory claim = ClaimWithWitness({
849+
QualifiedClaimWithWitness memory claim = QualifiedClaimWithWitness({
850+
allocatorSignature: '',
851+
sponsorSignature: '',
852+
sponsor: user,
853+
nonce: defaultNonce,
854+
expires: compact_.expires,
855+
witness: keccak256(
856+
abi.encode(
857+
keccak256(bytes(mandateTypeString)),
858+
defaultOutputChainId,
859+
tribunal,
860+
mandate_.recipient,
861+
mandate_.expires,
862+
mandate_.token,
863+
mandate_.minimumAmount,
864+
mandate_.baselinePriorityFee,
865+
mandate_.scalingFactor,
866+
keccak256(abi.encodePacked(mandate_.decayCurve)),
867+
mandate_.salt
868+
)
869+
),
870+
witnessTypestring: witnessTypeString,
871+
qualificationTypehash: erc7683Allocator.QUALIFICATION_TYPEHASH(),
872+
qualificationPayload: abi.encode(defaultTargetBlock, defaultMaximumBlocksAfterTarget),
873+
id: usdcId,
874+
allocatedAmount: defaultAmount,
875+
claimant: filler,
876+
amount: defaultAmount
877+
});
878+
vm.prank(arbiter);
879+
compactContract.claim(claim);
880+
881+
vm.assertEq(compactContract.balanceOf(user, usdcId), 0);
882+
vm.assertEq(compactContract.balanceOf(filler, usdcId), defaultAmount);
883+
}
884+
885+
function test_isValidSignature_successful_openFor() public {
886+
// Deposit tokens
887+
vm.startPrank(user);
888+
usdc.mint(user, defaultAmount);
889+
usdc.approve(address(compactContract), defaultAmount);
890+
compactContract.deposit(
891+
address(usdc), address(erc7683Allocator), defaultResetPeriod, defaultScope, defaultAmount, user
892+
);
893+
894+
// register a claim
895+
Compact memory compact_ = _getCompact();
896+
Mandate memory mandate_ = _getMandate();
897+
898+
bytes32 claimHash = _hashCompact(compact_, mandate_);
899+
bytes32 typeHash = _getTypeHash();
900+
compactContract.register(claimHash, typeHash, defaultResetPeriodTimestamp);
901+
902+
address filler = makeAddr('filler');
903+
vm.assertEq(compactContract.balanceOf(user, usdcId), defaultAmount);
904+
vm.assertEq(compactContract.balanceOf(filler, usdcId), 0);
905+
906+
// we open the order and lock the tokens
907+
(IOriginSettler.GaslessCrossChainOrder memory gaslessCrossChainOrder_, bytes memory sponsorSignature) =
908+
_getGaslessCrossChainOrder();
909+
erc7683Allocator.openFor(gaslessCrossChainOrder_, sponsorSignature, '');
910+
vm.stopPrank();
911+
912+
// claim should be successful
913+
QualifiedClaimWithWitness memory claim = QualifiedClaimWithWitness({
848914
allocatorSignature: '',
849915
sponsorSignature: '',
850916
sponsor: user,
@@ -866,6 +932,8 @@ contract ERC7683Allocator_isValidSignature is OnChainCrossChainOrderData {
866932
)
867933
),
868934
witnessTypestring: witnessTypeString,
935+
qualificationTypehash: erc7683Allocator.QUALIFICATION_TYPEHASH(),
936+
qualificationPayload: abi.encode(uint256(0), uint256(0)),
869937
id: usdcId,
870938
allocatedAmount: defaultAmount,
871939
claimant: filler,
@@ -914,7 +982,7 @@ contract ERC7683Allocator_resolveFor is GaslessCrossChainOrderData {
914982
fillInstructions[0] = IOriginSettler.FillInstruction({
915983
destinationChainId: defaultOutputChainId,
916984
destinationSettler: bytes32(uint256(uint160(tribunal))),
917-
originData: abi.encode(claim, _getMandate(), defaultTargetBlock, defaultMaximumBlocksAfterTarget)
985+
originData: abi.encode(claim, _getMandate(), uint256(0), uint256(0))
918986
});
919987

920988
IOriginSettler.ResolvedCrossChainOrder memory resolvedCrossChainOrder = IOriginSettler.ResolvedCrossChainOrder({

0 commit comments

Comments
 (0)