Skip to content

Commit

Permalink
refactor split components
Browse files Browse the repository at this point in the history
  • Loading branch information
0age committed Oct 18, 2024
1 parent 08dcf7f commit 59f4791
Showing 1 changed file with 186 additions and 46 deletions.
232 changes: 186 additions & 46 deletions src/TheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -650,22 +650,6 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
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 {
expires.later();

messageHash.signedBy(sponsor, sponsorSignature, sponsorDomainSeparator);
qualificationMessageHash.signedBy(allocator, allocatorSignature, _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID));
}

function _notExpiredAndSignedByBoth(
uint256 expires,
bytes32 messageHash,
Expand Down Expand Up @@ -745,6 +729,13 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
return _processClaimWithQualificationAndSponsorDomain(messageHash, messageHash, calldataPointer, offsetToId, bytes32(0), operation);
}

function _processSimpleSplitClaim(bytes32 messageHash, uint256 calldataPointer, uint256 offsetToId, function(address, address, uint256, uint256) internal returns (bool) operation)
internal
returns (bool)
{
return _processSplitClaimWithQualificationAndSponsorDomain(messageHash, messageHash, calldataPointer, offsetToId, bytes32(0), operation);
}

function _processClaimWithSponsorDomain(
bytes32 messageHash,
uint256 calldataPointer,
Expand All @@ -765,6 +756,16 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
return _processClaimWithQualificationAndSponsorDomain(messageHash, qualificationMessageHash, calldataPointer, offsetToId, bytes32(0), operation);
}

function _processSplitClaimWithQualification(
bytes32 messageHash,
bytes32 qualificationMessageHash,
uint256 calldataPointer,
uint256 offsetToId,
function(address, address, uint256, uint256) internal returns (bool) operation
) internal returns (bool) {
return _processSplitClaimWithQualificationAndSponsorDomain(messageHash, qualificationMessageHash, calldataPointer, offsetToId, bytes32(0), operation);
}

function _processClaimWithQualificationAndSponsorDomain(
bytes32 messageHash,
bytes32 qualificationMessageHash,
Expand Down Expand Up @@ -828,6 +829,68 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
return operation(sponsor, claimant, id, amount);
}

function _processSplitClaimWithQualificationAndSponsorDomain(
bytes32 messageHash,
bytes32 qualificationMessageHash,
uint256 calldataPointer,
uint256 offsetToId,
bytes32 sponsorDomainSeparator,
function(address, address, uint256, uint256) internal returns (bool) operation
) internal returns (bool) {
bytes calldata allocatorSignature;
bytes calldata sponsorSignature;
address sponsor;
uint256 nonce;
uint256 expires;

uint256 id;
uint256 allocatedAmount;
SplitComponent[] calldata claimants;

assembly {
let allocatorSignaturePtr := add(calldataPointer, calldataload(calldataPointer))
allocatorSignature.offset := add(0x20, allocatorSignaturePtr)
allocatorSignature.length := calldataload(allocatorSignaturePtr)

let sponsorSignaturePtr := add(calldataPointer, calldataload(add(calldataPointer, 0x20)))
sponsorSignature.offset := add(0x20, sponsorSignaturePtr)
sponsorSignature.length := calldataload(sponsorSignaturePtr)

sponsor := calldataload(add(calldataPointer, 0x40)) // TODO: sanitize
nonce := calldataload(add(calldataPointer, 0x60))
expires := calldataload(add(calldataPointer, 0x80))

let calldataPointerWithOffset := add(calldataPointer, offsetToId)
id := calldataload(calldataPointerWithOffset)
allocatedAmount := calldataload(add(calldataPointerWithOffset, 0x20))

let claimantsPtr := add(calldataPointer, calldataload(add(calldataPointerWithOffset, 0x40)))
claimants.offset := add(0x20, claimantsPtr)
claimants.length := calldataload(claimantsPtr)
}

expires.later();

uint96 allocatorId = id.toAllocatorId();
address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(nonce);

if ((sponsorDomainSeparator != bytes32(0)).and(id.toScope() != Scope.Multichain)) {
revert InvalidScope(id);
}

bytes32 domainSeparator = _INITIAL_DOMAIN_SEPARATOR.toLatest(_INITIAL_CHAIN_ID);
assembly {
sponsorDomainSeparator := add(sponsorDomainSeparator, mul(iszero(sponsorDomainSeparator), domainSeparator))
}

messageHash.signedBy(sponsor, sponsorSignature, sponsorDomainSeparator);
qualificationMessageHash.signedBy(allocator, allocatorSignature, domainSeparator);

_emitClaim(sponsor, messageHash, allocator);

return _verifyAndProcessSplitComponents(sponsor, id, allocatedAmount, claimants, operation);
}

function usingBasicClaim(
function(
bytes32,
Expand All @@ -852,6 +915,54 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
}
}

