Skip to content

Commit

Permalink
progress on deposit+register+claim — still hitting a signature error
Browse files Browse the repository at this point in the history
  • Loading branch information
0age committed Oct 28, 2024
1 parent 888e55f commit 76a37df
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 19 deletions.
25 changes: 12 additions & 13 deletions src/TheCompact.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ import {
PERMIT2_DEPOSIT_WITNESS_FRAGMENT_HASH,
PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_ONE,
PERMIT2_DEPOSIT_WITH_ACTIVATION_TYPESTRING_FRAGMENT_TWO,
TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_ONE,
TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO,
TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_ONE,
TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_TWO,
COMPACT_ACTIVATION_TYPEHASH,
BATCH_COMPACT_ACTIVATION_TYPEHASH,
MULTICHAIN_COMPACT_ACTIVATION_TYPEHASH,
Expand Down Expand Up @@ -426,8 +426,8 @@ contract TheCompact is ITheCompact, ERC6909, Tstorish {
if iszero(witnessLength) {
let indexWords := shl(5, c)

mstore(add(categorySpecificEnd, 0x0e), TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO)
mstore(sub(categorySpecificEnd, 1), TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_ONE)
mstore(add(categorySpecificEnd, 0x0e), TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_TWO)
mstore(sub(categorySpecificEnd, 1), TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_ONE)
mstore(memoryLocation, sub(add(categorySpecificEnd, 0x2e), memoryOffset))

let m := mload(0x40)
Expand All @@ -451,8 +451,8 @@ contract TheCompact is ITheCompact, ERC6909, Tstorish {

// 4. insert tokenPermissions
let tokenPermissionsFragmentStart := add(categorySpecificEnd, witnessLength)
mstore(add(tokenPermissionsFragmentStart, 0x0f), TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO)
mstore(tokenPermissionsFragmentStart, TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_ONE)
mstore(add(tokenPermissionsFragmentStart, 0x0f), TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_TWO)
mstore(tokenPermissionsFragmentStart, TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_ONE)
mstore(memoryLocation, sub(add(tokenPermissionsFragmentStart, 0x2f), memoryOffset))

categorySpecificEnd := add(tokenPermissionsFragmentStart, 1)
Expand All @@ -479,20 +479,19 @@ contract TheCompact is ITheCompact, ERC6909, Tstorish {
let permit2WitnessOffset := add(m, 0x160)
let activationTypehash
activationTypehash, compactTypehash := writeWitnessAndGetTypehashes(permit2WitnessOffset, compactCategory, witness.offset, witness.length)
let signatureOffset := and(add(mload(permit2WitnessOffset), 0x5f), not(0x1f))
mstore(add(m, 0x140), signatureOffset)
signatureOffset := add(m, add(signatureOffset, 0x20))
let signatureOffsetValue := and(add(mload(permit2WitnessOffset), 0x17f), not(0x1f))
mstore(add(m, 0x140), signatureOffsetValue)
let signatureOffset := add(m, add(signatureOffsetValue, 0x20))
mstore(signatureOffset, signatureLength)
calldatacopy(add(signatureOffset, 0x20), signature.offset, signatureLength)

mstore(0, activationTypehash)
mstore(0x20, id)
mstore(0x40, claimHash)
mstore(add(m, 0x100), keccak256(0, 0x60))
mstore(0x40, m)

mstore(signatureOffset, signatureLength)
calldatacopy(add(signatureOffset, 0x20), signature.offset, signatureLength)

if iszero(and(isPermit2Deployed, call(gas(), permit2, 0, add(m, 0x1c), add(0x24, add(signatureOffset, signatureLength)), 0, 0))) {
if iszero(and(isPermit2Deployed, call(gas(), permit2, 0, add(m, 0x1c), add(0x24, add(signatureOffsetValue, signatureLength)), 0, 0))) {
// bubble up if the call failed and there's data
// NOTE: consider evaluating remaining gas to protect against revert bombing
if returndatasize() {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/HashLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ import {
COMPACT_BATCH_ACTIVATION_TYPEHASH,
BATCH_COMPACT_BATCH_ACTIVATION_TYPEHASH,
MULTICHAIN_COMPACT_BATCH_ACTIVATION_TYPEHASH,
TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_ONE,
TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO,
TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_ONE,
TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_TWO,
PERMIT2_DEPOSIT_WITNESS_FRAGMENT_HASH
} from "../types/EIP712Types.sol";

Expand Down
8 changes: 4 additions & 4 deletions src/types/EIP712Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ bytes32 constant PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_FIVE
// uint128(abi.decode(bytes("] idsAndAmounts,"), (bytes16)))
uint128 constant PERMIT2_ACTIVATION_MULTICHAIN_COMPACT_TYPESTRING_FRAGMENT_SIX = 0x5d20696473416e64416d6f756e74732c;

// abi.decode(bytes("TokenPermissions(address token,u"), (bytes32))
bytes32 constant TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_ONE = 0x546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75;
// abi.decode(bytes(")TokenPermissions(address token,"), (bytes32))
bytes32 constant TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_ONE = 0x29546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c;

// uint112(abi.decode(bytes("int256 amount)"), (bytes14)))
uint112 constant TOKEN_PERMISSIONS_TYPSTRING_FRAGMENT_TWO = 0x696e7432353620616d6f756e7429;
// uint120(abi.decode(bytes("uint256 amount)"), (bytes15)))
uint120 constant TOKEN_PERMISSIONS_TYPESTRING_FRAGMENT_TWO = 0x75696e7432353620616d6f756e7429;
84 changes: 84 additions & 0 deletions test/TheCompact.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MockERC20 } from "../lib/solady/test/utils/mocks/MockERC20.sol";
import { Compact, BatchCompact, Segment } from "../src/types/EIP712Types.sol";
import { ResetPeriod } from "../src/types/ResetPeriod.sol";
import { Scope } from "../src/types/Scope.sol";
import { CompactCategory } from "../src/types/CompactCategory.sol";
import { ISignatureTransfer } from "permit2/src/interfaces/ISignatureTransfer.sol";

import { HashLib } from "../src/lib/HashLib.sol";
Expand Down Expand Up @@ -341,6 +342,89 @@ contract TheCompactTest is Test {
assert(bytes(theCompact.tokenURI(id)).length > 0);
}

function test_depositAndRegisterViaPermit2ThenClaim() public {
address recipient = 0x1111111111111111111111111111111111111111;
ResetPeriod resetPeriod = ResetPeriod.TenMinutes;
Scope scope = Scope.Multichain;
uint256 amount = 1e18;
uint256 nonce = 0;
uint256 deadline = block.timestamp + 1000;
uint256 expires = block.timestamp + 1000;
address claimant = 0x1111111111111111111111111111111111111111;
address arbiter = 0x2222222222222222222222222222222222222222;

vm.prank(allocator);
uint96 allocatorId = theCompact.__registerAllocator(allocator, "");

bytes32 domainSeparator = keccak256(abi.encode(permit2EIP712DomainHash, keccak256(bytes("Permit2")), block.chainid, address(permit2)));

assertEq(domainSeparator, EIP712(permit2).DOMAIN_SEPARATOR());

bytes32 typehash = keccak256("Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount)");

uint256 id = (uint256(scope) << 255) | (uint256(resetPeriod) << 252) | (uint256(allocatorId) << 160) | uint256(uint160(address(token)));

bytes32 claimHash = keccak256(abi.encode(typehash, arbiter, swapper, nonce, expires, id, amount));

bytes32 digest = keccak256(
abi.encodePacked(
bytes2(0x1901),
domainSeparator,
keccak256(
abi.encode(
keccak256(
"PermitWitnessTransferFrom(TokenPermissions permitted,address spender,uint256 nonce,uint256 deadline,Activation(uint256 id,Compact compact)Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount)TokenPermissions(address token,uint256 amount)"
),
keccak256(abi.encode(keccak256("TokenPermissions(address token,uint256 amount)"), address(token), amount)),
address(theCompact), // spender
nonce,
deadline,
keccak256(
abi.encode(
keccak256("Activation(uint256 id,Compact compact)Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount)"), id, claimHash
)
)
)
)
)
);

(bytes32 r, bytes32 vs) = vm.signCompact(swapperPrivateKey, digest);
bytes memory signature = abi.encodePacked(r, vs);

uint256 returnedId = theCompact.depositAndRegister(address(token), amount, nonce, deadline, swapper, allocator, resetPeriod, scope, claimHash, CompactCategory.Compact, "", signature);
vm.snapshotGasLastCall("depositAndRegisterViaPermit2");
assertEq(returnedId, id);

(address derivedToken, address derivedAllocator, ResetPeriod derivedResetPeriod, Scope derivedScope) = theCompact.getLockDetails(id);
assertEq(derivedToken, address(token));
assertEq(derivedAllocator, allocator);
assertEq(uint256(derivedResetPeriod), uint256(resetPeriod));
assertEq(uint256(derivedScope), uint256(scope));

assertEq(token.balanceOf(address(theCompact)), amount);
assertEq(theCompact.balanceOf(recipient, id), amount);

digest = keccak256(abi.encodePacked(bytes2(0x1901), theCompact.DOMAIN_SEPARATOR(), claimHash));

bytes memory sponsorSignature = "";

(r, vs) = vm.signCompact(allocatorPrivateKey, digest);
bytes memory allocatorSignature = abi.encodePacked(r, vs);

BasicClaim memory claim = BasicClaim(allocatorSignature, sponsorSignature, swapper, nonce, expires, id, amount, claimant, amount);

vm.prank(arbiter);
(bool status) = theCompact.claim(claim);
vm.snapshotGasLastCall("claim");
assert(status);

assertEq(address(theCompact).balance, amount);
assertEq(claimant.balance, 0);
assertEq(theCompact.balanceOf(swapper, id), 0);
assertEq(theCompact.balanceOf(claimant, id), amount);
}

/* TODO: add this test back once there's room for batch permit2 deposits again
function test_depositBatchViaPermit2SingleERC20() public {
address recipient = 0x1111111111111111111111111111111111111111;
Expand Down

0 comments on commit 76a37df

Please sign in to comment.