Skip to content
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

create more libs #20

Merged
merged 3 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 27 additions & 27 deletions snapshots/TheCompactTest.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"basicTransfer": "56850",
"basicWithdrawal": "59816",
"batchClaim": "111810",
"batchClaimRegisteredWithDeposit": "111810",
"batchClaimRegisteredWithDepositWithWitness": "112675",
"batchClaimWithWitness": "112669",
"basicTransfer": "56867",
"basicWithdrawal": "59810",
"batchClaim": "112477",
"batchClaimRegisteredWithDeposit": "112477",
"batchClaimRegisteredWithDepositWithWitness": "113236",
"batchClaimWithWitness": "113230",
"batchDepositAndRegisterViaPermit2": "221877",
"batchDepositAndRegisterWithWitnessViaPermit2": "221855",
"batchTransfer": "81520",
"batchWithdrawal": "99951",
"claim": "56817",
"claimAndWithdraw": "73116",
"claimWithWitness": "59462",
"batchTransfer": "81344",
"batchWithdrawal": "99729",
"claim": "56982",
"claimAndWithdraw": "73258",
"claimWithWitness": "59479",
"depositAndRegisterViaPermit2": "124247",
"depositBatchSingleERC20": "67868",
"depositBatchSingleNative": "28171",
Expand All @@ -22,21 +22,21 @@
"depositERC20ViaPermit2AndURI": "98289",
"depositETHAndURI": "26754",
"depositETHBasic": "28391",
"qualifiedBatchClaim": "113348",
"qualifiedBatchClaimWithWitness": "112885",
"qualifiedClaim": "60238",
"qualifiedClaimWithWitness": "58927",
"qualifiedSplitBatchClaim": "140922",
"qualifiedSplitBatchClaimWithWitness": "140987",
"qualifiedSplitClaim": "86554",
"qualifiedSplitClaimWithWitness": "87031",
"qualifiedBatchClaim": "114099",
"qualifiedBatchClaimWithWitness": "113637",
"qualifiedClaim": "60414",
"qualifiedClaimWithWitness": "59106",
"qualifiedSplitBatchClaim": "141456",
"qualifiedSplitBatchClaimWithWitness": "141522",
"qualifiedSplitClaim": "86977",
"qualifiedSplitClaimWithWitness": "87452",
"register": "25379",
"splitBatchClaim": "140264",
"splitBatchClaimWithWitness": "140331",
"splitBatchTransfer": "110587",
"splitBatchWithdrawal": "139819",
"splitClaim": "86275",
"splitClaimWithWitness": "85936",
"splitTransfer": "82732",
"splitWithdrawal": "93702"
"splitBatchClaim": "140758",
"splitBatchClaimWithWitness": "140719",
"splitBatchTransfer": "110582",
"splitBatchWithdrawal": "139745",
"splitClaim": "86751",
"splitClaimWithWitness": "86232",
"splitTransfer": "82438",
"splitWithdrawal": "93362"
}
2 changes: 1 addition & 1 deletion src/lib/ClaimHashLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import {
ExogenousQualifiedSplitBatchMultichainClaimWithWitness
} from "../types/BatchMultichainClaims.sol";

import { TransferComponent, SplitComponent, SplitByIdComponent, BatchClaimComponent, SplitBatchClaimComponent } from "../types/Components.sol";
import { BatchClaimComponent, SplitBatchClaimComponent } from "../types/Components.sol";

import { ResetPeriod } from "../types/ResetPeriod.sol";
import { Scope } from "../types/Scope.sol";
Expand Down
231 changes: 7 additions & 224 deletions src/lib/ClaimProcessorLib.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import { COMPACT_TYPEHASH, BATCH_COMPACT_TYPEHASH, MULTICHAIN_COMPACT_TYPEHASH } from "../types/EIP712Types.sol";
import { SplitComponent, BatchClaimComponent, SplitBatchClaimComponent } from "../types/Components.sol";