function usingSplitClaim(
function(
bytes32,
uint256,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnIn
)
internal
pure
returns (
function(
bytes32,
SplitClaim calldata,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnOut
)
{
assembly {
fnOut := fnIn
}
}

function usingSplitClaimWithWitness(
function(
bytes32,
uint256,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnIn
)
internal
pure
returns (
function(
bytes32,
SplitClaimWithWitness calldata,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnOut
)
{
assembly {
fnOut := fnIn
}
}

function usingMultichainClaim(
function(
bytes32,
Expand Down Expand Up @@ -928,6 +1039,58 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
}
}

function usingQualifiedSplitClaim(
function(
bytes32,
bytes32,
uint256,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnIn
)
internal
pure
returns (
function(
bytes32,
bytes32,
QualifiedSplitClaim calldata,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnOut
)
{
assembly {
fnOut := fnIn
}
}

function usingQualifiedSplitClaimWithWitness(
function(
bytes32,
bytes32,
uint256,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnIn
)
internal
pure
returns (
function(
bytes32,
bytes32,
QualifiedSplitClaimWithWitness calldata,
uint256,
function(address, address, uint256, uint256) internal returns (bool)
) internal returns (bool) fnOut
)
{
assembly {
fnOut := fnIn
}
}

function usingQualifiedClaimWithWitness(
function(
bytes32,
Expand Down Expand Up @@ -1215,45 +1378,24 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
}

function _processSplitClaim(SplitClaim calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation) internal returns (bool) {
bytes32 messageHash = claimPayload.toMessageHash();
uint96 allocatorId = claimPayload.id.toAllocatorId();
address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce);
_notExpiredAndSignedByBoth(claimPayload.expires, messageHash, claimPayload.sponsor, claimPayload.sponsorSignature, messageHash, allocator, claimPayload.allocatorSignature);

return _verifyAndProcessSplitComponents(claimPayload.sponsor, messageHash, claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, allocator, operation);
return usingSplitClaim(_processSimpleSplitClaim)(claimPayload.toMessageHash(), claimPayload, 0xa0, operation);
}

function _processQualifiedSplitClaim(QualifiedSplitClaim calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation) internal returns (bool) {
(bytes32 messageHash, bytes32 qualificationMessageHash) = claimPayload.toMessageHash();

uint96 allocatorId = claimPayload.id.toAllocatorId();
address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce);

_notExpiredAndSignedByBoth(claimPayload.expires, messageHash, claimPayload.sponsor, claimPayload.sponsorSignature, qualificationMessageHash, allocator, claimPayload.allocatorSignature);

return _verifyAndProcessSplitComponents(claimPayload.sponsor, messageHash, claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, allocator, operation);
return usingQualifiedSplitClaim(_processSplitClaimWithQualification)(messageHash, qualificationMessageHash, claimPayload, 0xe0, operation);
}

function _processSplitClaimWithWitness(SplitClaimWithWitness calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation) internal returns (bool) {
bytes32 messageHash = claimPayload.toMessageHash();
uint96 allocatorId = claimPayload.id.toAllocatorId();
address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce);
_notExpiredAndSignedByBoth(claimPayload.expires, messageHash, claimPayload.sponsor, claimPayload.sponsorSignature, messageHash, allocator, claimPayload.allocatorSignature);

return _verifyAndProcessSplitComponents(claimPayload.sponsor, messageHash, claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, allocator, operation);
return usingSplitClaimWithWitness(_processSimpleSplitClaim)(claimPayload.toMessageHash(), claimPayload, 0xe0, operation);
}

function _processQualifiedSplitClaimWithWitness(QualifiedSplitClaimWithWitness calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation)
internal
returns (bool)
{
(bytes32 messageHash, bytes32 qualificationMessageHash) = claimPayload.toMessageHash();
uint96 allocatorId = claimPayload.id.toAllocatorId();
address allocator = allocatorId.fromRegisteredAllocatorIdWithConsumed(claimPayload.nonce);

_notExpiredAndSignedByBoth(claimPayload.expires, messageHash, claimPayload.sponsor, claimPayload.sponsorSignature, qualificationMessageHash, allocator, claimPayload.allocatorSignature);

return _verifyAndProcessSplitComponents(claimPayload.sponsor, messageHash, claimPayload.id, claimPayload.allocatedAmount, claimPayload.claimants, allocator, operation);
return usingQualifiedSplitClaimWithWitness(_processSplitClaimWithQualification)(messageHash, qualificationMessageHash, claimPayload, 0x120, operation);
}

function _processBatchClaim(BatchClaim calldata claimPayload, function(address, address, uint256, uint256) internal returns (bool) operation) internal returns (bool) {
Expand Down Expand Up @@ -1429,19 +1571,15 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {

function _verifyAndProcessSplitComponents(
address sponsor,
bytes32 messageHash,
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];
Expand Down Expand Up @@ -1480,12 +1618,14 @@ contract TheCompact is ITheCompact, ERC6909, Extsload {
uint256 totalClaims = claims.length;
uint256 errorBuffer = (totalClaims == 0).asUint256();

_emitClaim(sponsor, messageHash, allocator);

unchecked {
for (uint256 i = 0; i < totalClaims; ++i) {
SplitBatchClaimComponent calldata claimComponent = claims[i];
errorBuffer |= (claimComponent.id.toAllocatorId() != allocatorId).asUint256();

_verifyAndProcessSplitComponents(sponsor, messageHash, claimComponent.id, claimComponent.allocatedAmount, claimComponent.portions, allocator, operation);
_verifyAndProcessSplitComponents(sponsor, claimComponent.id, claimComponent.allocatedAmount, claimComponent.portions, operation);
}
}

Expand Down

0 comments on commit 59f4791

Please sign in to comment.