Skip to content

Commit

Permalink
Merge pull request #8 from Uniswap/squeeze-everything-in
Browse files Browse the repository at this point in the history
squeeze everything in!
  • Loading branch information
0age authored Oct 30, 2024
2 parents dea985b + 8ce5938 commit f5adf00
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 104 deletions.
68 changes: 36 additions & 32 deletions snapshots/TheCompactTest.json
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
{
"basicTransfer": "56751",
"basicWithdrawal": "59775",
"basicTransfer": "56817",
"basicWithdrawal": "59797",
"batchClaim": "111809",
"batchClaimRegisteredWithDeposit": "111809",
"batchClaimRegisteredWithDepositWithWitness": "112505",
"batchClaimWithWitness": "112499",
"batchDepositAndRegisterViaPermit2": "221852",
"batchDepositAndRegisterWithWitnessViaPermit2": "221830",
"claim": "56934",
"claimAndWithdraw": "73203",
"claimWithWitness": "59399",
"depositAndRegisterViaPermit2": "124230",
"depositBatchSingleERC20": "67780",
"depositBatchSingleNative": "28083",
"depositBatchViaPermit2NativeAndERC20": "129518",
"depositBatchViaPermit2SingleERC20": "104645",
"depositERC20AndURI": "67073",
"depositERC20Basic": "67080",
"depositERC20ViaPermit2AndURI": "98277",
"depositETHAndURI": "26733",
"depositETHBasic": "28252",
"qualifiedBatchClaim": "113183",
"qualifiedBatchClaimWithWitness": "112625",
"batchClaimRegisteredWithDepositWithWitness": "112571",
"batchClaimWithWitness": "112565",
"batchDepositAndRegisterViaPermit2": "221878",
"batchDepositAndRegisterWithWitnessViaPermit2": "221856",
"batchTransfer": "81517",
"batchWithdrawal": "99932",
"claim": "56956",
"claimAndWithdraw": "73247",
"claimWithWitness": "59421",
"depositAndRegisterViaPermit2": "124248",
"depositBatchSingleERC20": "67846",
"depositBatchSingleNative": "28149",
"depositBatchViaPermit2NativeAndERC20": "129570",
"depositBatchViaPermit2SingleERC20": "104724",
"depositERC20AndURI": "67095",
"depositERC20Basic": "67124",
"depositERC20ViaPermit2AndURI": "98312",
"depositETHAndURI": "26755",
"depositETHBasic": "28318",
"qualifiedBatchClaim": "113227",
"qualifiedBatchClaimWithWitness": "112691",
"qualifiedClaim": "60215",
"qualifiedClaimWithWitness": "58777",
"qualifiedSplitBatchClaim": "140849",
"qualifiedSplitBatchClaimWithWitness": "140819",
"qualifiedSplitClaim": "86458",
"qualifiedSplitClaimWithWitness": "86780",
"register": "25335",
"splitBatchClaim": "140333",
"splitBatchClaimWithWitness": "140275",
"splitBatchTransfer": "113034",
"splitBatchWithdrawal": "142264",
"splitClaim": "86381",
"splitClaimWithWitness": "85862"
"qualifiedSplitBatchClaim": "140893",
"qualifiedSplitBatchClaimWithWitness": "140885",
"qualifiedSplitClaim": "86502",
"qualifiedSplitClaimWithWitness": "86846",
"register": "25357",
"splitBatchClaim": "140377",
"splitBatchClaimWithWitness": "140341",
"splitBatchTransfer": "110592",
"splitBatchWithdrawal": "139800",
"splitClaim": "86425",
"splitClaimWithWitness": "85906",
"splitTransfer": "82729",
"splitWithdrawal": "93639"
}
80 changes: 40 additions & 40 deletions src/TheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,13 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
using ValidityLib for bytes32;

function deposit(address allocator) external payable returns (uint256 id) {
id = address(0).toIdIfRegistered(Scope.Multichain, ResetPeriod.TenMinutes, allocator);

_deposit(msg.sender, id, msg.value);
id = _performBasicNativeTokenDeposit(allocator);
}

function depositAndRegister(address allocator, bytes32 claimHash, bytes32 typehash) external payable returns (uint256 id) {
id = address(0).toIdIfRegistered(Scope.Multichain, ResetPeriod.TenMinutes, allocator);

_deposit(msg.sender, id, msg.value);
id = _performBasicNativeTokenDeposit(allocator);

_register(msg.sender, claimHash, typehash, 0x258);
_registerWithDefaults(claimHash, typehash);
}