import { ComponentLib } from "./ComponentLib.sol";
import { EfficiencyLib } from "./EfficiencyLib.sol";
import { EventLib } from "./EventLib.sol";
import { HashLib } from "./HashLib.sol";
import { IdLib } from "./IdLib.sol";
import { RegistrationLib } from "./RegistrationLib.sol";
import { ValidityLib } from "./ValidityLib.sol";
Expand All @@ -20,13 +19,14 @@ import { ValidityLib } from "./ValidityLib.sol";
* any changes.
*/
library ClaimProcessorLib {
using ComponentLib for bytes32;
using ClaimProcessorLib for uint256;
using ClaimProcessorLib for bytes32;
using ClaimProcessorLib for SplitComponent[];
using EfficiencyLib for bool;
using EfficiencyLib for uint256;
using EfficiencyLib for bytes32;
using EventLib for address;
using HashLib for uint256;
using IdLib for uint256;
using ValidityLib for uint256;
using ValidityLib for uint96;
Expand Down Expand Up @@ -177,33 +177,7 @@ library ClaimProcessorLib {
bytes32 domainSeparator,
function(address, address, uint256, uint256) internal returns (bool) operation
) internal returns (bool) {
// Declare variables for parameters that will be extracted from calldata.
uint256 id;
uint256 allocatedAmount;
SplitComponent[] calldata components;

assembly ("memory-safe") {
// Calculate pointer to claim parameters using provided offset.
let calldataPointerWithOffset := add(calldataPointer, offsetToId)

// Extract resource lock id and allocated amount.
id := calldataload(calldataPointerWithOffset)
allocatedAmount := calldataload(add(calldataPointerWithOffset, 0x20))

// Extract array of split components containing claimant addresses and amounts.
let componentsPtr := add(calldataPointer, calldataload(add(calldataPointerWithOffset, 0x40)))
components.offset := add(0x20, componentsPtr)
components.length := calldataload(componentsPtr)
}

// Validate the claim and extract the sponsor address.
address sponsor = messageHash.validate(id.toAllocatorId(), qualificationMessageHash, calldataPointer, domainSeparator, sponsorDomainSeparator, typehash);

// Verify the resource lock scope is compatible with the provided domain separator.
sponsorDomainSeparator.ensureValidScope(id);

// Process each split component, verifying total amount and executing operations.
return components.verifyAndProcessSplitComponents(sponsor, id, allocatedAmount, operation);
return messageHash.processClaimWithSplitComponents(qualificationMessageHash, calldataPointer, offsetToId, sponsorDomainSeparator, typehash, domainSeparator, operation, validate);
}

/**
Expand Down Expand Up @@ -232,76 +206,7 @@ library ClaimProcessorLib {
bytes32 domainSeparator,
function(address, address, uint256, uint256) internal returns (bool) operation
) internal returns (bool) {
// Declare variables for parameters that will be extracted from calldata.
BatchClaimComponent[] calldata claims;
address claimant;

assembly ("memory-safe") {
// Calculate pointer to claim parameters using provided offset.
let calldataPointerWithOffset := add(calldataPointer, offsetToId)

// Extract array of batch claim components and claimant address.
let claimsPtr := add(calldataPointer, calldataload(calldataPointerWithOffset))
claims.offset := add(0x20, claimsPtr)
claims.length := calldataload(claimsPtr)
claimant := calldataload(add(calldataPointerWithOffset, 0x20))
}

// Extract allocator id from first claim for validation.
uint96 firstAllocatorId = claims[0].id.toAllocatorId();

// Validate the claim and extract the sponsor address.
address sponsor = messageHash.validate(firstAllocatorId, qualificationMessageHash, calldataPointer, domainSeparator, sponsorDomainSeparator, typehash);

// Revert if the batch is empty.
uint256 totalClaims = claims.length;
assembly ("memory-safe") {
if iszero(totalClaims) {
// revert InvalidBatchAllocation()
mstore(0, 0x3a03d3bb)
revert(0x1c, 0x04)
}
}

// Process first claim and initialize error tracking.
// NOTE: many of the bounds checks on these array accesses can be skipped as an optimization
BatchClaimComponent calldata component = claims[0];
uint256 id = component.id;
uint256 amount = component.amount;
uint256 errorBuffer = component.allocatedAmount.allocationExceededOrScopeNotMultichain(amount, id, sponsorDomainSeparator).asUint256();

// Execute transfer or withdrawal for first claim.
operation(sponsor, claimant, id, amount);

unchecked {
// Process remaining claims while accumulating potential errors.
for (uint256 i = 1; i < totalClaims; ++i) {
component = claims[i];
id = component.id;
amount = component.amount;
errorBuffer |= (id.toAllocatorId() != firstAllocatorId).or(component.allocatedAmount.allocationExceededOrScopeNotMultichain(amount, id, sponsorDomainSeparator)).asUint256();

operation(sponsor, claimant, id, amount);
}

// If any errors occurred, identify specific failures and revert.
if (errorBuffer.asBool()) {
for (uint256 i = 0; i < totalClaims; ++i) {
component = claims[i];
component.amount.withinAllocated(component.allocatedAmount);
id = component.id;
sponsorDomainSeparator.ensureValidScope(component.id);
}

assembly ("memory-safe") {
// revert InvalidBatchAllocation()
mstore(0, 0x3a03d3bb)
revert(0x1c, 0x04)
}
}
}

return true;
return messageHash.processClaimWithBatchComponents(qualificationMessageHash, calldataPointer, offsetToId, sponsorDomainSeparator, typehash, domainSeparator, operation, validate);
}

/**
Expand Down Expand Up @@ -330,108 +235,7 @@ library ClaimProcessorLib {
bytes32 domainSeparator,
function(address, address, uint256, uint256) internal returns (bool) operation
) internal returns (bool) {
// Declare variable for SplitBatchClaimComponent array that will be extracted from calldata.
SplitBatchClaimComponent[] calldata claims;

assembly ("memory-safe") {
// Extract array of split batch claim components.
let claimsPtr := add(calldataPointer, calldataload(add(calldataPointer, offsetToId)))
claims.offset := add(0x20, claimsPtr)
claims.length := calldataload(claimsPtr)
}

// Extract allocator id from first claim for validation.
uint96 firstAllocatorId = claims[0].id.toAllocatorId();

// Validate the claim and extract the sponsor address.
address sponsor = messageHash.validate(firstAllocatorId, qualificationMessageHash, calldataPointer, domainSeparator, sponsorDomainSeparator, typehash);

// Initialize tracking variables.
uint256 totalClaims = claims.length;
uint256 errorBuffer = (totalClaims == 0).asUint256();
uint256 id;

unchecked {
// Process each claim component while accumulating potential errors.
for (uint256 i = 0; i < totalClaims; ++i) {
SplitBatchClaimComponent calldata claimComponent = claims[i];
id = claimComponent.id;
errorBuffer |= (id.toAllocatorId() != firstAllocatorId).or(id.scopeNotMultichain(sponsorDomainSeparator)).asUint256();

// Process each split component, verifying total amount and executing operations.
claimComponent.portions.verifyAndProcessSplitComponents(sponsor, id, claimComponent.allocatedAmount, operation);
}

// If any errors occurred, identify specific scope failures and revert.
if (errorBuffer.asBool()) {
for (uint256 i = 0; i < totalClaims; ++i) {
sponsorDomainSeparator.ensureValidScope(claims[i].id);
}

assembly ("memory-safe") {
// revert InvalidBatchAllocation()
mstore(0, 0x3a03d3bb)
revert(0x1c, 0x04)
}
}
}

return true;
}

/**
* @notice Internal function for verifying and processing split components. Ensures that the
* sum of split amounts doesn't exceed the allocated amount, checks for arithmetic overflow,
* and executes the specified operation for each split recipient. Reverts if the total
* claimed amount exceeds the allocation or if arithmetic overflow occurs during summation.
* @param claimants Array of split components specifying recipients and their amounts.
* @param sponsor The address of the claim sponsor.
* @param id The ERC6909 token identifier of the resource lock.
* @param allocatedAmount The total amount allocated for this claim.
* @param operation Function pointer to either _release or _withdraw for executing the claim.
* @return Whether all split components were successfully processed.
*/
function verifyAndProcessSplitComponents(
SplitComponent[] calldata claimants,
address sponsor,
uint256 id,
uint256 allocatedAmount,
function(address, address, uint256, uint256) internal returns (bool) operation
) internal returns (bool) {
// Initialize tracking variables.
uint256 totalClaims = claimants.length;
uint256 spentAmount = 0;
uint256 errorBuffer = (totalClaims == 0).asUint256();

unchecked {
// Process each split component while tracking total amount and checking for overflow.
for (uint256 i = 0; i < totalClaims; ++i) {
SplitComponent calldata component = claimants[i];
uint256 amount = component.amount;

// Track total amount claimed, checking for overflow.
uint256 updatedSpentAmount = amount + spentAmount;
errorBuffer |= (updatedSpentAmount < spentAmount).asUint256();
spentAmount = updatedSpentAmount;

// Execute transfer or withdrawal for the split component.
operation(sponsor, component.claimant, id, amount);
}
}

// Revert if an overflow occurred or if total claimed amount exceeds allocation.
errorBuffer |= (allocatedAmount < spentAmount).asUint256();
assembly ("memory-safe") {
if errorBuffer {
// revert AllocatedAmountExceeded(allocatedAmount, amount);
mstore(0, 0x3078b2f6)
mstore(0x20, allocatedAmount)
mstore(0x40, spentAmount)
revert(0x1c, 0x44)
}
}

return true;
return messageHash.processClaimWithSplitBatchComponents(qualificationMessageHash, calldataPointer, offsetToId, sponsorDomainSeparator, typehash, domainSeparator, operation, validate);
}

/**
Expand Down Expand Up @@ -739,25 +543,4 @@ library ClaimProcessorLib {
) internal returns (bool) {
return messageHash.processSplitBatchClaimWithQualificationAndSponsorDomain(messageHash, calldataPointer, offsetToId, sponsorDomain, typehash, domainSeparator, operation);
}

/**
* @notice Internal pure function for retrieving EIP-712 typehashes where no witness data is
* provided, returning the corresponding typehash based on the index provided. The available
* typehashes are:
* - 0: COMPACT_TYPEHASH
* - 1: BATCH_COMPACT_TYPEHASH
* - 2: MULTICHAIN_COMPACT_TYPEHASH
* @param i The index of the EIP-712 typehash to retrieve.
* @return typehash The corresponding EIP-712 typehash.
*/
function typehashes(uint256 i) internal pure returns (bytes32 typehash) {
assembly ("memory-safe") {
let m := mload(0x40)
mstore(0, COMPACT_TYPEHASH)
mstore(0x20, BATCH_COMPACT_TYPEHASH)
mstore(0x40, MULTICHAIN_COMPACT_TYPEHASH)
typehash := mload(shl(5, i))
mstore(0x40, m)
}
}
}
6 changes: 4 additions & 2 deletions src/lib/ClaimProcessorLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ import {

import { ClaimHashLib } from "./ClaimHashLib.sol";
import { ClaimProcessorLib } from "./ClaimProcessorLib.sol";
import { DomainLib } from "./DomainLib.sol";
import { HashLib } from "./HashLib.sol";
import { EfficiencyLib } from "./EfficiencyLib.sol";
import { FunctionCastLib } from "./FunctionCastLib.sol";
import { HashLib } from "./HashLib.sol";
import { SharedLogic } from "./SharedLogic.sol";
import { ValidityLib } from "./ValidityLib.sol";

Expand Down Expand Up @@ -117,12 +118,13 @@ contract ClaimProcessorLogic is SharedLogic {
using ClaimHashLib for ExogenousQualifiedSplitBatchMultichainClaim;
using ClaimHashLib for ExogenousQualifiedSplitBatchMultichainClaimWithWitness;
using ClaimProcessorLib for uint256;
using DomainLib for uint256;
using HashLib for uint256;
using EfficiencyLib for uint256;
using FunctionCastLib for function(bytes32, uint256, uint256, bytes32, bytes32, function(address, address, uint256, uint256) internal returns (bool)) internal returns (bool);
using FunctionCastLib for function(bytes32, uint256, uint256, bytes32, bytes32, bytes32, function(address, address, uint256, uint256) internal returns (bool)) internal returns (bool);
using FunctionCastLib for function(bytes32, bytes32, uint256, uint256, bytes32, bytes32, function(address, address, uint256, uint256) internal returns (bool)) internal returns (bool);
using FunctionCastLib for function(bytes32, bytes32, uint256, uint256, bytes32, bytes32, bytes32, function(address, address, uint256, uint256) internal returns (bool)) internal returns (bool);
using HashLib for uint256;
using ValidityLib for uint96;
using ValidityLib for uint256;
using ValidityLib for bytes32;
Expand Down
Loading