From 051ee6420ea79791312b03572cd2ac3d26a5c9fa Mon Sep 17 00:00:00 2001 From: 0age <37939117+0age@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:46:07 -0700 Subject: [PATCH] clean up Claim event --- src/TheCompact.sol | 358 +++++++++++++++++++-------------- src/interfaces/ITheCompact.sol | 15 +- src/lib/FunctionCastLib.sol | 36 ++-- src/lib/HashLib.sol | 12 +- src/types/Claims.sol | 2 +- test/TheCompact.t.sol | 6 +- 6 files changed, 243 insertions(+), 186 deletions(-) diff --git a/src/TheCompact.sol b/src/TheCompact.sol index 286fb8d..2f6ecc6 100644 --- a/src/TheCompact.sol +++ b/src/TheCompact.sol @@ -21,7 +21,7 @@ import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.so import { BasicTransfer, SplitTransfer, - Claim, + BasicClaim, QualifiedClaim, ClaimWithWitness, QualifiedClaimWithWitness, @@ -88,7 +88,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { using HashLib for uint256; using HashLib for BasicTransfer; using HashLib for SplitTransfer; - using HashLib for Claim; + using HashLib for BasicClaim; using HashLib for QualifiedClaim; using HashLib for ClaimWithWitness; using HashLib for QualifiedClaimWithWitness; @@ -140,14 +140,14 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { using FunctionCastLib for function(TransferComponent[] memory, uint256) internal returns (address); - using FunctionCastLib for function(bytes32, Claim calldata, address) internal view; + using FunctionCastLib for function(bytes32, BasicClaim calldata, address) internal view; using FunctionCastLib for function(bytes32, bytes32, QualifiedClaim calldata, address) internal view; - using FunctionCastLib for function(QualifiedClaim calldata) internal returns (bytes32); + using FunctionCastLib for function(QualifiedClaim calldata) internal returns (bytes32, address); using FunctionCastLib - for function(QualifiedClaimWithWitness calldata) internal returns (bytes32); + for function(QualifiedClaimWithWitness calldata) internal returns (bytes32, address); IPermit2 private constant _PERMIT2 = IPermit2(0x000000000022D473030F116dDEE9F6B43aC78BA3); @@ -404,12 +404,12 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { return _processSplitBatchTransfer(withdrawal, _withdraw); } - function claim(Claim calldata claimPayload) external returns (bool) { - return _processClaim(claimPayload, _release); + function claim(BasicClaim calldata claimPayload) external returns (bool) { + return _processBasicClaim(claimPayload, _release); } - function claimAndWithdraw(Claim calldata claimPayload) external returns (bool) { - return _processClaim(claimPayload, _withdraw); + function claimAndWithdraw(BasicClaim calldata claimPayload) external returns (bool) { + return _processBasicClaim(claimPayload, _withdraw); } function claim(QualifiedClaim calldata claimPayload) external returns (bool) { @@ -685,16 +685,69 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { } } - function _notExpiredAndWithValidSignatures( + function _notExpiredAndSignedByAllocator( bytes32 messageHash, - Claim calldata claimPayload, - address allocator + address allocator, + BasicTransfer calldata transferPayload + ) internal view { + transferPayload.expires.later(); + + messageHash.signedBy( + allocator, + transferPayload.allocatorSignature, + _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID) + ); + } + + function _notExpiredAndSignedByBoth( + uint256 expires, + bytes32 sponsorDomainSeparator, + bytes32 messageHash, + address sponsor, + bytes calldata sponsorSignature, + bytes32 qualificationMessageHash, + address allocator, + bytes calldata allocatorSignature ) internal view { - claimPayload.expires.later(); + expires.later(); + + messageHash.signedBy(sponsor, sponsorSignature, sponsorDomainSeparator); + qualificationMessageHash.signedBy( + allocator, allocatorSignature, _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID) + ); + } + + function _notExpiredAndSignedByBoth( + uint256 expires, + bytes32 messageHash, + address sponsor, + bytes calldata sponsorSignature, + bytes32 qualificationMessageHash, + address allocator, + bytes calldata allocatorSignature + ) internal view { + expires.later(); bytes32 domainSeparator = _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID); - messageHash.signedBy(claimPayload.sponsor, claimPayload.sponsorSignature, domainSeparator); - messageHash.signedBy(allocator, claimPayload.allocatorSignature, domainSeparator); + + messageHash.signedBy(sponsor, sponsorSignature, domainSeparator); + qualificationMessageHash.signedBy(allocator, allocatorSignature, domainSeparator); + } + + function _notExpiredAndWithValidSignatures( + bytes32 messageHash, + BasicClaim calldata claimPayload, + address allocator + ) internal view { + _notExpiredAndSignedByBoth( + claimPayload.expires, + messageHash, + claimPayload.sponsor, + claimPayload.sponsorSignature, + messageHash, + allocator, + claimPayload.allocatorSignature + ); } function _notExpiredAndWithValidSignaturesExogenous( @@ -702,16 +755,16 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { ExogenousMultichainClaim calldata claimPayload, address allocator ) internal view { - claimPayload.expires.later(); - - bytes32 exogenousDomainSeparator = - claimPayload.notarizedChainId.toNotarizedDomainSeparator(); - messageHash.signedBy( - claimPayload.sponsor, claimPayload.sponsorSignature, exogenousDomainSeparator + _notExpiredAndSignedByBoth( + claimPayload.expires, + claimPayload.notarizedChainId.toNotarizedDomainSeparator(), + messageHash, + claimPayload.sponsor, + claimPayload.sponsorSignature, + messageHash, + allocator, + claimPayload.allocatorSignature ); - - bytes32 domainSeparator = _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID); - messageHash.signedBy(allocator, claimPayload.allocatorSignature, domainSeparator); } function _notExpiredAndWithValidQualifiedSignatures( @@ -720,11 +773,14 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { QualifiedClaim calldata claimPayload, address allocator ) internal view { - claimPayload.expires.later(); - bytes32 domainSeparator = _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID); - messageHash.signedBy(claimPayload.sponsor, claimPayload.sponsorSignature, domainSeparator); - qualificationMessageHash.signedBy( - allocator, claimPayload.allocatorSignature, domainSeparator + _notExpiredAndSignedByBoth( + claimPayload.expires, + messageHash, + claimPayload.sponsor, + claimPayload.sponsorSignature, + qualificationMessageHash, + allocator, + claimPayload.allocatorSignature ); } @@ -736,108 +792,71 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { messageHash = claimPayload.toMessageHash(); allocatorId = claimPayload.claims[0].id.toAllocatorId(); - _notExpiredAndWithValidSignatures.usingBatchClaim()( + _notExpiredAndSignedByBoth( + claimPayload.expires, + messageHash, + claimPayload.sponsor, + claimPayload.sponsorSignature, messageHash, - claimPayload, - allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce) + allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce), + claimPayload.allocatorSignature ); } function _notExpiredAndWithValidSignaturesBatchWithWitness( BatchClaimWithWitness calldata claimPayload - ) internal returns (bytes32 messageHash, uint96 allocatorId) { + ) internal returns (bytes32 messageHash, uint96 allocatorId, address allocator) { messageHash = claimPayload.toMessageHash(); allocatorId = claimPayload.claims[0].id.toAllocatorId(); + allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce); - _notExpiredAndWithValidSignatures.usingBatchClaimWithWitness()( + _notExpiredAndSignedByBoth( + claimPayload.expires, messageHash, - claimPayload, - allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce) + claimPayload.sponsor, + claimPayload.sponsorSignature, + messageHash, + allocator, + claimPayload.allocatorSignature ); } // NOTE: this function expects that there's at least one array element function _notExpiredAndWithValidSignaturesQualifiedBatch( QualifiedBatchClaim calldata claimPayload - ) internal returns (bytes32 messageHash, uint96 allocatorId) { + ) internal returns (bytes32 messageHash, uint96 allocatorId, address allocator) { bytes32 qualificationMessageHash; allocatorId = claimPayload.claims[0].id.toAllocatorId(); + allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce); (messageHash, qualificationMessageHash) = claimPayload.toMessageHash(); _notExpiredAndWithValidQualifiedSignatures.usingQualifiedBatchClaim()( - messageHash, - qualificationMessageHash, - claimPayload, - allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce) - ); - } - - function _notExpiredAndWithValidSignaturesQualifiedBatchWithWitness( - QualifiedBatchClaimWithWitness calldata claimPayload - ) internal returns (bytes32 messageHash, uint96 allocatorId) { - bytes32 qualificationMessageHash; - allocatorId = claimPayload.claims[0].id.toAllocatorId(); - (messageHash, qualificationMessageHash) = claimPayload.toMessageHash(); - - _notExpiredAndWithValidQualifiedSignatures.usingQualifiedBatchClaimWithWitness()( - messageHash, - qualificationMessageHash, - claimPayload, - allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce) + messageHash, qualificationMessageHash, claimPayload, allocator ); } function _notExpiredAndWithValidSignaturesQualified(QualifiedClaim calldata claimPayload) internal - returns (bytes32 messageHash) + returns (bytes32 messageHash, address allocator) { bytes32 qualificationMessageHash; (messageHash, qualificationMessageHash) = claimPayload.toMessageHash(); + allocator = claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); _notExpiredAndWithValidQualifiedSignatures( - messageHash, - qualificationMessageHash, - claimPayload, - claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) + messageHash, qualificationMessageHash, claimPayload, allocator ); } - function _notExpiredAndWithValidSignaturesWithWitness( - bytes32 messageHash, - ClaimWithWitness calldata claimPayload, - address allocator - ) internal view { - claimPayload.expires.later(); - bytes32 domainSeparator = _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID); - messageHash.signedBy(claimPayload.sponsor, claimPayload.sponsorSignature, domainSeparator); - messageHash.signedBy(allocator, claimPayload.allocatorSignature, domainSeparator); - } - function _notExpiredAndWithValidSignaturesQualifiedWithWitness( QualifiedClaimWithWitness calldata claimPayload - ) internal returns (bytes32 messageHash) { + ) internal returns (bytes32 messageHash, address allocator) { bytes32 qualificationMessageHash; (messageHash, qualificationMessageHash) = claimPayload.toMessageHash(); + allocator = claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); _notExpiredAndWithValidQualifiedSignatures.usingQualifiedClaimWithWitness()( - messageHash, - qualificationMessageHash, - claimPayload, - claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) - ); - } - - function _notExpiredAndSignedByAllocator( - bytes32 messageHash, - address allocator, - BasicTransfer calldata transferPayload - ) internal view { - transferPayload.expires.later(); - - messageHash.signedBy( - allocator, - transferPayload.allocatorSignature, - _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID) + messageHash, qualificationMessageHash, claimPayload, allocator ); } @@ -924,16 +943,13 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { return true; } - function _processClaim( - Claim calldata claimPayload, + function _processBasicClaim( + BasicClaim calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { bytes32 messageHash = claimPayload.toMessageHash(); - _notExpiredAndWithValidSignatures( - messageHash, - claimPayload, - claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) - ); + address allocator = claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); + _notExpiredAndWithValidSignatures(messageHash, claimPayload, allocator); claimPayload.amount.withinAllocated(claimPayload.allocatedAmount); @@ -943,6 +959,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { claimPayload.id, messageHash, claimPayload.amount, + allocator, operation ); } @@ -952,11 +969,10 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { bytes32 messageHash = claimPayload.toMessageHash(); + address allocator = claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); _notExpiredAndWithValidSignatures.usingMultichainClaim()( - messageHash, - claimPayload, - claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) + messageHash, claimPayload, allocator ); claimPayload.amount.withinAllocated(claimPayload.allocatedAmount); @@ -967,6 +983,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { claimPayload.id, messageHash, claimPayload.amount, + allocator, operation ); } @@ -979,10 +996,9 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { uint256 id = claimPayload.id; uint256 amount = claimPayload.amount; + address allocator = id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); - _notExpiredAndWithValidSignaturesExogenous( - messageHash, claimPayload, id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) - ); + _notExpiredAndWithValidSignaturesExogenous(messageHash, claimPayload, allocator); if (id.toScope() != Scope.Multichain) { revert InvalidScope(id); @@ -991,7 +1007,13 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { amount.withinAllocated(claimPayload.allocatedAmount); return _emitAndOperate( - claimPayload.sponsor, claimPayload.claimant, id, messageHash, amount, operation + claimPayload.sponsor, + claimPayload.claimant, + id, + messageHash, + amount, + allocator, + operation ); } @@ -1001,12 +1023,15 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { uint256 id, uint256 allocatedAmount, SplitComponent[] calldata claimants, + address allocator, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { uint256 totalClaims = claimants.length; uint256 spentAmount = 0; uint256 errorBuffer = (totalClaims == 0).asUint256(); + _emitClaim(sponsor, messageHash, allocator); + unchecked { for (uint256 i = 0; i < totalClaims; ++i) { SplitComponent calldata component = claimants[i]; @@ -1016,7 +1041,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { errorBuffer |= (updatedSpentAmount < spentAmount).asUint256(); spentAmount = updatedSpentAmount; - _emitAndOperate(sponsor, component.claimant, id, messageHash, amount, operation); + operation(sponsor, component.claimant, id, amount); } } @@ -1039,11 +1064,8 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { bytes32 messageHash = claimPayload.toMessageHash(); - _notExpiredAndWithValidSignatures.usingSplitClaim()( - messageHash, - claimPayload, - claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) - ); + address allocator = claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); + _notExpiredAndWithValidSignatures.usingSplitClaim()(messageHash, claimPayload, allocator); return _verifyAndProcessSplitComponents( claimPayload.sponsor, @@ -1051,6 +1073,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, + allocator, operation ); } @@ -1060,13 +1083,16 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { claimPayload.amount.withinAllocated(claimPayload.allocatedAmount); + (bytes32 messageHash, address allocator) = + _notExpiredAndWithValidSignaturesQualified(claimPayload); return _emitAndOperate( claimPayload.sponsor, claimPayload.claimant, claimPayload.id, - _notExpiredAndWithValidSignaturesQualified(claimPayload), + messageHash, claimPayload.amount, + allocator, operation ); } @@ -1075,12 +1101,15 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { QualifiedSplitClaim calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { + (bytes32 messageHash, address allocator) = + _notExpiredAndWithValidSignaturesQualified.usingQualifiedSplitClaim()(claimPayload); return _verifyAndProcessSplitComponents( claimPayload.sponsor, - _notExpiredAndWithValidSignaturesQualified.usingQualifiedSplitClaim()(claimPayload), + messageHash, claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, + allocator, operation ); } @@ -1090,10 +1119,9 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { bytes32 messageHash = claimPayload.toMessageHash(); + address allocator = claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); _notExpiredAndWithValidSignatures.usingClaimWithWitness()( - messageHash, - claimPayload, - claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) + messageHash, claimPayload, allocator ); claimPayload.amount.withinAllocated(claimPayload.allocatedAmount); @@ -1104,6 +1132,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { claimPayload.id, messageHash, claimPayload.amount, + allocator, operation ); } @@ -1113,10 +1142,9 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { bytes32 messageHash = claimPayload.toMessageHash(); + address allocator = claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce); _notExpiredAndWithValidSignatures.usingSplitClaimWithWitness()( - messageHash, - claimPayload, - claimPayload.id.toRegisteredAllocatorWithConsumed(claimPayload.nonce) + messageHash, claimPayload, allocator ); return _verifyAndProcessSplitComponents( @@ -1125,19 +1153,28 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, + allocator, operation ); } + function _emitClaim(address sponsor, bytes32 messageHash, address allocator) + internal + returns (bool) + { + emit Claim(sponsor, allocator, msg.sender, messageHash); + } + function _emitAndOperate( address sponsor, address claimant, uint256 id, bytes32 messageHash, uint256 amount, + address allocator, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { - emit Claimed(sponsor, claimant, id, messageHash, amount); + _emitClaim(sponsor, messageHash, allocator); return operation(sponsor, claimant, id, amount); } @@ -1147,13 +1184,16 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { claimPayload.amount.withinAllocated(claimPayload.allocatedAmount); + (bytes32 messageHash, address allocator) = + _notExpiredAndWithValidSignaturesQualifiedWithWitness(claimPayload); return _emitAndOperate( claimPayload.sponsor, claimPayload.claimant, claimPayload.id, - _notExpiredAndWithValidSignaturesQualifiedWithWitness(claimPayload), + messageHash, claimPayload.amount, + allocator, operation ); } @@ -1162,13 +1202,18 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { QualifiedSplitClaimWithWitness calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { + (bytes32 messageHash, address allocator) = + _notExpiredAndWithValidSignaturesQualifiedWithWitness.usingSplitClaimQualifiedWithWitness()( + claimPayload + ); + return _verifyAndProcessSplitComponents( claimPayload.sponsor, - _notExpiredAndWithValidSignaturesQualifiedWithWitness - .usingSplitClaimQualifiedWithWitness()(claimPayload), + messageHash, claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, + allocator, operation ); } @@ -1179,6 +1224,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { address claimant, bytes32 messageHash, BatchClaimComponent[] calldata claims, + address allocator, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { uint256 totalClaims = claims.length; @@ -1190,7 +1236,9 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { BatchClaimComponent calldata component = claims[0]; uint256 errorBuffer = (component.allocatedAmount < component.amount).asUint256(); - _emitAndOperate(sponsor, claimant, component.id, messageHash, component.amount, operation); + _emitClaim(sponsor, messageHash, allocator); + + operation(sponsor, claimant, component.id, component.amount); unchecked { for (uint256 i = 1; i < totalClaims; ++i) { @@ -1199,9 +1247,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { component.allocatedAmount < component.amount ).asUint256(); - _emitAndOperate( - sponsor, claimant, component.id, messageHash, component.amount, operation - ); + operation(sponsor, claimant, component.id, component.amount); } } if (errorBuffer.asBool()) { @@ -1222,6 +1268,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { address sponsor, bytes32 messageHash, SplitBatchClaimComponent[] calldata claims, + address allocator, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { uint256 totalClaims = claims.length; @@ -1238,6 +1285,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { claimComponent.id, claimComponent.allocatedAmount, claimComponent.portions, + allocator, operation ); } @@ -1256,12 +1304,9 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { ) internal returns (bool) { bytes32 messageHash = batchClaim.toMessageHash(); uint96 allocatorId = batchClaim.claims[0].id.toAllocatorId(); + address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce); - _notExpiredAndWithValidSignatures.usingBatchClaim()( - messageHash, - batchClaim, - allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce) - ); + _notExpiredAndWithValidSignatures.usingBatchClaim()(messageHash, batchClaim, allocator); return _verifyAndProcessBatchComponents( allocatorId, @@ -1269,6 +1314,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { batchClaim.claimant, messageHash, batchClaim.claims, + allocator, operation ); } @@ -1279,15 +1325,12 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { ) internal returns (bool) { bytes32 messageHash = batchClaim.toMessageHash(); uint96 allocatorId = batchClaim.claims[0].id.toAllocatorId(); + address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce); - _notExpiredAndWithValidSignatures.usingSplitBatchClaim()( - messageHash, - batchClaim, - allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce) - ); + _notExpiredAndWithValidSignatures.usingSplitBatchClaim()(messageHash, batchClaim, allocator); return _verifyAndProcessSplitBatchComponents( - allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, operation + allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, allocator, operation ); } @@ -1297,16 +1340,14 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { ) internal returns (bool) { (bytes32 messageHash, bytes32 qualifiedMessageHash) = batchClaim.toMessageHash(); uint96 allocatorId = batchClaim.claims[0].id.toAllocatorId(); + address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce); _notExpiredAndWithValidQualifiedSignatures.usingQualifiedSplitBatchClaim()( - messageHash, - qualifiedMessageHash, - batchClaim, - allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce) + messageHash, qualifiedMessageHash, batchClaim, allocator ); return _verifyAndProcessSplitBatchComponents( - allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, operation + allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, allocator, operation ); } @@ -1316,16 +1357,14 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { ) internal returns (bool) { (bytes32 messageHash, bytes32 qualifiedMessageHash) = batchClaim.toMessageHash(); uint96 allocatorId = batchClaim.claims[0].id.toAllocatorId(); + address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce); _notExpiredAndWithValidQualifiedSignatures.usingQualifiedSplitBatchClaimWithWitness()( - messageHash, - qualifiedMessageHash, - batchClaim, - allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce) + messageHash, qualifiedMessageHash, batchClaim, allocator ); return _verifyAndProcessSplitBatchComponents( - allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, operation + allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, allocator, operation ); } @@ -1335,15 +1374,14 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { ) internal returns (bool) { bytes32 messageHash = batchClaim.toMessageHash(); uint96 allocatorId = batchClaim.claims[0].id.toAllocatorId(); + address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce); _notExpiredAndWithValidSignatures.usingSplitBatchClaimWithWitness()( - messageHash, - batchClaim, - allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce) + messageHash, batchClaim, allocator ); return _verifyAndProcessSplitBatchComponents( - allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, operation + allocatorId, batchClaim.sponsor, messageHash, batchClaim.claims, allocator, operation ); } @@ -1351,7 +1389,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { QualifiedBatchClaim calldata batchClaim, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { - (bytes32 messageHash, uint96 allocatorId) = + (bytes32 messageHash, uint96 allocatorId, address allocator) = _notExpiredAndWithValidSignaturesQualifiedBatch(batchClaim); return _verifyAndProcessBatchComponents( @@ -1360,6 +1398,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { batchClaim.claimant, messageHash, batchClaim.claims, + allocator, operation ); } @@ -1368,7 +1407,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { BatchClaimWithWitness calldata batchClaim, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { - (bytes32 messageHash, uint96 allocatorId) = + (bytes32 messageHash, uint96 allocatorId, address allocator) = _notExpiredAndWithValidSignaturesBatchWithWitness(batchClaim); return _verifyAndProcessBatchComponents( @@ -1377,6 +1416,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { batchClaim.claimant, messageHash, batchClaim.claims, + allocator, operation ); } @@ -1385,8 +1425,13 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { QualifiedBatchClaimWithWitness calldata batchClaim, function(address, address, uint256, uint256) internal returns (bool) operation ) internal returns (bool) { - (bytes32 messageHash, uint96 allocatorId) = - _notExpiredAndWithValidSignaturesQualifiedBatchWithWitness(batchClaim); + uint96 allocatorId = batchClaim.claims[0].id.toAllocatorId(); + address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(batchClaim.nonce); + (bytes32 messageHash, bytes32 qualificationMessageHash) = batchClaim.toMessageHash(); + + _notExpiredAndWithValidQualifiedSignatures.usingQualifiedBatchClaimWithWitness()( + messageHash, qualificationMessageHash, batchClaim, allocator + ); return _verifyAndProcessBatchComponents( allocatorId, @@ -1394,6 +1439,7 @@ contract TheCompact is ITheCompact, ERC6909, Extsload { batchClaim.claimant, messageHash, batchClaim.claims, + allocator, operation ); } diff --git a/src/interfaces/ITheCompact.sol b/src/interfaces/ITheCompact.sol index c87b6cf..cf47c94 100644 --- a/src/interfaces/ITheCompact.sol +++ b/src/interfaces/ITheCompact.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.27; import { ForcedWithdrawalStatus } from "../types/ForcedWithdrawalStatus.sol"; import { ResetPeriod } from "../types/ResetPeriod.sol"; import { Scope } from "../types/Scope.sol"; -import { Claim, BasicTransfer } from "../types/Claims.sol"; +import { BasicClaim, BasicTransfer } from "../types/Claims.sol"; import { BatchClaim } from "../types/BatchClaims.sol"; import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol"; @@ -23,12 +23,11 @@ interface ITheCompact { uint256 indexed id, uint256 depositedAmount ); - event Claimed( + event Claim( address indexed sponsor, - address indexed claimant, - uint256 indexed id, - bytes32 claimHash, - uint256 claimAmount + address indexed allocator, + address indexed arbiter, + bytes32 claimHash ); event Withdrawal( address indexed account, @@ -99,11 +98,11 @@ interface ITheCompact { function allocatedWithdrawal(BasicTransfer memory transfer) external returns (bool); - function claim(Claim memory claim) external returns (bool); + function claim(BasicClaim memory claim) external returns (bool); function claim(BatchClaim memory claim) external returns (bool); - function claimAndWithdraw(Claim memory claim) external returns (bool); + function claimAndWithdraw(BasicClaim memory claim) external returns (bool); function enableForcedWithdrawal(uint256 id) external returns (uint256 withdrawableAt); diff --git a/src/lib/FunctionCastLib.sol b/src/lib/FunctionCastLib.sol index 34f9a63..39a11ee 100644 --- a/src/lib/FunctionCastLib.sol +++ b/src/lib/FunctionCastLib.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.27; import { BasicTransfer, SplitTransfer, - Claim, + BasicClaim, QualifiedClaim, ClaimWithWitness, QualifiedClaimWithWitness, @@ -279,7 +279,7 @@ library FunctionCastLib { } } - function usingSplitClaim(function (Claim calldata) internal view returns (bytes32) fnIn) + function usingSplitClaim(function (BasicClaim calldata) internal view returns (bytes32) fnIn) internal pure returns (function (SplitClaim calldata) internal view returns (bytes32) fnOut) @@ -316,7 +316,9 @@ library FunctionCastLib { } } - function usingClaimWithWitness(function (bytes32, Claim calldata, address) internal view fnIn) + function usingClaimWithWitness( + function (bytes32, BasicClaim calldata, address) internal view fnIn + ) internal pure returns (function (bytes32, ClaimWithWitness calldata, address) internal view fnOut) @@ -327,7 +329,7 @@ library FunctionCastLib { } function usingSplitClaimWithWitness( - function(bytes32, Claim calldata, address) internal view fnIn + function(bytes32, BasicClaim calldata, address) internal view fnIn ) internal pure @@ -338,7 +340,7 @@ library FunctionCastLib { } } - function usingSplitClaim(function(bytes32, Claim calldata, address) internal view fnIn) + function usingSplitClaim(function(bytes32, BasicClaim calldata, address) internal view fnIn) internal pure returns (function(bytes32, SplitClaim calldata, address) internal view fnOut) @@ -348,7 +350,7 @@ library FunctionCastLib { } } - function usingBatchClaim(function(bytes32, Claim calldata, address) internal view fnIn) + function usingBatchClaim(function(bytes32, BasicClaim calldata, address) internal view fnIn) internal pure returns (function(bytes32, BatchClaim calldata, address) internal view fnOut) @@ -358,7 +360,9 @@ library FunctionCastLib { } } - function usingSplitBatchClaim(function(bytes32, Claim calldata, address) internal view fnIn) + function usingSplitBatchClaim( + function(bytes32, BasicClaim calldata, address) internal view fnIn + ) internal pure returns (function(bytes32, SplitBatchClaim calldata, address) internal view fnOut) @@ -369,7 +373,7 @@ library FunctionCastLib { } function usingSplitBatchClaimWithWitness( - function(bytes32, Claim calldata, address) internal view fnIn + function(bytes32, BasicClaim calldata, address) internal view fnIn ) internal pure @@ -383,7 +387,7 @@ library FunctionCastLib { } function usingBatchClaimWithWitness( - function(bytes32, Claim calldata, address) internal view fnIn + function(bytes32, BasicClaim calldata, address) internal view fnIn ) internal pure @@ -395,11 +399,11 @@ library FunctionCastLib { } function usingQualifiedSplitClaim( - function(QualifiedClaim calldata) internal returns (bytes32) fnIn + function(QualifiedClaim calldata) internal returns (bytes32, address) fnIn ) internal pure - returns (function(QualifiedSplitClaim calldata) internal returns (bytes32) fnOut) + returns (function(QualifiedSplitClaim calldata) internal returns (bytes32, address) fnOut) { assembly { fnOut := fnIn @@ -479,18 +483,22 @@ library FunctionCastLib { } function usingSplitClaimQualifiedWithWitness( - function(QualifiedClaimWithWitness calldata) internal returns (bytes32) fnIn + function(QualifiedClaimWithWitness calldata) internal returns (bytes32, address) fnIn ) internal pure - returns (function(QualifiedSplitClaimWithWitness calldata) internal returns (bytes32) fnOut) + returns ( + function(QualifiedSplitClaimWithWitness calldata) internal returns (bytes32, address) fnOut + ) { assembly { fnOut := fnIn } } - function usingMultichainClaim(function(bytes32, Claim calldata, address) internal view fnIn) + function usingMultichainClaim( + function(bytes32, BasicClaim calldata, address) internal view fnIn + ) internal pure returns (function(bytes32, MultichainClaim calldata, address) internal view fnOut) diff --git a/src/lib/HashLib.sol b/src/lib/HashLib.sol index 83435e9..e56da9b 100644 --- a/src/lib/HashLib.sol +++ b/src/lib/HashLib.sol @@ -29,7 +29,7 @@ import { import { BasicTransfer, SplitTransfer, - Claim, + BasicClaim, QualifiedClaim, ClaimWithWitness, QualifiedClaimWithWitness, @@ -111,7 +111,7 @@ library HashLib { FunctionCastLib for function(BatchClaimWithWitness calldata, BatchClaimComponent[] calldata) internal view returns (bytes32); - using FunctionCastLib for function(Claim calldata) internal view returns (bytes32); + using FunctionCastLib for function(BasicClaim calldata) internal view returns (bytes32); using FunctionCastLib for function(ClaimWithWitness calldata, uint256) internal view returns (bytes32); @@ -167,7 +167,11 @@ library HashLib { } } - function toClaimMessageHash(Claim calldata claim) internal view returns (bytes32 messageHash) { + function toClaimMessageHash(BasicClaim calldata claim) + internal + view + returns (bytes32 messageHash) + { assembly ("memory-safe") { let m := mload(0x40) // Grab the free memory pointer; memory will be left dirtied. @@ -178,7 +182,7 @@ library HashLib { } } - function toMessageHash(Claim calldata claim) internal view returns (bytes32 messageHash) { + function toMessageHash(BasicClaim calldata claim) internal view returns (bytes32 messageHash) { return toClaimMessageHash(claim); } diff --git a/src/types/Claims.sol b/src/types/Claims.sol index 3f043af..df4fb87 100644 --- a/src/types/Claims.sol +++ b/src/types/Claims.sol @@ -20,7 +20,7 @@ struct SplitTransfer { SplitComponent[] recipients; // The recipients and amounts of each transfer. } -struct Claim { +struct BasicClaim { bytes allocatorSignature; // Authorization from the allocator. bytes sponsorSignature; // Authorization from the sponsor. address sponsor; // The account to source the tokens from. diff --git a/test/TheCompact.t.sol b/test/TheCompact.t.sol index 73ecdf3..a23fce2 100644 --- a/test/TheCompact.t.sol +++ b/test/TheCompact.t.sol @@ -14,7 +14,7 @@ import { HashLib } from "../src/lib/HashLib.sol"; import { BasicTransfer, SplitTransfer, - Claim, + BasicClaim, QualifiedClaim, ClaimWithWitness, QualifiedClaimWithWitness, @@ -1123,7 +1123,7 @@ contract TheCompactTest is Test { (r, vs) = vm.signCompact(allocatorPrivateKey, digest); bytes memory allocatorSignature = abi.encodePacked(r, vs); - Claim memory claim = Claim( + BasicClaim memory claim = BasicClaim( allocatorSignature, sponsorSignature, swapper, @@ -1184,7 +1184,7 @@ contract TheCompactTest is Test { (r, vs) = vm.signCompact(allocatorPrivateKey, digest); bytes memory allocatorSignature = abi.encodePacked(r, vs); - Claim memory claim = Claim( + BasicClaim memory claim = BasicClaim( allocatorSignature, sponsorSignature, swapper,