function deposit(address token, address allocator, uint256 amount) external returns (uint256) {
Expand All @@ -86,7 +82,7 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
function depositAndRegister(address token, address allocator, uint256 amount, bytes32 claimHash, bytes32 typehash) external returns (uint256 id) {
id = _performBasicERC20Deposit(token, allocator, amount);

_register(msg.sender, claimHash, typehash, 0x258);
_registerWithDefaults(claimHash, typehash);
}

function deposit(address allocator, ResetPeriod resetPeriod, Scope scope, address recipient) external payable returns (uint256 id) {
Expand Down Expand Up @@ -123,15 +119,15 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
uint256, // nonce
uint256, // deadline
address, // depositor
address allocator,
ResetPeriod resetPeriod,
Scope scope,
address, // allocator
ResetPeriod, // resetPeriod
Scope, //scope
address recipient,
bytes calldata signature
) external returns (uint256) {
bytes32 witness = _deriveCompactDepositWitnessHash(0xa4);
bytes32 witness = _deriveCompactDepositWitnessHash(uint256(0xa4).asStubborn());

(uint256 id, uint256 initialBalance, uint256 m, uint256 typestringMemoryLocation) = _setReentrancyLockAndStartPreparingPermit2Call(token, allocator, resetPeriod, scope);
(uint256 id, uint256 initialBalance, uint256 m, uint256 typestringMemoryLocation) = _setReentrancyLockAndStartPreparingPermit2Call(token);

_insertCompactDepositTypestringAt(typestringMemoryLocation);

Expand All @@ -154,15 +150,15 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
uint256, // nonce
uint256, // deadline
address depositor, // also recipient
address allocator,
address, // allocator
ResetPeriod resetPeriod,
Scope scope,
Scope, //scope
bytes32 claimHash,
CompactCategory compactCategory,
string calldata witness,
bytes calldata signature
) external returns (uint256) {
(uint256 id, uint256 initialBalance, uint256 m, uint256 typestringMemoryLocation) = _setReentrancyLockAndStartPreparingPermit2Call(token, allocator, resetPeriod, scope);
(uint256 id, uint256 initialBalance, uint256 m, uint256 typestringMemoryLocation) = _setReentrancyLockAndStartPreparingPermit2Call(token);

(bytes32 activationTypehash, bytes32 compactTypehash) = _writeWitnessAndGetTypehashes(typestringMemoryLocation, compactCategory, witness, bool(false).asStubborn());

Expand All @@ -189,18 +185,18 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
ISignatureTransfer.TokenPermissions[] calldata permitted,
uint256, // nonce
uint256, // deadline
address allocator,
ResetPeriod resetPeriod,
Scope scope,
address, // allocator
ResetPeriod, // resetPeriod
Scope, //scope
address recipient,
bytes calldata signature
) external payable returns (uint256[] memory ids) {
uint256 totalTokensLessInitialNative;
bool firstUnderlyingTokenIsNative;
uint256[] memory initialTokenBalances;
(totalTokensLessInitialNative, firstUnderlyingTokenIsNative, ids, initialTokenBalances) = _preprocessAndPerformInitialNativeDeposit(permitted, allocator, resetPeriod, scope, recipient);
(totalTokensLessInitialNative, firstUnderlyingTokenIsNative, ids, initialTokenBalances) = _preprocessAndPerformInitialNativeDeposit(permitted, recipient);

bytes32 witness = _deriveCompactDepositWitnessHash(0x84);
bytes32 witness = _deriveCompactDepositWitnessHash(uint256(0x84).asStubborn());

(uint256 m, uint256 typestringMemoryLocation) = _beginPreparingBatchDepositPermit2Calldata(totalTokensLessInitialNative, firstUnderlyingTokenIsNative);

Expand All @@ -211,7 +207,7 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
uint256 signatureOffsetValue;
assembly ("memory-safe") {
mstore(add(m, 0x80), witness)
signatureOffsetValue := add(0x220, mul(totalTokensLessInitialNative, 0x80))
signatureOffsetValue := add(0x220, shl(7, totalTokensLessInitialNative))
}

_writeSignatureAndPerformPermit2Call(m, uint256(0xc0).asStubborn(), signatureOffsetValue, signature);
Expand All @@ -224,16 +220,16 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
ISignatureTransfer.TokenPermissions[] calldata permitted,
uint256, // nonce
uint256, // deadline
address allocator,
address, // allocator
ResetPeriod resetPeriod,
Scope scope,
Scope, //scope
bytes32 claimHash,
CompactCategory compactCategory,
string calldata witness,
bytes calldata signature
) external payable returns (uint256[] memory) {
(uint256 totalTokensLessInitialNative, bool firstUnderlyingTokenIsNative, uint256[] memory ids, uint256[] memory initialTokenBalances) =
_preprocessAndPerformInitialNativeDeposit(permitted, allocator, resetPeriod, scope, depositor);
_preprocessAndPerformInitialNativeDeposit(permitted, depositor);

uint256 idsHash;
assembly ("memory-safe") {
Expand All @@ -249,8 +245,8 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
uint256 signatureOffsetValue;
assembly ("memory-safe") {
let witnessLength := witness.length
let totalWitnessMemoryOffset := and(add(add(0xf3, add(witnessLength, iszero(iszero(witnessLength)))), add(mul(eq(compactCategory, 1), 0x0b), mul(eq(compactCategory, 2), 0x40))), not(0x1f))
signatureOffsetValue := add(add(0x180, mul(totalTokensLessInitialNative, 0x80)), totalWitnessMemoryOffset)
let totalWitnessMemoryOffset := and(add(add(0xf3, add(witnessLength, iszero(iszero(witnessLength)))), add(mul(eq(compactCategory, 1), 0x0b), shl(6, eq(compactCategory, 2)))), not(0x1f))
signatureOffsetValue := add(add(0x180, shl(7, totalTokensLessInitialNative)), totalWitnessMemoryOffset)
}

_writeSignatureAndPerformPermit2Call(m, uint256(0xc0).asStubborn(), signatureOffsetValue, signature);
Expand All @@ -270,7 +266,6 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
return _processBasicTransfer(withdrawal, _withdraw);
}

/*
function allocatedTransfer(SplitTransfer calldata transfer) external returns (bool) {
return _processSplitTransfer(transfer, _release);
}
Expand All @@ -286,7 +281,6 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
function allocatedWithdrawal(BatchTransfer calldata withdrawal) external returns (bool) {
return _processBatchTransfer(withdrawal, _withdraw);
}
*/

function allocatedTransfer(SplitBatchTransfer calldata transfer) external returns (bool) {
return _processSplitBatchTransfer(transfer, _release);
Expand All @@ -307,7 +301,7 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
sstore(cutoffTimeSlotLocation, withdrawableAt)
}

emit ForcedWithdrawalEnabled(msg.sender, id, withdrawableAt);
_emitForcedWithdrawalStatusUpdatedEvent(id, withdrawableAt);
}

function disableForcedWithdrawal(uint256 id) external returns (bool) {
Expand All @@ -325,21 +319,17 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
sstore(cutoffTimeSlotLocation, 0)
}

emit ForcedWithdrawalDisabled(msg.sender, id);
_emitForcedWithdrawalStatusUpdatedEvent(id, uint256(0).asStubborn());

return true;
}

