Skip to content

Commit

Permalink
optimize deposit + register & get under codesize (removed batch permi…
Browse files Browse the repository at this point in the history
…t2 deposit for now)
  • Loading branch information
0age committed Oct 28, 2024
1 parent 4b5062a commit 47c4802
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 395 deletions.
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ solc = '0.8.28'
evm_version='cancun'
via_ir = true
# optimizer_runs = 4_294_967_295
optimizer_runs = 9
optimizer_runs = 200
bytecode_hash = 'none'
src = "src"
out = "out"
Expand Down
63 changes: 31 additions & 32 deletions snapshots/TheCompactTest.json
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
{
"basicTransfer": "57220",
"basicWithdrawal": "60350",
"batchClaim": "112331",
"batchClaimWithWitness": "112988",
"batchTransfer": "82936",
"batchWithdrawal": "101303",
"claim": "60821",
"claimAndWithdraw": "73704",
"claimWithWitness": "60004",
"depositBatchSingleERC20": "67765",
"depositBatchViaPermit2SingleERC20": "107820",
"depositERC20AndURI": "67076",
"depositERC20Basic": "67081",
"depositERC20ViaPermit2AndURI": "98237",
"depositETHAndURI": "26774",
"depositETHBasic": "28237",
"qualifiedBatchClaim": "113658",
"qualifiedBatchClaimWithWitness": "113117",
"qualifiedClaim": "60719",
"qualifiedClaimWithWitness": "59407",
"qualifiedSplitBatchClaim": "141263",
"qualifiedSplitBatchClaimWithWitness": "141228",
"qualifiedSplitClaim": "86947",
"qualifiedSplitClaimWithWitness": "87358",
"splitBatchClaim": "140743",
"splitBatchClaimWithWitness": "140674",
"splitBatchTransfer": "113646",
"splitBatchWithdrawal": "142938",
"splitClaim": "86873",
"splitClaimWithWitness": "86452",
"splitTransfer": "83176",
"splitWithdrawal": "94106"
"basicTransfer": "57231",
"basicWithdrawal": "60321",
"batchClaim": "112342",
"batchClaimWithWitness": "112999",
"batchTransfer": "82862",
"batchWithdrawal": "101233",
"claim": "60835",
"claimAndWithdraw": "73718",
"claimWithWitness": "59909",
"depositBatchSingleERC20": "67728",
"depositERC20AndURI": "67021",
"depositERC20Basic": "67026",
"depositERC20ViaPermit2AndURI": "98015",
"depositETHAndURI": "26694",
"depositETHBasic": "28186",
"qualifiedBatchClaim": "113669",
"qualifiedBatchClaimWithWitness": "113128",
"qualifiedClaim": "60733",
"qualifiedClaimWithWitness": "59312",
"qualifiedSplitBatchClaim": "141215",
"qualifiedSplitBatchClaimWithWitness": "141180",
"qualifiedSplitClaim": "86961",
"qualifiedSplitClaimWithWitness": "87256",
"splitBatchClaim": "140724",
"splitBatchClaimWithWitness": "140655",
"splitBatchTransfer": "113519",
"splitBatchWithdrawal": "142771",
"splitClaim": "86887",
"splitClaimWithWitness": "86379",
"splitTransfer": "83187",
"splitWithdrawal": "94053"
}
416 changes: 274 additions & 142 deletions src/TheCompact.sol

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions src/interfaces/ITheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +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 { CompactCategory } from "../types/CompactCategory.sol";
import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol";
import {
BasicTransfer,
Expand Down Expand Up @@ -120,17 +121,20 @@ interface ITheCompact {
bytes calldata signature
) external returns (uint256 id);

function deposit(
function depositAndRegister(
address token,
uint256 amount,
uint256 nonce,
uint256 deadline,
address depositor,
ISignatureTransfer.TokenPermissions[] calldata permitted,
address allocator,
ResetPeriod resetPeriod,
Scope scope,
address recipient,
uint256 nonce,
uint256 deadline,
bytes32 claimHash,
CompactCategory compactCategory,
string calldata witness,
bytes calldata signature
) external payable returns (uint256[] memory ids);
) external returns (uint256 id);

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

Expand Down
151 changes: 2 additions & 149 deletions src/lib/HashLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,6 @@ import {
MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_THREE,
MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_FOUR,
MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_FIVE,
PERMIT2_DEPOSIT_WITNESS_FRAGMENT_HASH,
PERMIT2_DEPOSIT_WITH_COMPACT_ACTIVATION_TYPEHASH,
PERMIT2_DEPOSIT_WITH_BATCH_COMPACT_ACTIVATION_TYPEHASH,
PERMIT2_DEPOSIT_WITH_MULTICHAIN_COMPACT_ACTIVATION_TYPEHASH,
PERMIT2_BATCH_DEPOSIT_WITH_COMPACT_ACTIVATION_TYPEHASH,
PERMIT2_BATCH_DEPOSIT_WITH_BATCH_COMPACT_ACTIVATION_TYPEHASH,
PERMIT2_BATCH_DEPOSIT_WITH_MULTICHAIN_COMPACT_ACTIVATION_TYPEHASH,
PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_ONE,
PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_TWO,
PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_THREE,
PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FOUR,
PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FIVE,
PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_ONE,
PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_TWO,
PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_THREE,
PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FOUR,
PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FIVE,
PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_SIX,
PERMIT2_ACTIVATION_COMPACT_TYPESTRING_FRAGMENT_ONE,
PERMIT2_ACTIVATION_COMPACT_TYPESTRING_FRAGMENT_TWO,
PERMIT2_ACTIVATION_COMPACT_TYPESTRING_FRAGMENT_THREE,
Expand All @@ -61,7 +43,8 @@ import {
BATCH_COMPACT_BATCH_ACTIVATION_TYPEHASH,
MULTICHAIN_COMPACT_BATCH_ACTIVATION_TYPEHASH,
TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_ONE,
TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO
TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO,
PERMIT2_DEPOSIT_WITNESS_FRAGMENT_HASH
} from "../types/EIP712Types.sol";

import {
Expand Down Expand Up @@ -130,7 +113,6 @@ import {

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

import { ActivatedCompactCategory } from "../types/ActivatedCompactCategory.sol";
import { ResetPeriod } from "../types/ResetPeriod.sol";
import { Scope } from "../types/Scope.sol";

Expand Down Expand Up @@ -929,133 +911,4 @@ library HashLib {
messageHash := keccak256(m, 0xa0)
}
}

function toPermit2DepositAndRegisterTypehashes(ActivatedCompactCategory category, string calldata compactWitnessTypestringFragment)
internal
pure
returns (bytes32 permit2Typehash, bytes32 activationTypehash, bytes32 compactTypehash)
{
assembly ("memory-safe") {
function toTypehash(c, witnessOffset, witnessLength) -> p, a, t {
let m := mload(0x40) // Grab the free memory pointer; memory will be left dirtied

let isBatch := gt(c, 2)
c := sub(c, mul(isBatch, 3))
let indexWords := shl(5, c)

let activationStart

// 1. handle no-witness cases or prepare first witness fragment based on deposit vs batch deposit
let fragmentTwoStart
if iszero(isBatch) {
if iszero(witnessLength) {
mstore(0, PERMIT2_DEPOSIT_WITH_COMPACT_ACTIVATION_TYPEHASH)
mstore(0x20, PERMIT2_DEPOSIT_WITH_BATCH_COMPACT_ACTIVATION_TYPEHASH)
mstore(0x40, PERMIT2_DEPOSIT_WITH_MULTICHAIN_COMPACT_ACTIVATION_TYPEHASH)
p := mload(indexWords)

mstore(0, COMPACT_ACTIVATION_TYPEHASH)
mstore(0x20, BATCH_COMPACT_ACTIVATION_TYPEHASH)
mstore(0x40, MULTICHAIN_COMPACT_ACTIVATION_TYPEHASH)
a := mload(indexWords)

mstore(0, COMPACT_TYPEHASH)
mstore(0x20, BATCH_COMPACT_TYPEHASH)
mstore(0x40, MULTICHAIN_COMPACT_TYPEHASH)
t := mload(indexWords)

mstore(0x40, m)
leave
}

mstore(m, PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_ONE)
mstore(add(m, 0x20), PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_TWO)
mstore(add(m, 0x40), PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_THREE)
mstore(add(m, 0x6d), PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FIVE)
mstore(add(m, 0x60), PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FOUR)
fragmentTwoStart := add(m, 0x8d)
activationStart := add(m, 0x77)
}

if iszero(fragmentTwoStart) {
if iszero(witnessLength) {
mstore(0, PERMIT2_BATCH_DEPOSIT_WITH_COMPACT_ACTIVATION_TYPEHASH)
mstore(0x20, PERMIT2_BATCH_DEPOSIT_WITH_BATCH_COMPACT_ACTIVATION_TYPEHASH)
mstore(0x40, PERMIT2_BATCH_DEPOSIT_WITH_MULTICHAIN_COMPACT_ACTIVATION_TYPEHASH)
p := mload(indexWords)

mstore(0, COMPACT_BATCH_ACTIVATION_TYPEHASH)
mstore(0x20, BATCH_COMPACT_BATCH_ACTIVATION_TYPEHASH)
mstore(0x40, MULTICHAIN_COMPACT_BATCH_ACTIVATION_TYPEHASH)
a := mload(indexWords)

mstore(0, COMPACT_TYPEHASH)
mstore(0x20, BATCH_COMPACT_TYPEHASH)
mstore(0x40, MULTICHAIN_COMPACT_TYPEHASH)
t := mload(indexWords)

mstore(0x40, m)
leave
}

mstore(m, PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_ONE)
mstore(add(m, 0x20), PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_TWO)
mstore(add(m, 0x40), PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_THREE)
mstore(add(m, 0x60), PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FOUR)
mstore(add(m, 0x80), PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_FIVE)
mstore8(add(m, 0xa0), PERMIT2_BATCH_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_SIX)
fragmentTwoStart := add(m, 0xa1)
activationStart := add(m, 0x83)
}

// 2. prepare second witness fragment based on compact category
let fragmentThreeStart
if iszero(c) {
mstore(fragmentTwoStart, PERMIT2_ACTIVATION_COMPACT_TYPESTRING_FRAGMENT_ONE)
mstore(add(fragmentTwoStart, 0x20), PERMIT2_ACTIVATION_COMPACT_TYPESTRING_FRAGMENT_TWO)
mstore(add(fragmentTwoStart, 0x50), PERMIT2_ACTIVATION_COMPACT_TYPESTRING_FRAGMENT_FOUR)
mstore(add(fragmentTwoStart, 0x40), PERMIT2_ACTIVATION_COMPACT_TYPESTRING_FRAGMENT_THREE)
fragmentThreeStart := add(fragmentTwoStart, 0x70)
}

if iszero(sub(c, 1)) {
mstore(fragmentTwoStart, PERMIT2_ACTIVATION_BATCH_COMPACT_TYPESTRING_FRAGMENT_ONE)
mstore(add(fragmentTwoStart, 0x20), PERMIT2_ACTIVATION_BATCH_COMPACT_TYPESTRING_FRAGMENT_TWO)
mstore(add(fragmentTwoStart, 0x5b), PERMIT2_ACTIVATION_BATCH_COMPACT_TYPESTRING_FRAGMENT_FOUR)
mstore(add(fragmentTwoStart, 0x40), PERMIT2_ACTIVATION_BATCH_COMPACT_TYPESTRING_FRAGMENT_THREE)
fragmentThreeStart := add(fragmentTwoStart, 0x7b)
}

if iszero(fragmentThreeStart) {
mstore(fragmentTwoStart, PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_ONE)
mstore(add(fragmentTwoStart, 0x20), PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_TWO)
mstore(add(fragmentTwoStart, 0x40), PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_THREE)
mstore(add(fragmentTwoStart, 0x60), PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_FOUR)
mstore(add(fragmentTwoStart, 0x90), PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_SIX)
mstore(add(fragmentTwoStart, 0x80), PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_FIVE)
fragmentThreeStart := add(fragmentTwoStart, 0xb0)
}

// 3. insert the supplied compact witness
calldatacopy(fragmentThreeStart, witnessOffset, witnessLength)

// 4. insert tokenPermissions
let tokenPermissionsFragmentStart := add(fragmentThreeStart, witnessLength)
mstore(add(tokenPermissionsFragmentStart, 0x0e), TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO)
mstore(tokenPermissionsFragmentStart, TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_ONE)

// 5. derive the permit2 typehash
let totalPayloadSizeWithoutTokenPermissions := sub(tokenPermissionsFragmentStart, m)
p := keccak256(m, add(totalPayloadSizeWithoutTokenPermissions, 0x2e))

// 6. derive the activation typehash
a := keccak256(activationStart, sub(totalPayloadSizeWithoutTokenPermissions, activationStart))

// 7. derive the compact typehash
t := keccak256(fragmentTwoStart, sub(totalPayloadSizeWithoutTokenPermissions, fragmentTwoStart))
}

permit2Typehash, activationTypehash, compactTypehash := toTypehash(category, compactWitnessTypestringFragment.offset, compactWitnessTypestringFragment.length)
}
}
}
7 changes: 0 additions & 7 deletions src/lib/IdLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { MetadataLib } from "./MetadataLib.sol";
import { EfficiencyLib } from "./EfficiencyLib.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";
import { CompactCategory } from "../types/CompactCategory.sol";
import { ActivatedCompactCategory } from "../types/ActivatedCompactCategory.sol";

library IdLib {
using IdLib for uint96;
Expand Down Expand Up @@ -194,12 +193,6 @@ library IdLib {
return (msg.sender == allocator).or(allocator.code.length > 0).or(proof.length == 86 && (proof[0] == 0xff).and(allocator == address(uint160(uint256(keccak256(proof))))));
}

function toActivated(CompactCategory category, bool batch) internal pure returns (ActivatedCompactCategory activatedCategory) {
assembly ("memory-safe") {
activatedCategory := add(category, mul(batch, 3))
}
}

function register(address allocator) internal returns (uint96 allocatorId) {
allocatorId = allocator.usingAllocatorId();

Expand Down
11 changes: 0 additions & 11 deletions src/types/ActivatedCompactCategory.sol

This file was deleted.

Loading

0 comments on commit 47c4802

Please sign in to comment.