function forcedWithdrawal(uint256 id, address recipient, uint256 amount) external returns (bool) {
uint256 cutoffTimeSlotLocation = _getCutoffTimeSlot(msg.sender, id);

uint256 withdrawableAt;
assembly ("memory-safe") {
withdrawableAt := sload(cutoffTimeSlotLocation)
}

if ((withdrawableAt == 0).or(withdrawableAt > block.timestamp)) {
assembly ("memory-safe") {
let withdrawableAt := sload(cutoffTimeSlotLocation)
if or(iszero(withdrawableAt), gt(withdrawableAt, timestamp())) {
// revert PrematureWithdrawal(id)
mstore(0, 0x9287bcb0)
mstore(0x20, id)
Expand Down Expand Up @@ -369,9 +359,19 @@ contract TheCompact is ITheCompact, ClaimProcessor, ERC6909 {
msg.sender.usingAllocatorId().mustHaveARegisteredAllocator();

unchecked {
uint256 noncesLength = nonces.length;
for (uint256 i = 0; i < noncesLength; ++i) {
nonces[i].consumeNonceAsAllocator(msg.sender);
uint256 i;

assembly ("memory-safe") {
i := nonces.offset
}

uint256 end = i + (nonces.length << 5);
uint256 nonce;
for (; i < end; i += 0x20) {
assembly ("memory-safe") {
nonce := calldataload(i)
}
nonce.consumeNonceAsAllocator(msg.sender);
}
}

Expand Down
5 changes: 1 addition & 4 deletions src/interfaces/ITheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import { BatchTransfer, SplitBatchTransfer } from "../types/BatchClaims.sol";
*/
interface ITheCompact {
event Claim(address indexed sponsor, address indexed allocator, address indexed arbiter, bytes32 claimHash);
event ForcedWithdrawalEnabled(address indexed account, uint256 indexed id, uint256 withdrawableAt);
event ForcedWithdrawalDisabled(address indexed account, uint256 indexed id);
event ForcedWithdrawalStatusUpdated(address indexed account, uint256 indexed id, bool activating, uint256 withdrawableAt);
event CompactRegistered(address indexed sponsor, bytes32 claimHash, bytes32 typehash, uint256 expires);
event AllocatorRegistered(uint96 allocatorId, address allocator);

Expand Down Expand Up @@ -89,15 +88,13 @@ interface ITheCompact {

function allocatedWithdrawal(BasicTransfer calldata withdrawal) external returns (bool);

/*
function allocatedTransfer(SplitTransfer calldata transfer) external returns (bool);

function allocatedWithdrawal(SplitTransfer calldata withdrawal) external returns (bool);

function allocatedTransfer(BatchTransfer calldata transfer) external returns (bool);

function allocatedWithdrawal(BatchTransfer calldata withdrawal) external returns (bool);
*/

function allocatedTransfer(SplitBatchTransfer calldata transfer) external returns (bool);

Expand Down
11 changes: 0 additions & 11 deletions src/lib/FunctionCastLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2003,17 +2003,6 @@ library FunctionCastLib {
}
}

// NOTE: the id field needs to be at the exact same struct offset for this to work!
function usingSplitByIdComponent(function (TransferComponent[] memory, uint256) internal returns (address) fnIn)
internal
pure
returns (function (SplitByIdComponent[] memory, uint256) internal returns (address) fnOut)
{
assembly ("memory-safe") {
fnOut := fnIn
}
}

function usingClaimWithWitness(function (bytes32, BasicClaim calldata, address) internal view fnIn)
internal
pure
Expand Down
6 changes: 5 additions & 1 deletion src/lib/IdLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { EfficiencyLib } from "./EfficiencyLib.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";
import { CompactCategory } from "../types/CompactCategory.sol";

import { EfficientHashLib } from "solady/utils/EfficientHashLib.sol";

library IdLib {
using IdLib for uint96;
using IdLib for uint256;
Expand All @@ -23,6 +25,7 @@ library IdLib {
using EfficiencyLib for ResetPeriod;
using EfficiencyLib for Scope;
using SignatureCheckerLib for address;
using EfficientHashLib for bytes;

error NoAllocatorRegistered(uint96 allocatorId);
error AllocatorAlreadyRegistered(uint96 allocatorId, address allocator);
Expand Down Expand Up @@ -58,6 +61,7 @@ library IdLib {
function toIdIfRegistered(address token, Scope scope, ResetPeriod resetPeriod, address allocator) internal view returns (uint256 id) {
uint96 allocatorId = allocator.usingAllocatorId();
allocatorId.mustHaveARegisteredAllocator();

id = ((scope.asUint256() << 255) | (resetPeriod.asUint256() << 252) | (allocatorId.asUint256() << 160) | token.asUint256());
}

Expand Down Expand Up @@ -92,7 +96,7 @@ library IdLib {
}

function canBeRegistered(address allocator, bytes calldata proof) internal view returns (bool) {
return (msg.sender == allocator).or(allocator.code.length > 0).or(proof.length == 86 && (proof[0] == 0xff).and(allocator == address(uint160(uint256(keccak256(proof))))));
return (msg.sender == allocator).or(allocator.code.length > 0).or(proof.length == 86 && (proof[0] == 0xff).and(allocator == address(uint160(uint256(proof.hashCalldata())))));
}

function toAllocator(uint256 id) internal view returns (address allocator) {
Expand Down
Loading

0 comments on commit f5adf00

Please sign in to comment.